ROSE 0.11.145.317
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 else if (is_Fortran_language())
11389 {
11390 if (func1->get_name() == func2->get_name())
11391 result = true;
11392 }
11393 else
11394 {
11395 cout<<"Error: SageInterface::isSameFunction(): unhandled language"<<endl;
11396 ROSE_ABORT();
11397 }
11398
11399 } // not identical
11400 return result;
11401 } // isSameFunction()
11402
11405{
11406 bool result =false;
11407 ROSE_ASSERT(stmt != NULL);
11408 SgScopeStatement* p_scope = stmt->get_scope();
11409 ROSE_ASSERT(p_scope != NULL);
11410#if 0
11411 if (p_scope->containsOnlyDeclarations())
11412 {
11413 SgDeclarationStatementPtrList stmtlist= p_scope->getDeclarationList ()
11414 if (stmtlist[stmtlist.size()-1] == stmt)
11415 result = true;
11416 }
11417 else
11418 {
11419 SgStatementPtrList stmtlist= p_scope->getStatementList ();
11420 if (stmtlist[stmtlist.size()-1] == stmt)
11421 result = true;
11422 }
11423#endif
11424 SgStatementPtrList stmtlist= p_scope->generateStatementList ();
11425 if (stmtlist[stmtlist.size()-1] == stmt)
11426 result = true;
11427
11428 return result;
11429}
11430
11431#ifndef USE_ROSE
11432//-----------------------------------------------
11433// Remove original expression trees from expressions, so you can change
11434// the value and have it unparsed correctly.
11436 struct Visitor: public AstSimpleProcessing {
11437 virtual void visit(SgNode* n) {
11438 SgValueExp* valueExp = isSgValueExp(n);
11439 if (valueExp != NULL) {
11440 valueExp->set_originalExpressionTree(NULL);
11441 }
11442 else {
11443 SgCastExp* cast_exp = isSgCastExp(n);
11444 if (cast_exp != NULL) {
11445 cast_exp->set_originalExpressionTree(NULL);
11446 }
11447 }
11448 }
11449 };
11450 Visitor().traverse(top, preorder);
11451}
11452#endif
11453
11455 while (s && !isSgSwitchStatement(s)) {
11456 s = isSgStatement(s->get_parent());
11457 }
11458 ROSE_ASSERT (s);
11459 return isSgSwitchStatement(s);
11460}
11461
11464 while (s && !isSgOmpClauseBodyStatement(s)) {
11465 s = isSgStatement(s->get_parent());
11466 }
11467 // ROSE_ASSERT (s); // s is allowed to be NULL.
11468 if (s==NULL)
11469 return NULL;
11470 return isSgOmpClauseBodyStatement(s);
11471}
11472
11473
11474SgScopeStatement* SageInterface::findEnclosingLoop(SgStatement* s, const std::string& label, bool stopOnSwitches) {
11475 /* label can represent a fortran label or a java label provided as a label in a continue/break statement */
11476 for (; s; s = isSgStatement(s->get_parent())) {
11477 SgScopeStatement* sc = isSgScopeStatement(s);
11478 // Need to check for empty label as for java we must detect the
11479 // innermost labeled statement and skip everything in between
11480 switch (s->variantT()) {
11481 case V_SgDoWhileStmt: {
11482 if (label.empty()) {
11483 return sc;
11484 }
11485 break;
11486 }
11487 case V_SgForStatement: {
11488 if (label.empty()) {
11489 return sc;
11490 }
11491 break;
11492 }
11493 case V_SgFortranDo:
11494 case V_SgFortranNonblockedDo: {
11495 if (label.empty() ||
11496 label == isSgFortranDo(sc)->get_string_label()) {
11497 return sc;
11498 }
11499 break;
11500 }
11501 case V_SgWhileStmt: {
11502 if (label.empty() ||
11503 label == isSgWhileStmt(sc)->get_string_label()) {
11504 return sc;
11505 }
11506 break;
11507 }
11508 case V_SgSwitchStatement: {
11509 if (stopOnSwitches) return sc;
11510 break;
11511 }
11512 case V_SgJavaForEachStatement: {
11513 if (label.empty()) {
11514 return sc;
11515 }
11516 break;
11517 }
11518 case V_SgJavaLabelStatement: {
11519 if (label.empty() ||
11520 label == isSgJavaLabelStatement(sc)->get_label().getString()) {
11521 return sc;
11522 }
11523 break;
11524 }
11525 default: continue;
11526 }
11527 }
11528 return NULL;
11529}
11530
11531#ifndef USE_ROSE
11533{
11534 class RemoveJumpsToNextStatementVisitor: public AstSimpleProcessing {
11535 public:
11536 virtual void visit(SgNode* n) {
11537 if (isSgBasicBlock(n)) {
11538 SgBasicBlock* bb = isSgBasicBlock(n);
11539 bool changes = true;
11540 while (changes) {
11541 changes = false;
11542 for (SgStatementPtrList::iterator i = bb->get_statements().begin();
11543 i != bb->get_statements().end(); ++i) {
11544 if (isSgGotoStatement(*i)) {
11545 SgGotoStatement* gs = isSgGotoStatement(*i);
11546 SgStatementPtrList::iterator inext = i;
11547 ++inext;
11548 if (inext == bb->get_statements().end())
11549 continue;
11550 if (!isSgLabelStatement(*inext))
11551 continue;
11552 SgLabelStatement* ls = isSgLabelStatement(*inext);
11553 if (gs->get_label() == ls) {
11554 changes = true;
11555 bb->get_statements().erase(i);
11556 break;
11557 }
11558 }
11559 }
11560 }
11561 }
11562 }
11563 };
11564
11565 RemoveJumpsToNextStatementVisitor().traverse(top, postorder);
11566
11567}
11568#endif
11569
11570// special purpose remove for AST transformation/optimization from astInliner, don't use it otherwise.
11572 // assert (LowLevelRewrite::isRemovableStatement(*i));
11573 SgStatement* parent = isSgStatement(stmt->get_parent());
11574 ROSE_ASSERT (parent);
11575 SgBasicBlock* bb = isSgBasicBlock(parent);
11576 SgForInitStatement* fis = isSgForInitStatement(parent);
11577 if (bb || fis) {
11578 ROSE_ASSERT (bb || fis);
11579 SgStatementPtrList& siblings =
11580 (bb ? bb->get_statements() : fis->get_init_stmt());
11581 SgStatementPtrList::iterator j =
11582 std::find(siblings.begin(), siblings.end(), stmt);
11583 ROSE_ASSERT (j != siblings.end());
11584 siblings.erase(j);
11585 // LowLevelRewrite::remove(*i);
11586 } else {
11587 parent->replace_statement(stmt, new SgNullStatement(TRANS_FILE));
11588 }
11589}
11590
11591
11592#ifndef USE_ROSE
11593std::set<SgLabelStatement*> SageInterface::findUnusedLabels (SgNode* top)
11594{
11595 class FindUsedAndAllLabelsVisitor: public AstSimpleProcessing {
11596 SgLabelStatementPtrSet& used;
11597 SgLabelStatementPtrSet& all;
11598
11599 public:
11600 FindUsedAndAllLabelsVisitor(SgLabelStatementPtrSet& used,
11601 SgLabelStatementPtrSet& all):
11602 used(used), all(all) {}
11603
11604 virtual void visit(SgNode* n) {
11605 if (isSgGotoStatement(n)) {
11606 used.insert(isSgGotoStatement(n)->get_label());
11607 }
11608 if (isSgLabelStatement(n)) {
11609 all.insert(isSgLabelStatement(n));
11610 }
11611 }
11612 };
11613
11614 SgLabelStatementPtrSet used;
11615 SgLabelStatementPtrSet unused;
11616 FindUsedAndAllLabelsVisitor(used, unused).traverse(top, preorder);
11617
11618 for (SgLabelStatementPtrSet::iterator i = used.begin();
11619 i != used.end(); ++i) {
11620 assert (unused.find(*i) != unused.end());
11621 // std::cout << "Keeping used label " << (*i)->get_label().str() << std::endl;
11622 unused.erase(*i);
11623 }
11624
11625 return unused;
11626}
11627
11628// Remove all unused labels in a section of code.
11629void SageInterface::removeUnusedLabels(SgNode* top, bool keepChild/* =false */) {
11630
11631 SgLabelStatementPtrSet unused = findUnusedLabels(top);
11632
11633 for (SgLabelStatementPtrSet::iterator i = unused.begin();
11634 i != unused.end(); ++i) {
11635
11636 SgLabelStatement* l_stmt = *i;
11637 // std::cout << "Removing unused label " << (*i)->get_label().str() << std::endl;
11638 if (keepChild)
11639 {
11640 SgStatement* child= l_stmt->get_statement();
11641// l_stmt->set_parent(NULL);
11642 l_stmt->set_statement(NULL);
11643 replaceStatement (l_stmt, child);
11644 }
11645 else
11647 }
11648}
11649#endif
11650
11652 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_body();
11653 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_loop_body();
11654 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_body();
11655
11656 ROSE_ASSERT (!"Bad loop kind");
11657 return NULL;
11658 }
11659
11661 if (isSgWhileStmt(loopStmt)) {
11662 isSgWhileStmt(loopStmt)->set_body(body);
11663 } else if (isSgForStatement(loopStmt)) {
11664 isSgForStatement(loopStmt)->set_loop_body(body);
11665 } else if (isSgDoWhileStmt(loopStmt)) {
11666 isSgDoWhileStmt(loopStmt)->set_body(body);
11667 } else {
11668 ROSE_ASSERT (!"Bad loop kind");
11669 }
11670 body->set_parent(loopStmt);
11671 }
11672
11674 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_condition();
11675 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_test();
11676 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_condition();
11677
11678 ROSE_ASSERT (!"Bad loop kind");
11679 return NULL;
11680 }
11681
11683 if (isSgWhileStmt(loopStmt)) {
11684 isSgWhileStmt(loopStmt)->set_condition(cond);
11685 } else if (isSgForStatement(loopStmt)) {
11686 isSgForStatement(loopStmt)->set_test(cond);
11687 } else if (isSgDoWhileStmt(loopStmt)) {
11688 isSgDoWhileStmt(loopStmt)->set_condition(cond);
11689 } else {
11690 ROSE_ASSERT (!"Bad loop kind");
11691 }
11692 cond->set_parent(loopStmt);
11693 }
11694
11696// usually useful when compare two expressions to see if they actually refer to the same variable
11697static SgExpression* SkipCasting (SgExpression* exp)
11698{
11699 SgCastExp* cast_exp = isSgCastExp(exp);
11700 if (cast_exp != NULL)
11701 {
11702 SgExpression* operand = cast_exp->get_operand();
11703 assert(operand != 0);
11704 return SkipCasting(operand);
11705 }
11706 else
11707 return exp;
11708}
11709
11712{
11713 ROSE_ASSERT(loop!=NULL);
11714
11715 SgStatementPtrList &init = loop ->get_init_stmt();
11716 if (init.size() !=1) // We only handle one statement case
11717 return false;
11718
11719 SgStatement* init1 = init.front();
11720 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
11721 if (decl == NULL) // we only handle for (int i=0; ...)
11722 return true; // the return value is ambiguous: if not int i=0; it is already normalized
11723
11724 SgVariableSymbol* osymbol = getFirstVarSym(decl);
11725 SgInitializedName* ivarname = decl->get_variables().front();
11726 SgExpression* lbast = NULL; // the lower bound, initial state
11727 ROSE_ASSERT(ivarname != NULL);
11728 SgInitializer * initor = ivarname->get_initializer();
11729 if (isSgAssignInitializer(initor))
11730 {
11731 lbast = isSgAssignInitializer(initor)->get_operand();
11732 }
11733 else
11734 { //SgConstructorInitializer etc.
11735 // other complex declaration statements, such as Decomposition::Iterator ditr(&decomp) should be skipped
11736 // they cause a loop to be non-canonical.
11737 return false;
11738 }
11739
11740 // add a new statement like int i; and insert it to the enclosing function
11741 // There are multiple choices about where to insert this statement:
11742 // global scope: max name pollution,
11743 // right before the loop: mess up perfectly nested loops
11744 // So we prepend the statement to the enclosing function's body
11746 ROSE_ASSERT(funcDef!=NULL);
11747 SgBasicBlock* funcBody = funcDef->get_body();
11748 ROSE_ASSERT(funcBody!=NULL);
11749 //TODO a better name
11750 std::ostringstream os;
11751 os<<ivarname->get_name().getString();
11752
11753 // keep the original variable name if possible
11754 SgSymbol * visibleSym = NULL;
11755 visibleSym = lookupVariableSymbolInParentScopes(ivarname->get_name(), funcBody);
11756 if (visibleSym != NULL) // if there is a name collision, add suffix to the variable name
11757 {
11758 os<<"_nom_";
11759 os<<++gensym_counter;
11760 }
11761
11762 SgVariableDeclaration* ndecl = buildVariableDeclaration(os.str(),ivarname->get_type(), NULL, funcBody);
11763 prependStatement(ndecl, funcBody);
11764 SgVariableSymbol* nsymbol = getFirstVarSym(ndecl);
11765
11766 // replace variable ref to the new symbol
11767 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11768 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11769 {
11770 SgVarRefExp *vRef = isSgVarRefExp((*i));
11771 if (vRef->get_symbol()==osymbol)
11772 vRef->set_symbol(nsymbol);
11773 }
11774 // replace for (int i=0;) with for (i=0;)
11776 removeStatement(decl); //any side effect to the symbol? put after symbol replacement anyway
11777 init.push_back(ninit);
11778 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11779 // ninit->set_parent(loop);
11780 ninit->set_parent(loop->get_for_init_stmt ());
11781
11782 // keep record of this normalization
11783 // We may undo it later on.
11784 trans_records.forLoopInitNormalizationTable[loop] = true;
11785 trans_records.forLoopInitNormalizationRecord[loop] = make_pair (decl, ndecl) ;
11786
11787 return true;
11788}
11789
11790/*
11791 int i_norm_1;
11792 for (i_norm_1=0; i_norm_1<upper; i_norm_1 ++ );
11793Becomes:
11794 for (int i=0; i< upper; i++) ;
11795 * */
11797{
11798 ROSE_ASSERT (loop != NULL);
11799 //If not previously normalized, nothing to do and return false.
11800 if (!trans_records.forLoopInitNormalizationTable[loop])
11801 return false;
11802 // retrieve original and new declaration of the previous normalization
11803 SgVariableDeclaration* decl = trans_records.forLoopInitNormalizationRecord[loop].first;
11804 SgVariableDeclaration* ndecl = trans_records.forLoopInitNormalizationRecord[loop].second;
11805 ROSE_ASSERT (decl!= NULL);
11806 ROSE_ASSERT (ndecl!= NULL);
11807
11808
11809 // Sanity check
11810 SgStatementPtrList &init = loop ->get_init_stmt();
11811 ROSE_ASSERT(init.size() ==1); // We only handle one statement case
11812
11813 // remove the current init_stmt
11814 SgStatement* init1 = init.front();
11815 SgExprStatement* exp_stmt = isSgExprStatement(init1);
11816 ROSE_ASSERT (exp_stmt != NULL);
11817 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
11818 ROSE_ASSERT (assign_op != NULL);
11819
11820 // remove the new declaration and the current i_norm=1;
11821 removeStatement(ndecl);
11822 removeStatement (exp_stmt);
11823
11824 // restore the original declaration
11825 init.push_back(decl);
11826 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11827 // ninit->set_parent(loop);
11828 decl->set_parent(loop->get_for_init_stmt ());
11829
11830 // replace variable references
11831 // current symbol in the AST
11832 SgVariableSymbol* osymbol = getFirstVarSym(ndecl);
11833 // new symbol we want to have: the original decl
11834 SgVariableSymbol* nsymbol = getFirstVarSym(decl);
11835 // replace variable ref to the new symbol
11836 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11837 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11838 {
11839 SgVarRefExp *vRef = isSgVarRefExp((*i));
11840 if (vRef->get_symbol()==osymbol)
11841 vRef->set_symbol(nsymbol);
11842 }
11843
11844 // clear record: now the loop is not normalized any more
11845 trans_records.forLoopInitNormalizationTable[loop] = false;
11846 return true;
11847}
11848
11850{
11851 ROSE_ASSERT(loop != NULL);
11852
11853 // Normalized the test expressions
11854 // -------------------------------------
11855#if 0 // this is undecided
11856 // skip for (;;) case
11857 SgStatement* test_stmt = loop->get_test();
11858 if (test_stmt!=NULL)
11859 {
11860 if (isSgNullStatement(test_stmt))
11861 return false;
11862 }
11863#endif
11864 SgExpression* test = loop->get_test_expr();
11865 SgExpression* testlhs=NULL, * testrhs=NULL;
11866 if (isSgBinaryOp(test))
11867 {
11868 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11869 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11870 ROSE_ASSERT(testlhs && testrhs);
11871 }
11872 else
11873 return false;
11874 // keep the variable since test will be removed later on
11875 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11876 if (testlhs_var == NULL )
11877 return false;
11878 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11879 if (var_symbol==NULL)
11880 return false;
11881
11882 switch (test->variantT()) {
11883 case V_SgLessThanOp: // i<x is normalized to i<= (x-1)
11885 buildSubtractOp(deepCopy(testrhs), buildIntVal(1))));
11886 // deepDelete(test);// replaceExpression() does this already by default.
11887 break;
11888 case V_SgGreaterThanOp: // i>x is normalized to i>= (x+1)
11890 buildAddOp(deepCopy(testrhs), buildIntVal(1))));
11891 break;
11892 case V_SgLessOrEqualOp:
11893 case V_SgGreaterOrEqualOp:
11894 case V_SgNotEqualOp: //TODO Do we want to allow this?
11895 break;
11896 default:
11897 return false;
11898 }
11899 return true;
11900}
11902{
11903 ROSE_ASSERT(loop != NULL);
11904
11905 SgExpression* test = loop->get_test_expr();
11906 SgExpression* testlhs=NULL, * testrhs=NULL;
11907 if (isSgBinaryOp(test))
11908 {
11909 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11910 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11911 ROSE_ASSERT(testlhs && testrhs);
11912 }
11913 else
11914 return false;
11915 // keep the variable since test will be removed later on
11916 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11917 if (testlhs_var == NULL )
11918 return false;
11919 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11920 if (var_symbol==NULL)
11921 return false;
11922
11923
11924 // -------------------------------------
11925 SgExpression* incr = loop->get_increment();
11926 ROSE_ASSERT(incr != NULL);
11927 switch (incr->variantT()) {
11928 case V_SgPlusPlusOp: //i++ is normalized to i+=1
11929 {
11930 // check if the variables match
11931 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgPlusPlusOp(incr)->get_operand()));
11932 if (incr_var == NULL) return false;
11933 if ( incr_var->get_symbol() != var_symbol)
11934 return false;
11935 replaceExpression(incr,
11936 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)),buildIntVal(1)));
11937 break;
11938 }
11939 case V_SgMinusMinusOp: //i-- is normalized to i+=-1
11940 {
11941 // check if the variables match
11942 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusMinusOp(incr)->get_operand()));
11943 if (incr_var == NULL) return false;
11944 if ( incr_var->get_symbol() != var_symbol)
11945 return false;
11946 replaceExpression(incr,
11947 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildIntVal(-1)));
11948 break;
11949 }
11950 case V_SgMinusAssignOp: // i-= s is normalized to i+= -s
11951 {
11952 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusAssignOp(incr)->get_lhs_operand()));
11953 SgExpression* rhs = isSgMinusAssignOp(incr)->get_rhs_operand();
11954 ROSE_ASSERT (rhs != NULL);
11955 if (incr_var == NULL) return false;
11956 if ( incr_var->get_symbol() != var_symbol)
11957 return false;
11958 replaceExpression(incr,
11959 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildMultiplyOp(buildIntVal(-1), copyExpression(rhs))));
11960 break;
11961 }
11962 case V_SgAssignOp:
11963 case V_SgPlusAssignOp:
11964 break;
11965 default:
11966 return false;
11967 }
11968
11969 return true;
11970}
11971
11972/*
11973The AST of switch-case statement
11974
11975AST using EDG 6.x
11976
11977|___ *[0] ->@0x7f8d973f0010 SgSwitchStatement switch-case.C 4:3
11978 |--- p_item_selector ->@0x7f8d9738e010 SgExprStatement switch-case.C 4:10
11979 | |___ p_expression ->@0x7f8d973bd010 SgVarRefExp switch-case.C 4:10 init name@0x7f8d97757130 symbol name="a"
11980 |___ p_body ->@0x7f8d97522168 SgBasicBlock switch-case.C 5:3
11981 |--- *[0] ->@0x7f8d97343010 SgCaseOptionStmt switch-case.C 6:10
11982 | |___ p_key ->@0x7f8d98d4c090 SgIntVal switch-case.C 6:10 value=1 valueString=
11983 |--- *[1] ->@0x7f8d975222c0 SgBasicBlock switch-case.C 7:7
11984 | |--- *[0] ->@0x7f8d9738e070 SgExprStatement switch-case.C 7:8
11985 | | |___ p_expression ->@0x7f8da76c2010 SgNullExpression compilerGenerated 0:0
11986 | |___ *[1] ->@0x7f8d97308010 SgBreakStmt switch-case.C 8:9
11987 |--- *[2] ->@0x7f8d972c5010 SgDefaultOptionStmt switch-case.C 10:4
11988 |___ *[3] ->@0x7f8d97522418 SgBasicBlock switch-case.C 11:7
11989 |___ *[0] ->@0x7f8d9738e0d0 SgExprStatement switch-case.C 11:8
11990 |___ p_expression ->@0x7f8da76c2060 SgNullExpression compilerGenerated 0:0
11991
11992AST using EDG 5.x
11993└──@0x7fd34c734010 SgSwitchStatement switch-case.cpp 4:3
11994 ├──@0x7fd34c6d2010 SgExprStatement switch-case.cpp 4:10
11995 │ └──@0x7fd34c701010 SgVarRefExp switch-case.cpp 4:10
11996 └──@0x7fd34c866168 SgBasicBlock switch-case.cpp 5:3
11997 ├──@0x7fd34c5b2010 SgCaseOptionStmt switch-case.cpp 6:10
11998 │ ├──@0x7fd34c5fd010 SgCastExp compilerGenerated 0:0
11999 │ │ └──@0x7fd34c63c010 SgBoolValExp switch-case.cpp 6:10
12000 │ ├──@0x7fd34c8662c0 SgBasicBlock switch-case.cpp 7:7
12001 │ │ └──@0x7fd34c6d2070 SgExprStatement switch-case.cpp 7:8
12002 │ │ └──@0x7fd34c6aa010 SgNullExpression compilerGenerated 0:0
12003 │ └── NULL
12004 ├──@0x7fd34c5b20a8 SgCaseOptionStmt switch-case.cpp 9:10
12005 │ ├──@0x7fd34c5fd090 SgCastExp compilerGenerated 0:0
12006 │ │ └──@0x7fd34c63c070 SgBoolValExp switch-case.cpp 9:10
12007 │ ├──@0x7fd34c866418 SgBasicBlock switch-case.cpp 10:7
12008 │ │ └──@0x7fd34c6d20d0 SgExprStatement switch-case.cpp 10:8
12009 │ │ └──@0x7fd34c6aa060 SgNullExpression compilerGenerated 0:0
12010 │ └── NULL
12011 └──@0x7fd34c56f010 SgDefaultOptionStmt switch-case.cpp 12:5
12012 └──@0x7fd34c866570 SgBasicBlock switch-case.cpp 13:7
12013 └──@0x7fd34c6d2130 SgExprStatement switch-case.cpp 13:8
12014 └──@0x7fd34c6aa0b0 SgNullExpression compilerGenerated 0:0
12015
12016*/
12018 bool changed = false;
12019 // Only act on switch statements
12020 if (!switchStmt) return changed;
12021
12022 // The body of the switch should be a basic block
12023 SgBasicBlock* bodyBlock = isSgBasicBlock(switchStmt->get_body());
12024 if (!bodyBlock) return changed;
12025
12026 // Copy the list of statements to allow modification
12027 SgStatementPtrList& stmtList = bodyBlock->get_statements();
12028 std::vector<SgStatement*> stmts(stmtList.begin(), stmtList.end());
12029 int n = static_cast<int>(stmts.size());
12030
12031 // Walk through statements, detecting case/default labels
12032 // Note that this for loop does not have i++!
12033 for (int i = 0; i < n; ) {
12034 SgStatement* curr = stmts[i];
12035 // We expect curr is either SgCaseOptionStmt or SgDefaultOptionStmt at this point
12036 //
12037 // Helper lambda to handle a label statement of either SgCaseOptionStmt or SgDefaultOptionStmt
12038 auto processLabel = [&](SgStatement* labelStmt) {
12039
12040 // set j to next statement after the label statmt
12041 int j = i + 1;
12042 std::vector<SgStatement*> toWrap;
12043 // Collect statements until next case/default or end
12044 while (j < n && !isSgCaseOptionStmt(stmts[j]) && !isSgDefaultOptionStmt(stmts[j])) {
12045 toWrap.push_back(stmts[j]);
12046 ++j;
12047 }
12048
12049 // now the current statement is isSgCaseOptionStmt or isSgDefaultOptionStmt
12050 // Single-block case: if we collected exactly one basic-block and label has no body, just move it
12051 // I think the AST is constructed improperly
12052 if (toWrap.size() == 1
12053 && isSgBasicBlock(toWrap[0])
12054 && ((isSgCaseOptionStmt(labelStmt) && !isSgBasicBlock(isSgCaseOptionStmt(labelStmt)->get_body()))
12055 || (isSgDefaultOptionStmt(labelStmt) && !isSgBasicBlock(isSgDefaultOptionStmt(labelStmt)->get_body()))))
12056 {
12057#if 0
12058 //it seems like the body pointer is no longer used within the connection with EDG 6.x!!
12059 SgBasicBlock* moved = static_cast<SgBasicBlock*>(toWrap[0]);
12060 removeStatement (moved);
12061 if (auto c = isSgCaseOptionStmt(labelStmt)) {
12062 c->set_body(moved);
12063 } else if (auto d = isSgDefaultOptionStmt(labelStmt)) {
12064 d->set_body(moved);
12065 }
12066 moved->set_parent(labelStmt);
12067#endif
12068 // no further wrapping or removal needed
12069 }
12070 else if (!toWrap.empty()) {
12071 // Build a new block around statements
12072 // NOTE: wrong code: buildBasicBlock_nfi() version was calleda
12073 // It does support vector of stmts.
12074 // But we want to avoid the use of _nfi() version no file info (nfi)
12075 // to avoid set file info. manually.
12076 SgBasicBlock* newBlock = buildBasicBlock();
12077 insertStatementAfter(labelStmt, newBlock);
12078 // Insert block after label
12079#if 0
12080 //it seems like the body pointer is no longer used within the connection with EDG 6.x!!
12081 // NOTE: becomes its body
12082 newBlock->set_parent(labelStmt);
12083
12084 // Attach block as body of the label
12085 if (auto caseLabel = isSgCaseOptionStmt(labelStmt)) {
12086 caseLabel->set_body(newBlock);
12087 } else if (auto defaultLabel = isSgDefaultOptionStmt(labelStmt)) {
12088 defaultLabel->set_body(newBlock);
12089 }
12090#endif
12091 // Remove original flat statements
12092 for (auto* w: toWrap) {
12093 {
12094 // we must first remove it from original location, then append it to new location
12095 removeStatement(w);
12096 appendStatement(w, newBlock);
12097 }
12098 }
12099 changed = true;
12100 }
12101 return j; // next index to process
12102 };
12103
12104 // adjust i
12105 if (auto caseLabel = isSgCaseOptionStmt(curr)) {
12106 i = processLabel(caseLabel);
12107 } else if (auto defaultLabel = isSgDefaultOptionStmt(curr)) {
12108 i = processLabel(defaultLabel);
12109 } else {
12110 ++i;
12111 }
12112 }
12113
12114 return changed;
12115}
12116
12118// Her loop translation does not pass AST consistency tests so we rewrite some of them here
12119// NormalizeCPP.C NormalizeLoopTraverse::ProcessLoop()
12120bool SageInterface::forLoopNormalization(SgForStatement* loop, bool foldConstant /*= true*/)
12121{
12122 ROSE_ASSERT(loop != NULL);
12123 // Normalize initialization statement of the for loop
12124 // -------------------------------------
12125 // for (int i=0;... ) becomes int i; for (i=0;..)
12126 // Only roughly check here, isCanonicalForLoop() should be called to have a stricter check
12128 return false;
12129
12130 // Normalized the test expressions
12131 if (!normalizeForLoopTest(loop))
12132 return false;
12133
12134 // Normalize the increment expression
12135 if (!normalizeForLoopIncrement(loop))
12136 return false;
12137
12138 // Normalize the loop body: ensure there is a basic block
12140 ROSE_ASSERT(body!=NULL);
12141 // Liao, 9/22/2009
12142 // folding entire loop may cause decreased accuracy for floating point operations
12143 // we only want to fold the loop controlling expressions
12144 if (foldConstant)
12145 {
12146 //constantFolding(loop->get_parent());
12147 constantFolding(loop->get_test());
12148 constantFolding(loop->get_increment());
12149 }
12150
12151 return true;
12152}
12153
12156{
12157 // TODO, normalize continue to enddo ?
12158 ROSE_ASSERT (loop != NULL);
12159 SgExpression* e_3 = loop->get_increment();
12160 if (isSgNullExpression(e_3))
12161 {
12162 SgIntVal* iv = buildIntVal(1);
12163 loop->set_increment(iv);
12164 iv->set_parent(loop);
12165 delete (e_3);
12166 }
12167 return true;
12168}
12169
12170#if 0
12171bool SageInterface::loopUnrolling(SgForStatement* loop, size_t unrolling_factor)
12172{
12173 // normalize the loop first
12174 if (!forLoopNormalization(loop))
12175 return false; // input loop cannot be normalized to a canonical form
12176 // prepare Loop transformation environment
12178 ROSE_ASSERT(func!=NULL);
12179 AstInterfaceImpl faImpl(func->get_definition()->get_body());
12180 AstInterface fa(&faImpl);
12181 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
12182 ArrayInterface array_interface (*annot);
12183 array_interface.initialize(fa, AstNodePtrImpl(func->get_definition()));
12184 array_interface.observe(fa);
12185 LoopTransformInterface :: set_astInterface(fa);
12186 LoopTransformInterface :: set_arrayInterface(&array_interface);
12187
12188 // invoke the unrolling defined in Qing's code
12189 // the traversal will skip the input node ptr, so we pass loop's parent ptr instead
12190 AstNodePtr result = AstNodePtrImpl(loop->get_parent()) ;
12191
12192 LoopUnrolling lu(unrolling_factor);
12193 //LoopUnrolling lu(unrolling_factor,LoopUnrolling::COND_LEFTOVER);//works but not a good choice
12194 //if (lu.cmdline_configure()) // this will cause unrolling to be skipped if no -unroll is used in command line
12195 result = lu(lpTrans, result);
12196 return true;
12197}
12198#else
12199
12200// a brand new serious implementation for loop unrolling, Liao, 6/25/2009
12201/* Handle left-over iterations if iteration_count%unrolling_factor != 0
12202 * Handle stride (step) >1
12203 * Assuming loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
12204 *
12205 * iteration_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1
12206 * fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step;
12207 * fringe ==0 if no leftover iterations
12208 * otherwise adjust ub so the leftover iterations will put into the last fringe loop
12209 * unrolled loop's header: for (i=lb;i<=ub - fringe; i+= step*unroll_factor)
12210 * loop body: copy body n times from 0 to factor -1
12211 * stmt(i+ 0*step); ...; stmt (i+ (factor-1)*step);
12212 * fringe loop: the same as the original loop, except for no init statement
12213 *
12214 * e.g:
12215 * // unrolling 3 times for the following loop with stride !=1
12216 * for (i=0; i<=9; i+=3)
12217 * {
12218 * a[i]=i;
12219 * }
12220 * // it becomes
12221 * // iteration count = 10%3=1 -> 10/3+1 = 4
12222 * // fringe = 4%3 =1 --> 3*3
12223 * // ub-fringe = 9-3*3
12224 * for (i=0; i<=9-3*3; i+=3*3)
12225 * {
12226 * a[i+3*0]=i;
12227 * a[i+3*1]=i;
12228 * a[i+3*2]=i;
12229 * }
12230 * // i=9 is the leftover iteration
12231 * for (; i<=9; i+=3)
12232 * {
12233 * a[i]=i;
12234 * }
12235 *
12236 */
12237bool SageInterface::loopUnrolling(SgForStatement* target_loop, size_t unrolling_factor)
12238{
12239#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
12240 //Handle 0 and 1, which means no unrolling at all
12241 if (unrolling_factor <= 1)
12242 return true;
12243
12244 // normalize the target loop first
12245
12246 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12247 if (!forLoopNormalization(target_loop))
12248 {
12249 // the return value is not reliable
12250 // cerr<<"Error in SageInterface::loopUnrolling(): target loop cannot be normalized."<<endl;
12251 // dumpInfo(target_loop);
12252 // return false;
12253 }
12254 // grab the target loop's essential header information
12255 SgInitializedName* ivar = NULL;
12256 SgExpression* lb = NULL;
12257 SgExpression* ub = NULL;
12258 SgExpression* step = NULL;
12259 SgStatement* orig_body = NULL;
12260 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, &orig_body))
12261 {
12262 cerr<<"Error in SageInterface::loopUnrolling(): target loop is not canonical."<<endl;
12263 dumpInfo(target_loop);
12264 return false;
12265 }
12266 ROSE_ASSERT(ivar&& lb && ub && step);
12267 ROSE_ASSERT(isSgBasicBlock(orig_body));
12268
12269 // generate the fringe loop
12270 bool needFringe = true;
12271 SgForStatement* fringe_loop = deepCopy<SgForStatement>(target_loop);
12272 insertStatementAfter(target_loop,fringe_loop);
12273 removeStatement(fringe_loop->get_for_init_stmt());
12274 fringe_loop->set_for_init_stmt(NULL);
12275
12276 // _lu_iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;
12278 copyExpression(lb));
12279 raw_range_exp->set_need_paren(true);
12280 SgExpression* range_d_step_exp = buildDivideOp(raw_range_exp,copyExpression(step));//(ub-lb+1)/step
12281 SgExpression* condition_1 = buildEqualityOp(buildModOp(copyExpression(raw_range_exp),copyExpression(step)),buildIntVal(0)); //(ub-lb+1)%step ==0
12282
12283 SgExpression* iter_count_exp = buildConditionalExp(condition_1,range_d_step_exp, buildAddOp(copyExpression(range_d_step_exp),buildIntVal(1)));
12284 // fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step
12285 SgExpression* condition_2 = buildEqualityOp(buildModOp(iter_count_exp, buildIntVal(unrolling_factor)), buildIntVal(0));
12286 SgExpression* initor = buildConditionalExp(condition_2, buildIntVal(0), buildMultiplyOp(buildIntVal(unrolling_factor),copyExpression(step)));
12287
12288 SgScopeStatement* scope = target_loop->get_scope();
12289 ROSE_ASSERT(scope != NULL);
12290 string fringe_name = "_lu_fringe_"+ StringUtility::numberToString(++gensym_counter);
12291 SgVariableDeclaration* fringe_decl = buildVariableDeclaration(fringe_name, buildIntType(),buildAssignInitializer(initor), scope);
12292 insertStatementBefore(target_loop, fringe_decl);
12293 attachComment(fringe_decl, "iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;");
12294 attachComment(fringe_decl, "fringe = iter_count%unroll_factor==0 ? 0:unroll_factor*step");
12295
12296 // compile-time evaluate to see if index is a constant of value 0
12297 // if so, the iteration count can be divided even by the unrolling factor
12298 // and no fringe loop is needed
12299 // WE have to fold on its parent node to get a possible constant since
12300 // constant folding only folds children nodes, not the current node to a constant
12301 ConstantFolding::constantFoldingOptimization(fringe_decl,false);
12302 SgInitializedName * ivarname = fringe_decl->get_variables().front();
12303 ROSE_ASSERT(ivarname != NULL);
12304 // points to a new address if constant folding happens
12305 SgAssignInitializer * init1 = isSgAssignInitializer(ivarname->get_initializer());
12306 if (init1)
12307 if (isSgIntVal(init1->get_operand_i()))
12308 if (isSgIntVal(init1->get_operand_i())->get_value() == 0)
12309 needFringe = false;
12310
12311 // rewrite loop header ub --> ub -fringe; step --> step *unrolling_factor
12312 SgBinaryOp* ub_bin_op = isSgBinaryOp(ub->get_parent());
12313 ROSE_ASSERT(ub_bin_op);
12314 if (needFringe)
12315 ub_bin_op->set_rhs_operand(buildSubtractOp(copyExpression(ub),buildVarRefExp(fringe_name,scope)));
12316 else
12317 {
12318 ub_bin_op->set_rhs_operand(copyExpression(ub));
12319 removeStatement(fringe_decl);
12320 }
12321
12322 SgBinaryOp* step_bin_op = isSgBinaryOp(step->get_parent());
12323 ROSE_ASSERT(step_bin_op != NULL);
12324 step_bin_op->set_rhs_operand(buildMultiplyOp(copyExpression(step),buildIntVal(unrolling_factor)));
12325
12326 bool isPlus = false;
12327 if (isSgPlusAssignOp(step_bin_op))
12328 isPlus = true;
12329 else if (isSgMinusAssignOp(step_bin_op))
12330 isPlus = false;
12331 else
12332 {
12333 cerr<<"Error in SageInterface::loopUnrolling(): illegal incremental exp of a canonical loop"<<endl;
12334 dumpInfo(step_bin_op);
12335 ROSE_ABORT();
12336 }
12337
12338 // copy loop body factor -1 times, and replace reference to ivar with ivar +/- step*[1 to factor-1]
12339 for (size_t i =1; i<unrolling_factor; i++)
12340 {
12341 SgBasicBlock* body = isSgBasicBlock(deepCopy(fringe_loop->get_loop_body())); // normalized loop has a BB body
12342 ROSE_ASSERT(body);
12343 std::vector<SgVarRefExp*> refs = querySubTree<SgVarRefExp> (body, V_SgVarRefExp);
12344 for (std::vector<SgVarRefExp*>::iterator iter = refs.begin(); iter !=refs.end(); iter++)
12345 {
12346 SgVarRefExp* refexp = *iter;
12347 if (refexp->get_symbol()==ivar->get_symbol_from_symbol_table())
12348 {
12349 // replace reference to ivar with ivar +/- step*i
12350 SgExpression* new_exp = NULL;
12351 //build replacement expression for every appearance
12352 if (isPlus) //ivar +/- step * i
12353 new_exp = buildAddOp(buildVarRefExp(ivar,scope),buildMultiplyOp(copyExpression(step),buildIntVal(i)));
12354 else
12356
12357 // replace it with the right one
12358 replaceExpression(refexp, new_exp);
12359 }
12360 }
12361 // copy body to loop body, this should be a better choice
12362 // to avoid redefinition of variables after unrolling (new scope is introduced to avoid this)
12363 appendStatement(body,isSgBasicBlock(orig_body));
12364 // moveStatementsBetweenBlocks(body,isSgBasicBlock(orig_body));
12365 }
12366
12367 // remove the fringe loop if not needed finally
12368 // it is used to buffering the original loop body before in either cases
12369 if (!needFringe)
12370 removeStatement(fringe_loop);
12371
12372 // constant folding for the transformed AST
12373 ConstantFolding::constantFoldingOptimization(scope,false);
12374 //ConstantFolding::constantFoldingOptimization(getProject(),false);
12375
12376#endif
12377
12378 return true;
12379}
12380#endif
12381
12382// Liao, 6/15/2009
12385static size_t myfactorial (size_t n)
12386{
12387 size_t result=1;
12388 for (size_t i=2; i<=n; i++)
12389 result*=i;
12390 return result;
12391}
12392
12393#endif
12394
12395#ifndef USE_ROSE
12396
12399std::vector<size_t> getPermutationOrder( size_t n, size_t lexicoOrder)
12400{
12401 size_t k = lexicoOrder;
12402 std::vector<size_t> s(n);
12403 // initialize the permutation vector
12404 for (size_t i=0; i<n; i++)
12405 s[i]=i;
12406
12407 //compute (n- 1)!
12408 size_t factorial = myfactorial(n-1);
12409 //check if the number is not in the range of [0, n! - 1]
12410 if (k/n>=factorial)
12411 {
12412 printf("Error: in getPermutationOrder(), lexicoOrder is larger than n!-1\n");
12413 ROSE_ABORT();
12414 }
12415 // Algorithm:
12416 //check each element of the array, excluding the right most one.
12417 //the goal is to find the right element for each s[j] from 0 to n-2
12418 // method: each position is associated a factorial number
12419 // s[0] -> (n-1)!
12420 // s[1] -> (n-2)! ...
12421 // the input number k is divided by the factorial at each position (6, 3, 2, 1 for size =4)
12422 // so only big enough k can have non-zero value after division
12423 // 0 value means no change to the position for the current iteration
12424 // The non-zero value is further modular by the number of the right hand elements of the current element.
12425 // (mode on 4, 3, 2 to get offset 1-2-3, 1-2, 1 from the current position 0, 1, 2)
12426 // choose one of them to be moved to the current position,
12427 // shift elements between the current and the moved element to the right direction for one position
12428 for (size_t j=0; j<n-1; j++)
12429 {
12430 //calculates the next cell from the cells left
12431 //(the cells in the range [j, s.length - 1])
12432 int tempj = (k/factorial) % (n - j);
12433 //Temporarily saves the value of the cell needed
12434 // to add to the permutation this time
12435 int temps = s[j+tempj];
12436 //shift all elements to "cover" the "missing" cell
12437 //shift them to the right
12438 for (size_t i=j+tempj; i>j; i--)
12439 {
12440 s[i] = s[i-1]; //shift the chain right
12441 }
12442 // put the chosen cell in the correct spot
12443 s[j]= temps;
12444 // updates the factorial
12445 factorial = factorial /(n-(j+1));
12446 }
12447#if 0
12448 for (size_t i = 0; i<n; i++)
12449 cout<<" "<<s[i];
12450 cout<<endl;
12451#endif
12452 return s;
12453}
12454
12456/* Translation
12457 Before:
12458 for (i = 0; i < 100; i++)
12459 for (j = 0; j < 100; j++)
12460 for (k = 0; k < 100; k++)
12461 c[i][j]= c[i][j]+a[i][k]*b[k][j];
12462
12463 After tiling i loop nest's level 3 (k-loop) with size 5, it becomes
12464
12465// added a new controlling loop at the outer most level
12466 int _lt_var_k;
12467 for (_lt_var_k = 0; _lt_var_k <= 99; _lt_var_k += 1 * 5) {
12468 for (i = 0; i < 100; i++)
12469 for (j = 0; j < 100; j++)
12470 // rewritten loop header , normalized also
12471 for (k = _lt_var_k; k <= (99 < (_lt_var_k + 5 - 1))?99 : (_lt_var_k + 5 - 1); k += 1) {
12472 c[i][j] = c[i][j] + a[i][k] * b[k][j];
12473 }
12474 }
12475// finally run constant folding
12476
12477 */
12478bool SageInterface::loopTiling(SgForStatement* loopNest, size_t targetLevel, size_t tileSize)
12479{
12480 ROSE_ASSERT(loopNest != NULL);
12481 ROSE_ASSERT(targetLevel >0);
12482 // ROSE_ASSERT(tileSize>0);// 1 is allowed
12483 // skip tiling if tiling size is 0 (no tiling), we allow 0 to get a reference value for the original code being tuned
12484 // 1 (no need to tile)
12485 if (tileSize<=1)
12486 return true;
12487 // Locate the target loop at level n
12488 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(loopNest,V_SgForStatement);
12489 ROSE_ASSERT(loops.size()>=targetLevel);
12490 SgForStatement* target_loop = loops[targetLevel -1]; // adjust to numbering starting from 0
12491
12492 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12493 // normalize the target loop first
12494 if (!forLoopNormalization(target_loop))
12495 {// the return value is not reliable
12496// cerr<<"Error in SageInterface::loopTiling(): target loop cannot be normalized."<<endl;
12497// dumpInfo(target_loop);
12498// return false;
12499 }
12500 // grab the target loop's essential header information
12501 SgInitializedName* ivar = NULL;
12502 SgExpression* lb = NULL;
12503 SgExpression* ub = NULL;
12504 SgExpression* step = NULL;
12505 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, NULL))
12506 {
12507 cerr<<"Error in SageInterface::loopTiling(): target loop is not canonical."<<endl;
12508 dumpInfo(target_loop);
12509 return false;
12510 }
12511 ROSE_ASSERT(ivar&& lb && ub && step);
12512
12513 // Add a controlling loop around the top loop nest
12514 // Ensure the parent can hold more than one children
12515 SgLocatedNode* parent = NULL; //SageInterface::ensureBasicBlockAsParent(loopNest)
12516 if (isBodyStatement(loopNest)) // if it is a single body statement (Already a for statement, not a basic block)
12517 parent = makeSingleStatementBodyToBlock (loopNest);
12518 else
12519 parent = isSgLocatedNode(loopNest ->get_parent());
12520
12521 ROSE_ASSERT(parent!= NULL);
12522 // Now we can prepend a controlling loop index variable: __lt_var_originalIndex
12523 string ivar2_name = "_lt_var_"+ivar->get_name().getString();
12524 SgScopeStatement* scope = loopNest->get_scope();
12526 (ivar2_name, buildIntType(),NULL, scope);
12527 insertStatementBefore(loopNest, loop_index_decl);
12528 // init statement of the loop header, copy the lower bound
12529 SgStatement* init_stmt = buildAssignStatement(buildVarRefExp(ivar2_name,scope), copyExpression(lb));
12530 //two cases <= or >= for a normalized loop
12531 SgExprStatement* cond_stmt = NULL;
12532 SgExpression* orig_test = target_loop->get_test_expr();
12533 if (isSgBinaryOp(orig_test))
12534 {
12535 if (isSgLessOrEqualOp(orig_test))
12536 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12537 else if (isSgGreaterOrEqualOp(orig_test))
12538 {
12539 cond_stmt = buildExprStatement(buildGreaterOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12540 }
12541 else
12542 {
12543 cerr<<"Error: illegal condition operator for a canonical loop"<<endl;
12544 dumpInfo(orig_test);
12545 ROSE_ABORT();
12546 }
12547 }
12548 else
12549 {
12550 cerr<<"Error: illegal condition expression for a canonical loop"<<endl;
12551 dumpInfo(orig_test);
12552 ROSE_ABORT();
12553 }
12554 ROSE_ASSERT(cond_stmt != NULL);
12555
12556 // build loop incremental I
12557 // expression var+=up*tilesize or var-=upper * tilesize
12558 SgExpression* incr_exp = NULL;
12559 SgExpression* orig_incr_exp = target_loop->get_increment();
12560 if( isSgPlusAssignOp(orig_incr_exp))
12561 {
12562 incr_exp = buildPlusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12563 }
12564 else if (isSgMinusAssignOp(orig_incr_exp))
12565 {
12566 incr_exp = buildMinusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12567 }
12568 else
12569 {
12570 cerr<<"Error: illegal increment expression for a canonical loop"<<endl;
12571 dumpInfo(orig_incr_exp);
12572 ROSE_ABORT();
12573 }
12574 SgForStatement* control_loop = buildForStatement(init_stmt, cond_stmt,incr_exp, buildBasicBlock());
12575 insertStatementBefore(loopNest, control_loop);
12576 // move loopNest into the control loop
12577 removeStatement(loopNest);
12578 appendStatement(loopNest,isSgBasicBlock(control_loop->get_loop_body()));
12579
12580 // rewrite the lower (i=lb), upper bounds (i<=/>= ub) of the target loop
12581 SgAssignOp* assign_op = isSgAssignOp(lb->get_parent());
12582 ROSE_ASSERT(assign_op);
12583 assign_op->set_rhs_operand(buildVarRefExp(ivar2_name,scope));
12584 // ub< var_i+tileSize-1? ub:var_i+tileSize-1
12585 SgBinaryOp* bin_op = isSgBinaryOp(ub->get_parent());
12586 ROSE_ASSERT(bin_op);
12587 SgExpression* ub2 = buildSubtractOp(buildAddOp(buildVarRefExp(ivar2_name,scope), buildIntVal(tileSize)), buildIntVal(1));
12588 SgExpression* test_exp = buildLessThanOp(copyExpression(ub),ub2);
12589 test_exp->set_need_paren(true);
12590 ub->set_need_paren(true);
12591 ub2->set_need_paren(true);
12592 SgConditionalExp * triple_exp = buildConditionalExp(test_exp,copyExpression(ub), copyExpression(ub2));
12593 bin_op->set_rhs_operand(triple_exp);
12594 // constant folding
12595 // folding entire loop may decrease the accuracy of floating point calculation
12596 // we fold loop control expressions only
12597 //constantFolding(control_loop->get_scope());
12598 constantFolding(control_loop->get_test());
12599 constantFolding(control_loop->get_increment());
12600 return true;
12601}
12602
12604bool SageInterface::loopInterchange(SgForStatement* loop, size_t depth, size_t lexicoOrder)
12605{
12606 if (lexicoOrder == 0) // allow 0 to mean no interchange at all
12607 return true;
12608 // parameter verification
12609 ROSE_ASSERT(loop != NULL);
12610 //must have at least two levels
12611 ROSE_ASSERT (depth >1);
12612 ROSE_ASSERT(lexicoOrder<myfactorial(depth));
12613 //TODO need to verify the input loop has n perfectly-nested children loops inside
12614 // save the loop nest's headers: init, test, and increment
12615 std::vector<SgForStatement* > loopNest = SageInterface::querySubTree<SgForStatement>(loop,V_SgForStatement);
12616 ROSE_ASSERT(loopNest.size()>=depth);
12617 std::vector<std::vector<SgNode*> > loopHeads;
12618 for (std::vector<SgForStatement* > ::iterator i = loopNest.begin(); i!= loopNest.end(); i++)
12619 {
12620 SgForStatement* cur_loop = *i;
12621 std::vector<SgNode*> head;
12622 head.push_back(cur_loop->get_for_init_stmt());
12623 head.push_back(cur_loop->get_test());
12624 head.push_back(cur_loop->get_increment());
12625 loopHeads.push_back(head);
12626 }
12627
12628 // convert the lexicographical number to a permutation order array permutation[depth]
12629 std::vector<size_t> changedOrder = getPermutationOrder (depth, lexicoOrder);
12630 // rewrite the loop nest to reflect the permutation
12631 // set the header to the new header based on the permutation array
12632 for (size_t i=0; i<depth; i++)
12633 {
12634 // only rewrite if necessary
12635 if (i != changedOrder[i])
12636 {
12637 SgForStatement* cur_loop = loopNest[i];
12638 std::vector<SgNode*> newhead = loopHeads[changedOrder[i]];
12639
12640 SgForInitStatement* init = isSgForInitStatement(newhead[0]);
12641 //ROSE_ASSERT(init != NULL) // could be NULL?
12642 ROSE_ASSERT(init != cur_loop->get_for_init_stmt());
12643 cur_loop->set_for_init_stmt(init);
12644 if (init)
12645 {
12646 init->set_parent(cur_loop);
12648 }
12649
12650 SgStatement* test = isSgStatement(newhead[1]);
12651 cur_loop->set_test(test);
12652 if (test)
12653 {
12654 test->set_parent(cur_loop);
12656 }
12657
12658 SgExpression* incr = isSgExpression(newhead[2]);
12659 cur_loop->set_increment(incr);
12660 if (incr)
12661 {
12662 incr->set_parent(cur_loop);
12664 }
12665 }
12666 }
12667 return true;
12668}
12669
12672{
12673 ROSE_ASSERT(loop != NULL);
12674 SgInitializedName* ivarname=NULL;
12675
12676 // Fortran case ------------------
12677 if (SgFortranDo * do_loop = isSgFortranDo(loop))
12678 {
12679 SgAssignOp* assign_op = isSgAssignOp (do_loop->get_initialization());
12680 ROSE_ASSERT (assign_op != NULL);
12681 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12682 ROSE_ASSERT (var != NULL);
12683 ivarname = var->get_symbol()->get_declaration();
12684 ROSE_ASSERT (ivarname != NULL);
12685 return ivarname;
12686 }
12687 // C/C++ case ------------------------------
12688 SgForStatement* fs = isSgForStatement(loop);
12689 if (fs == NULL)
12690 {
12691 return NULL;
12692 }
12693 // we only handle C/C++ for loops and Fortran Do loops.
12694 // Any other kinds of loops (while, do-while,etc.) are skipped and return NULL;
12695 // ROSE_ASSERT (fs != NULL);
12696
12697 //Check initialization statement is something like i=xx;
12698 SgStatementPtrList & init = fs->get_init_stmt();
12699 if (init.size() !=1)
12700 {
12701 cerr<<"SageInterface::getLoopIndexVariable(), no or more than one initialization statements are encountered. Not supported yet "<<endl;
12702 //ROSE_ASSERT(false);
12703 return NULL;
12704 }
12705 SgStatement* init1 = init.front();
12706 SgExpression* ivarast=NULL;
12707
12708 // DQ (3/20/2016): Note that GNU compiler reports these variables are set but not used.
12709 //bool isCase1=false, isCase2=false;
12710
12711 //consider C99 style: for (int i=0;...)
12712 if (isSgVariableDeclaration(init1))
12713 {
12714 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12715 ivarname = decl->get_variables().front();
12716 ROSE_ASSERT(ivarname != NULL);
12717 //SgInitializer * initor = ivarname->get_initializer();
12718 // if (isSgAssignInitializer(initor))
12719 // isCase1 = true;
12720 }// other regular case: for (i=0;..)
12721 else if (isAssignmentStatement(init1, &ivarast))
12722 {
12723 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12724 if (var)
12725 {
12726 ivarname = var->get_symbol()->get_declaration();
12727 //isCase2 = true;
12728 }
12729 }
12730 else if (SgExprStatement* exp_stmt = isSgExprStatement(init1))
12731 { //case like: for (i = 1, len1 = 0, len2=0; i <= n; i++)
12732 // AST is: SgCommaOpExp -> SgAssignOp -> SgVarRefExp
12733 if (SgCommaOpExp* comma_exp = isSgCommaOpExp(exp_stmt->get_expression()))
12734 {
12735 SgCommaOpExp* leaf_exp = comma_exp;
12736 while (isSgCommaOpExp(leaf_exp->get_lhs_operand()))
12737 leaf_exp = isSgCommaOpExp(leaf_exp->get_lhs_operand());
12738 if (SgAssignOp* assign_op = isSgAssignOp(leaf_exp->get_lhs_operand()))
12739 {
12740 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12741 if (var)
12742 {
12743 ivarname = var->get_symbol()->get_declaration();
12744 }
12745 }
12746 }
12747 }
12748 else
12749 {
12750
12751 mlog[Sawyer::Message::Common::WARN] <<"Warning: SageInterface::getLoopIndexVariable(). Unhandled init_stmt type of SgForStatement"<<endl;
12752 mlog[Sawyer::Message::Common::WARN] <<"Init statement is :"<<init1->class_name() <<" " <<init1->unparseToString()<<endl;
12753 init1->get_file_info()->display("Debug");
12754
12755 return NULL;
12756 //ROSE_ASSERT (false);
12757 }
12758 // Cannot be both true
12759 // ROSE_ASSERT(!(isCase1&&isCase2));
12760
12761 //Check loop index's type
12762 //ROSE_ASSERT(isStrictIntegerType(ivarname->get_type()));
12763 return ivarname;
12764}
12765
12769{
12770 ROSE_ASSERT (ivar != NULL);
12771 ROSE_ASSERT (subtree_root != NULL);
12772 bool result = false;
12773 SgScopeStatement * cur_loop = findEnclosingLoop (getEnclosingStatement(subtree_root));
12774 while (cur_loop)
12775 {
12776 SgInitializedName * i_index = getLoopIndexVariable (cur_loop);
12777 if (i_index == ivar)
12778 {
12779 result = true;
12780 break;
12781 }
12782 else
12783 { // findEnclosingLoop() is inclusive.
12784 cur_loop = findEnclosingLoop (getEnclosingStatement(cur_loop->get_parent()));
12785 }
12786 }
12787 return result;
12788}
12789
12791
12796{
12797 ROSE_ASSERT (loop !=NULL);
12798 SgStatementPtrList& stmt_list = loop->get_init_stmt();
12799 if (stmt_list.size() >1) return true; // two var decl statements
12800 if (stmt_list.size() == 0) return false;
12801
12802// generateDOTforMultipleFile(*getProject());
12803 //single variable declaration statement, like int i;
12804 SgVariableDeclaration* decl_stmt = isSgVariableDeclaration(stmt_list[0]);
12805 if (decl_stmt != NULL)
12806 return false;
12807
12808 // single statement, but with comma expression (i=0, j=0)
12809 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
12810 ROSE_ASSERT (exp_stmt != NULL);
12811 if (isSgCommaOpExp (exp_stmt->get_expression()) )
12812 {
12813 return true;
12814 }
12815
12816 return false;
12817}
12819bool 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*/)
12820{
12821 ROSE_ASSERT(loop != NULL);
12822 SgFortranDo* fs = isSgFortranDo(loop);
12823 if (fs == NULL)
12824 return false;
12825 // 1. Check initialization statement is something like i=xx;
12826 SgExpression * init = fs->get_initialization();
12827 if (init == NULL)
12828 return false;
12829 SgAssignOp* init_assign = isSgAssignOp (init);
12830 SgExpression *lbast=NULL, *ubast=NULL;
12831 // SgExpression* ivarast=NULL, *stepast=NULL;
12832 SgInitializedName* ivarname=NULL;
12833
12834 bool isCase1=false;
12835 if (init_assign)
12836 {
12837 SgVarRefExp* var = isSgVarRefExp(init_assign->get_lhs_operand());
12838 if (var)
12839 ivarname = var->get_symbol()->get_declaration();
12840 lbast = init_assign->get_rhs_operand();
12841 if (ivarname && lbast )
12842 isCase1 = true;
12843 }
12844 // if not i=1
12845 if (!isCase1)
12846 return false;
12847
12848 //Check loop index's type
12849 if (!SageInterface::isStrictIntegerType(ivarname->get_type()))
12850 return false;
12851#if 0
12852 //2. Check test expression i [<=, >=, <, > ,!=] bound
12853 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12854 if (test == NULL)
12855 return false;
12856 switch (test->variantT()) {
12857 case V_SgLessOrEqualOp:
12858 if (isInclusiveUpperBound != NULL)
12859 *isInclusiveUpperBound = true;
12860 if (hasIncrementalIterationSpace != NULL)
12861 *hasIncrementalIterationSpace = true;
12862 break;
12863 case V_SgLessThanOp:
12864 if (isInclusiveUpperBound != NULL)
12865 *isInclusiveUpperBound = false;
12866 if (hasIncrementalIterationSpace != NULL)
12867 *hasIncrementalIterationSpace = true;
12868 break;
12869 case V_SgGreaterOrEqualOp:
12870 if (isInclusiveUpperBound != NULL)
12871 *isInclusiveUpperBound = true;
12872 if (hasIncrementalIterationSpace != NULL)
12873 *hasIncrementalIterationSpace = false;
12874 break;
12875 case V_SgGreaterThanOp:
12876 if (isInclusiveUpperBound != NULL)
12877 *isInclusiveUpperBound = false;
12878 if (hasIncrementalIterationSpace != NULL)
12879 *hasIncrementalIterationSpace = false;
12880 break;
12881// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12882 break;
12883 default:
12884 return false;
12885 }
12886 // check the tested variable is the same as the loop index
12887 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12888 if (testvar == NULL)
12889 return false;
12890 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12891 return false;
12892#endif
12893 //grab the upper bound
12894 ubast = loop->get_bound();
12895 // Fortran Do loops always have inclusive upper bound
12896 if (isInclusiveUpperBound != NULL)
12897 *isInclusiveUpperBound = true;
12898 //3. Check the increment expression
12899 SgExpression* incr = fs->get_increment();
12900 ROSE_ASSERT (incr != NULL);
12901 if (isSgNullExpression(incr))
12902 {
12903 cerr<<"Error:isCanonicalDoLoop() found NULL increment expression. Please call doLoopNormalization() first!"<<endl;
12904 ROSE_ASSERT (false);
12905 }
12906 if (hasIncrementalIterationSpace != NULL)
12907 {
12908 *hasIncrementalIterationSpace = true;
12909 // We can only tell a few cases
12910 if (SgIntVal* i_v = isSgIntVal(incr))
12911 {
12912 if (i_v->get_value()<0)
12913 *hasIncrementalIterationSpace = false;
12914 }
12915 }
12916#if 0
12917 SgVarRefExp* incr_var = NULL;
12918 switch (incr->variantT()) {
12919 case V_SgPlusAssignOp: //+=
12920 case V_SgMinusAssignOp://-=
12921 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12922 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12923 break;
12924 case V_SgPlusPlusOp: //++
12925 case V_SgMinusMinusOp: //--
12926 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12927 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12928 break;
12929 default:
12930 return false;
12931 }
12932 if (incr_var == NULL)
12933 return false;
12934 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12935 return false;
12936#endif
12937 // return loop information if requested
12938 if (ivar != NULL)
12939 *ivar = ivarname;
12940 if (lb != NULL)
12941 *lb = lbast;
12942 if (ub != NULL)
12943 *ub = ubast;
12944 if (step != NULL)
12945 *step = incr;
12946 if (body != NULL) {
12947 *body = fs->get_body();
12948 }
12949 return true;
12950}
12951//TODO: expose it to the namespace once it matures.
12953// with a single entry at the top and a single exit at the bottom, or an OpenMP construct.
12954/*
12955From OpenMP 4.5 Specification
12956
129571.2.2 OpenMP Language Terminology
12958
12959For C/C++, an executable statement, possibly compound, with a single entry at the
12960top and a single exit at the bottom, or an OpenMP construct.
12961
12962For Fortran, a block of executable statements with a single entry at the top and a
12963single exit at the bottom, or an OpenMP construct.
12964
12965COMMENTS:
12966
12967For all base languages:
12968* Access to the structured block must not be the result of a branch; and
12969* The point of exit cannot be a branch out of the structured block.
12970
12971 For C/C++:
12972* The point of entry must not be a call to setjmp();
12973* longjmp() and throw() must not violate the entry/exit criteria;
12974* Calls to exit() are allowed in a structured block; and
12975* 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.
12976
12977For Fortran:
12978* STOP statements are allowed in a structured block.
12979
12980*/
12981bool isStructuredBlock(SgStatement* s)
12982{
12983 bool rt = true;
12984 ROSE_ASSERT (s != NULL);
12985
12986 // contain break;
12987 std::set<SgNode*> bset = SgNodeHelper::loopRelevantBreakStmtNodes (s);
12988 if (bset.size()!=0 )
12989 rt = false;
12990 //TODO: contain goto statement, jumping to outside targets
12991 // longjump(), throw(),
12992 // calls to exit() are allowed.
12993
12994 return rt;
12995
12996}
12997
12999//TODO check the loop index is not being written in the loop body
13000bool 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*/)
13001{
13002 ROSE_ASSERT(loop != NULL);
13003 SgForStatement* fs = isSgForStatement(loop);
13004 //SgFortranDo* fs2 = isSgFortranDo(loop);
13005 if (fs == NULL)
13006 {
13007 // if (fs2)
13008 // return isCanonicalDoLoop (fs2, ivar, lb, ub, step, body, hasIncrementalIterationSpace, isInclusiveUpperBound);
13009 // else
13010 return false;
13011 }
13012 // 1. Check initialization statement is something like i=xx;
13013 SgStatementPtrList & init = fs->get_init_stmt();
13014 if (init.size() !=1)
13015 return false;
13016 SgStatement* init1 = init.front();
13017 SgExpression* ivarast=NULL, *lbast=NULL, *ubast=NULL, *stepast=NULL;
13018 SgInitializedName* ivarname=NULL;
13019
13020 bool isCase1=false, isCase2=false;
13021 //consider C99 style: for (int i=0;...)
13022 if (isSgVariableDeclaration(init1))
13023 {
13024 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
13025 ivarname = decl->get_variables().front();
13026 ROSE_ASSERT(ivarname != NULL);
13027 SgInitializer * initor = ivarname->get_initializer();
13028 if (isSgAssignInitializer(initor))
13029 {
13030 lbast = isSgAssignInitializer(initor)->get_operand();
13031 isCase1 = true;
13032 }
13033 }// other regular case: for (i=0;..)
13034 else if (isAssignmentStatement(init1, &ivarast, &lbast))
13035 {
13036 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
13037 if (var)
13038 {
13039 ivarname = var->get_symbol()->get_declaration();
13040 isCase2 = true;
13041 }
13042 }
13043 // Cannot be both true
13044 ROSE_ASSERT(!(isCase1&&isCase2));
13045 // if not either case is true
13046 if (!(isCase1||isCase2))
13047 return false;
13048
13049 //Check loop index's type
13050 if (!isStrictIntegerType(ivarname->get_type()))
13051 return false;
13052
13053 //2. Check test expression i [<=, >=, <, > ,!=] bound
13054 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
13055 if (test == NULL)
13056 return false;
13057 switch (test->variantT()) {
13058 case V_SgLessOrEqualOp:
13059 if (isInclusiveUpperBound != NULL)
13060 *isInclusiveUpperBound = true;
13061 if (hasIncrementalIterationSpace != NULL)
13062 *hasIncrementalIterationSpace = true;
13063 break;
13064 case V_SgLessThanOp:
13065 if (isInclusiveUpperBound != NULL)
13066 *isInclusiveUpperBound = false;
13067 if (hasIncrementalIterationSpace != NULL)
13068 *hasIncrementalIterationSpace = true;
13069 break;
13070 case V_SgGreaterOrEqualOp:
13071 if (isInclusiveUpperBound != NULL)
13072 *isInclusiveUpperBound = true;
13073 if (hasIncrementalIterationSpace != NULL)
13074 *hasIncrementalIterationSpace = false;
13075 break;
13076 case V_SgGreaterThanOp:
13077 if (isInclusiveUpperBound != NULL)
13078 *isInclusiveUpperBound = false;
13079 if (hasIncrementalIterationSpace != NULL)
13080 *hasIncrementalIterationSpace = false;
13081 break;
13082// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
13083 break;
13084 default:
13085 return false;
13086 }
13087 // check the tested variable is the same as the loop index
13088 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
13089 if (testvar == NULL)
13090 return false;
13091 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
13092 return false;
13093 //grab the upper bound
13094 ubast = test->get_rhs_operand();
13095
13096 //3. Check the increment expression
13097 /* Allowed forms
13098 ++var
13099 var++
13100 --var
13101 var--
13102
13103 var += incr
13104 var -= incr
13105
13106 var = var + incr
13107 var = incr + var
13108 var = var - incr
13109 */
13110 SgExpression* incr = fs->get_increment();
13111 SgVarRefExp* incr_var = NULL;
13112 switch (incr->variantT()) {
13113 case V_SgPlusAssignOp: //+=
13114 case V_SgMinusAssignOp://-=
13115 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
13116 stepast = isSgBinaryOp(incr)->get_rhs_operand();
13117 break;
13118 case V_SgPlusPlusOp: //++
13119 case V_SgMinusMinusOp: //--
13120 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
13121 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
13122 break;
13123 case V_SgAssignOp: { // cases : var + incr, var - incr, incr + var (not allowed: incr-var)
13124 incr_var=isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
13125 if(incr_var == NULL)
13126 return false;
13127 SgAddOp* addOp=isSgAddOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
13128 SgSubtractOp* subtractOp=isSgSubtractOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
13129 SgBinaryOp* arithOp=0;
13130 if(addOp)
13131 arithOp=addOp;
13132 else if(subtractOp)
13133 arithOp=subtractOp;
13134 else
13135 return false;
13136 ROSE_ASSERT(arithOp!=0);
13137 if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_lhs_operand()))) {
13138 // cases : var + incr, var - incr
13139 incr_var=varRefExp;
13140 stepast=isSgBinaryOp(arithOp)->get_rhs_operand();
13141 } else if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_rhs_operand()))) {
13142 if(isSgAddOp(arithOp)) {
13143 // case : incr + var (not allowed: incr-var)
13144 incr_var=varRefExp;
13145 stepast=isSgBinaryOp(arithOp)->get_lhs_operand();
13146 }
13147 }
13148 break;
13149 } // end of V_AssignOp
13150 default:
13151 return false;
13152 }
13153
13154 if (incr_var == NULL)
13155 return false;
13156 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
13157 return false;
13158
13159
13160 // single entry and single exit?
13161 // only for C for loop for now
13162 // TODO: Fortran support later
13163 if (fs && !isStructuredBlock(fs->get_loop_body()) )
13164 return false;
13165
13166 // return loop information if requested
13167 if (ivar != NULL)
13168 *ivar = ivarname;
13169 if (lb != NULL)
13170 *lb = lbast;
13171 if (ub != NULL)
13172 *ub = ubast;
13173 if (step != NULL)
13174 *step = stepast;
13175 if (body != NULL) {
13176 *body = fs->get_loop_body();
13177 }
13178 return true;
13179}
13180
13183{
13184 ROSE_ASSERT(loop != NULL);
13185 ROSE_ASSERT(lb != NULL);
13186 SgForStatement* forstmt = isSgForStatement(loop);
13187 SgFortranDo* dostmt = isSgFortranDo(loop);
13188 // ROSE_ASSERT(forstmt!= NULL);
13189
13190 if (forstmt != NULL)
13191 {
13192 // two cases: init_stmt is
13193 // SgExprStatement (assignment) like i=0;
13194 // SgVariableDeclaration int i =0 or
13195 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignOp);
13196 if (testList.size()>0) // assignment statement
13197 {
13198 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13199 SgAssignOp * assignop = isSgAssignOp((*testList.begin()));
13200 ROSE_ASSERT(assignop);
13201 if( assignop->get_rhs_operand()->get_lvalue())
13202 lb->set_lvalue(true);
13203 assignop->set_rhs_operand(lb);
13204 lb->set_parent(assignop);
13205 //TODO what happens to the original rhs operand?
13206 }
13207 else // variable declaration case
13208 {
13209 // SgVariableDeclaration
13210 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignInitializer );
13211 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13212 SgAssignInitializer* init = isSgAssignInitializer((*testList.begin()));
13213 ROSE_ASSERT(init != NULL);
13214 init->set_operand(lb);
13215 lb->set_parent(init);
13216 //TODO what happens to the original rhs operand?
13217 }
13218 }
13219 else if (dostmt != NULL)
13220 {
13221 SgExpression* init = dostmt->get_initialization();
13222 ROSE_ASSERT (init != NULL);
13223 SgAssignOp * a_op = isSgAssignOp (init);
13224 ROSE_ASSERT (a_op!=NULL);
13225 a_op->set_rhs_operand(lb);
13226 lb->set_parent(a_op);
13227 //TODO delete the previous operand?
13228 }
13229 else
13230 {
13231 cerr<<"Error. SageInterface::setLoopLowerBound(), illegal loop type:"<< loop->class_name()<<endl;
13232 ROSE_ASSERT (false);
13233 }
13234}
13235
13238{
13239 ROSE_ASSERT(loop != NULL);
13240 ROSE_ASSERT(ub != NULL);
13241 SgForStatement* forstmt = isSgForStatement(loop);
13242 // ROSE_ASSERT(forstmt!= NULL);
13243 SgFortranDo* dostmt = isSgFortranDo(loop);
13244 if (forstmt != NULL)
13245 {
13246 // set upper bound expression
13247 SgBinaryOp * binop= isSgBinaryOp(isSgExprStatement(forstmt->get_test())->get_expression());
13248 ROSE_ASSERT(binop != NULL);
13249 binop->set_rhs_operand(ub);
13250 ub->set_parent(binop);
13251 }
13252 else if (dostmt != NULL)
13253 {
13254 dostmt->set_bound(ub);
13255 ub->set_parent(dostmt);
13256 //TODO delete the original bound expression
13257 }
13258 else
13259 {
13260 cerr<<"Error. SageInterface::setLoopUpperBound(), illegal loop type:"<< loop->class_name()<<endl;
13261 ROSE_ASSERT (false);
13262 }
13263
13264}
13265
13268{
13269 ROSE_ASSERT(loop != NULL);
13270 ROSE_ASSERT(stride != NULL);
13271 SgForStatement* forstmt = isSgForStatement(loop);
13272 SgFortranDo * dostmt = isSgFortranDo (loop);
13273 // ROSE_ASSERT(forstmt!= NULL);
13274 if (dostmt != NULL)
13275 {
13276 dostmt->set_increment(stride);
13277 stride->set_parent(dostmt);
13278 //TODO delete original increment expression
13279 }
13280 else if (forstmt != NULL)
13281 {
13282 // set stride expression
13283 // case 1: i++ change to i+=stride
13284 Rose_STL_Container<SgNode*> testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusPlusOp);
13285 if (testList.size()>0)
13286 {
13287 ROSE_ASSERT(testList.size() == 1); // should have only one
13288 SgVarRefExp *loopvarexp = isSgVarRefExp(SageInterface::deepCopy
13289 (isSgPlusPlusOp( *testList.begin())->get_operand()));
13290 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13291 forstmt->set_increment(plusassignop);
13292 }
13293
13294 // case 1.5: i-- also changed to i+=stride
13295 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusMinusOp);
13296 if (testList.size()>0)
13297 {
13298 ROSE_ASSERT(testList.size()==1);// should have only one
13299 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13300 (isSgMinusMinusOp(*testList.begin())->get_operand()));
13301 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13302 forstmt->set_increment(plusassignop);
13303 }
13304
13305 // case 2: i+=X
13306 testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusAssignOp);
13307 if (testList.size()>0)
13308 {
13309 ROSE_ASSERT(testList.size()==1);// should have only one
13310 SgPlusAssignOp * assignop = isSgPlusAssignOp(*(testList.begin()));
13311 ROSE_ASSERT(assignop!=NULL);
13312 assignop->set_rhs_operand(stride);
13313 }
13314
13315 // case 2.5: i-=X changed to i+=stride
13316 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusAssignOp);
13317 if (testList.size()>0)
13318 {
13319 ROSE_ASSERT(testList.size()==1);// should have only one
13320 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13321 (isSgMinusAssignOp(*testList.begin())->get_lhs_operand()));
13322 SgExprStatement* exprstmt = isSgExprStatement((*testList.begin())->get_parent());
13323 ROSE_ASSERT(exprstmt !=NULL);
13324 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13325 exprstmt->set_expression(plusassignop);
13326 }
13327
13328#if 0 // [Robb Matzke 2021-03-17]
13329 // DQ (1/3/2007): I think this is a meaningless statement.
13330 testList.empty();
13331#endif
13332 // case 3: i=i + X or i =X +i i
13333 // TODO; what if users use i*=,etc ??
13334 // send out a warning: not canonical FOR/DO loop
13335 // or do this in the real frontend. MUST conform to canonical form
13336 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgAddOp);
13337 if (testList.size()>0)
13338 {
13339 ROSE_ASSERT(testList.size()==1);// should have only one ??
13340 // consider only the top first one
13341 SgAddOp * addop = isSgAddOp(*(testList.begin()));
13342 ROSE_ASSERT(addop!=NULL);
13343 string loopvar= (isSgVarRefExp(isSgAssignOp(addop->get_parent())->get_lhs_operand())->get_symbol()->get_name()).getString();
13344 if (isSgVarRefExp(addop->get_rhs_operand())!=NULL)
13345 {
13346 if ((isSgVarRefExp(addop->get_rhs_operand())->get_symbol()->get_name()).getString() ==loopvar)
13347 addop->set_lhs_operand(stride);
13348 else
13349 addop->set_rhs_operand(stride);
13350 }
13351 else
13352 addop->set_rhs_operand(stride);
13353 }
13354
13355 // case 3.5: i=i - X
13356 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgSubtractOp);
13357 if (testList.size()>0)
13358 {
13359 ROSE_ASSERT(testList.size()==1);// should have only one ??
13360 // consider only the top first one
13361 SgSubtractOp * subtractop = isSgSubtractOp(*(testList.begin()));
13362 ROSE_ASSERT(subtractop!=NULL);
13363 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13364 (isSgSubtractOp(*testList.begin())->get_lhs_operand()));
13365 SgAssignOp *assignop = isSgAssignOp((*testList.begin())->get_parent());
13366 ROSE_ASSERT(assignop !=NULL);
13367 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13368 assignop->set_rhs_operand(plusassignop);
13369 }
13370 }
13371 else
13372 {
13373 cerr<<"Error. SageInterface::setLoopStride(), illegal loop type:"<< loop->class_name()<<endl;
13374 ROSE_ASSERT (false);
13375
13376 }
13377}
13378
13382bool SageInterface::isAssignmentStatement(SgNode* s, SgExpression** lhs/*=NULL*/, SgExpression** rhs/*=NULL*/, bool* readlhs/*=NULL*/)
13383{
13384 SgExprStatement *n = isSgExprStatement(s);
13385 SgExpression *exp = (n != 0)? n->get_expression() : isSgExpression(s);
13386 if (exp != 0) {
13387 switch (exp->variantT()) {
13388 case V_SgPlusAssignOp:
13389 case V_SgMinusAssignOp:
13390 case V_SgAndAssignOp:
13391 case V_SgIorAssignOp:
13392 case V_SgMultAssignOp:
13393 case V_SgDivAssignOp:
13394 case V_SgModAssignOp:
13395 case V_SgXorAssignOp:
13396 case V_SgAssignOp:
13397 {
13398 SgBinaryOp* s2 = isSgBinaryOp(exp);
13399 if (lhs != 0)
13400 *lhs = s2->get_lhs_operand();
13401 if (rhs != 0) {
13402 SgExpression* init = s2->get_rhs_operand();
13403 if ( init->variantT() == V_SgAssignInitializer)
13404 init = isSgAssignInitializer(init)->get_operand();
13405 *rhs = init;
13406 }
13407 if (readlhs != 0)
13408 *readlhs = (exp->variantT() != V_SgAssignOp);
13409 return true;
13410 }
13411 default:
13412 return false;
13413 }
13414 }
13415 return false;
13416}
13417
13418
13419void
13421 {
13422 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,V_SgGotoStatement);
13423 for (size_t i = 0; i < gotos.size(); ++i)
13424 {
13425 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13426 SgLabelStatement* ls = gs->get_label();
13427 SgBasicBlock* lsParent = isSgBasicBlock(ls->get_parent());
13428 if (!lsParent) continue;
13429 SgStatementPtrList& bbStatements = lsParent->get_statements();
13430
13431 size_t j = std::find(bbStatements.begin(), bbStatements.end(), ls) - bbStatements.begin();
13432
13433 ROSE_ASSERT (j != bbStatements.size());
13434
13435 while (j < bbStatements.size() - 1 && isSgLabelStatement(bbStatements[j + 1]))
13436 {
13437 ++j;
13438 }
13439 gs->set_label(isSgLabelStatement(bbStatements[j]));
13440 }
13441 }
13442
13443bool SageInterface::mergeDeclarationAndAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt, bool removeAssignStmt /*= true*/)
13444{
13445 return mergeAssignmentWithDeclaration (assign_stmt, decl, removeAssignStmt);
13446}
13448
13452bool SageInterface::mergeAssignmentWithDeclaration(SgExprStatement* assign_stmt, SgVariableDeclaration* decl, bool removeAssignStmt /*= true*/)
13453{
13454 bool rt= true;
13455 ROSE_ASSERT(decl != NULL);
13456 ROSE_ASSERT(assign_stmt != NULL);
13457
13458 // Sanity check of assign statement: must be a form of var = xxx;
13459 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13460 if (assign_op == NULL)
13461 return false;
13462 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13463 if (assign_op_var == NULL) return false;
13464
13465 // Sanity check of the variable declaration: it should not have an existing initializer
13467 if (decl_var->get_initptr()!= NULL ) return false;
13468
13469 // check if two variables match
13470 // In translation, it is possible the declaration has not yet been inserted into its scope.
13471 // finding its symbol can return NULL.
13472 // But we still want to do the merge.
13473 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13474 if (decl_var_symbol!=NULL)
13475 {
13476 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13477 if (assign_op_var->get_symbol() != decl_var_symbol) return false;
13478 }
13479 else
13480 { // fallback to comparing variable names instead
13481 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13482 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name()) return false;
13483 }
13484
13485 // Everything looks fine now. Do the merge.
13487
13488 // Must preserve the proprecessing information of the original assign_stmt
13489 // use appending (not prepending) so the order of decl's comments and assign_stmt's comments can be preserved
13490 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13491
13492 // removeStatement() does not support removing a statement which is not inside a container.
13493 // But sometimes we do need to remove such a statement and replace it with a new one.
13494 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13495 // TODO: improve removeStatement() which uses low level rewritting.
13496 if (removeAssignStmt)
13497 SageInterface::removeStatement (assign_stmt);
13498// SageInterface::deepDelete (assign_stmt);
13500 decl_var->set_initptr(initor);
13501 initor->set_parent(decl_var);
13502
13503 return rt;
13504}
13505
13507{
13508 bool rt= true;
13509
13510 // Sanity check of assign statement: must be a form of var = xxx;
13511 ROSE_ASSERT(assign_stmt != NULL);
13512 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13513 if (assign_op == NULL)
13514 return false;
13515 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13516 if (assign_op_var == NULL)
13517 return false;
13518
13519 // Sanity check of the variable declaration: it should not have an existing initializer
13520 ROSE_ASSERT(decl != NULL);
13522 if (decl_var->get_initptr()!= NULL)
13523 return false;
13524
13525 // check if two variables match
13526 // In translation, it is possible the declaration has not yet been inserted into its scope.
13527 // finding its symbol can return NULL.
13528 // But we still want to do the merge.
13529 ROSE_ASSERT(decl_var != NULL);
13530 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13531 if (decl_var_symbol != NULL) {
13532 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13533 if (assign_op_var->get_symbol() != decl_var_symbol)
13534 return false;
13535 }
13536 else
13537 { // fallback to comparing variable names instead
13538 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13539 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name())
13540 return false;
13541 }
13542
13543 // Everything looks fine now. Do the merge.
13544 // It is implemented by
13545 // 1. copy rhs to the decl's rhs,
13546 // 2. then move the decl to the place of the assignment,
13547 // 3. then remove the assignment
13548 //
13549 // Copy rhs to be initializer
13552 decl_var->set_initptr(initor);
13553 initor->set_parent(decl_var);
13554
13555 // move proprocessing info. attached before decl to its next statement's front, using prepending to preserve the original order
13556 SgStatement* next_stmt = SageInterface::getNextStatement (decl);
13557 SageInterface::movePreprocessingInfo(decl, next_stmt, PreprocessingInfo::before, PreprocessingInfo::before, true);
13558
13559 // removeStatement() does not support removing a statement which is not inside a container.
13560 // But sometimes we do need to remove such a statement and replace it with a new one.
13561 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13562 // TODO: improve removeStatement() which uses low level rewritting.
13563
13564 // Now move the declaration to a new position, right before the assignment statement
13566 SageInterface::insertStatementBefore(assign_stmt, decl, false);
13567
13568 // preserve preprocessing info. attached to assign_stmt before removing it , using append (last false)
13569 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13570
13571 // Original assignment statement should be removed
13572 SageInterface::removeStatement (assign_stmt);
13573 // SageInterface::deepDelete (decl);
13574
13575 return rt;
13576}
13577// Split a variable declaration with an rhs assignment into two statements: a declaration and an assignment.
13578// Return the generated assignment statement, if any
13580{
13581 SgExprStatement* rt = NULL;
13582 ROSE_ASSERT (decl != NULL);
13583
13585 SgInitializer* initor = decl_var ->get_initptr();
13586 if (initor == NULL)
13587 rt = NULL;
13588 else
13589 {
13590 // Liao, 2021/10/21, we have to support all sorts of initializers, including aggregate initializer
13591 SgExpression * rhs=NULL;
13592 if (SgAssignInitializer * ainitor = isSgAssignInitializer (initor))
13593 rhs = ainitor->get_operand();
13594 else
13595 rhs = initor;
13596
13597 // we deep copy the rhs operand
13598 rt = buildAssignStatement (buildVarRefExp(decl_var) , deepCopy(rhs));
13599 decl_var->set_initptr(NULL);
13600 //TODO clean up initor
13601 insertStatementAfter ( decl, rt );
13602 }
13603 return rt;
13604}
13606ROSE_DLL_API int SageInterface::splitVariableDeclaration (SgScopeStatement* scope, bool topLevelOnly /* = true */)
13607{
13608 int count = 0;
13609 if (!topLevelOnly)
13610 {
13611 cerr<<"SageInterface::splitVariableDeclaration() topLevelOnly == false is not yet implemented."<<endl;
13612 ROSE_ASSERT (false);
13613 }
13614
13615 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVariableDeclaration);
13616 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13617 {
13618 SgVariableDeclaration *decl= isSgVariableDeclaration(*i);
13619 if (topLevelOnly)
13620 {
13621 ROSE_ASSERT(decl != NULL);
13622 if (decl->get_scope() == scope)
13623 {
13625 count ++;
13626 }
13627 }
13628 }
13629 return count;
13630}
13631
13632void SageInterface::collectVarRefs(SgLocatedNode* root, std::vector<SgVarRefExp* > & result)
13633{
13634 ROSE_ASSERT (root != NULL);
13635// std::vector<SgVarRefExp* > result;
13636
13637 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgVarRefExp);
13638 // AST query won't find variables used in types
13640
13641 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13642 {
13643 SgVarRefExp *vRef = isSgVarRefExp(*i);
13644 ROSE_ASSERT (vRef != NULL);
13645 result.push_back(vRef);
13646 }
13647}
13648
13649int SageInterface::collectVariableReferencesInArrayTypes(SgLocatedNode* root, Rose_STL_Container<SgNode*> & currentVarRefList)
13650{
13651 int rt = 0;
13652 ROSE_ASSERT (root != NULL);
13653 Rose_STL_Container<SgNode*> constructorList= NodeQuery::querySubTree(root, V_SgConstructorInitializer);
13654 for (size_t i =0; i< constructorList.size(); i++)
13655 {
13656 SgConstructorInitializer * c_init = isSgConstructorInitializer (constructorList[i]);
13657 if (SgArrayType* a_type = isSgArrayType(c_init->get_expression_type()))
13658 {
13659 Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree (a_type->get_index(),V_SgVarRefExp);
13660 for (size_t j =0 ; j< varList.size(); j++)
13661 {
13662 SgVarRefExp* var_exp = isSgVarRefExp(varList[j]) ;
13663 currentVarRefList.push_back(var_exp);
13664//TODO: these variable references do have special scopes, how to communicate to users?
13665// specialVarRefScopeExp[var_exp] = c_init ;
13666 rt ++;
13667 }
13668 }
13669 }
13670 return rt;
13671}
13672
13673namespace SageInterface { // A few internal helper classes
13674
13676 {
13677 SgAndOp* op;
13678
13679 public:
13680 AndOpGenerator(SgAndOp* op): op(op) {}
13681
13682 virtual SgStatement* generate(SgExpression* lhs)
13683 {
13684 if (lhs==NULL)
13685 return NULL;
13686 SgTreeCopy treeCopy;
13687 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13688 ROSE_ASSERT (lhsCopy);
13689 SgIfStmt* tree =
13696 return tree;
13697 }
13698 };
13699
13701 {
13702 SgOrOp* op;
13703
13704 public:
13705 OrOpGenerator(SgOrOp* op): op(op) {}
13706
13707 virtual SgStatement* generate(SgExpression* lhs)
13708 {
13709 if (lhs==NULL)
13710 return NULL;
13711 SgTreeCopy treeCopy;
13712 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13713 ROSE_ASSERT (lhsCopy);
13714 SgIfStmt* tree =
13721 return tree;
13722 }
13723 };
13724
13726 {
13727 SgConditionalExp* op;
13728
13729 public:
13731
13732 virtual SgStatement* generate(SgExpression* lhs)
13733 {
13734 if (lhs==NULL)
13735 return NULL;
13736 SgTreeCopy treeCopy;
13737 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13738 ROSE_ASSERT (lhsCopy);
13739 SgIfStmt* tree =
13746 return tree;
13747 }
13748 };
13749
13750} // end of namespace for the helper classes
13751
13754{
13755 ROSE_ASSERT(from != NULL);
13756
13757#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
13758#if 0 // This is not accurate for template class specializations. We disable this assertion for now. The worst case is compilation error later.
13760 std::cerr << "Type " << from->get_type()->unparseToString() << " of expression " << from->unparseToString() << " is not copy constructible" << std::endl;
13761 ROSE_ASSERT (false);
13762 }
13763
13764 assert (SageInterface::isCopyConstructible(from->get_type())); // How do we report errors?
13765#endif
13766 SgStatement* stmt = getStatementOfExpression(from);
13767 assert (stmt);
13768 if (!isSgForInitStatement(stmt->get_parent())) {
13769 //SageInterface::ensureBasicBlockAsParent(stmt);
13770 // no return value is accepted. Only the optional transformation matters
13771 if (isBodyStatement(stmt) && !isSgBasicBlock(stmt))
13773 }
13774
13775 SgScopeStatement* parent = isSgScopeStatement(stmt->get_parent());
13776 // cout << "parent is a " << (parent ? parent->sage_class_name() : "NULL") << endl;
13777 if (!parent && isSgForInitStatement(stmt->get_parent()))
13778 parent = isSgScopeStatement(stmt->get_parent()->get_parent()->get_parent());
13779 assert (parent);
13780 // cout << "parent is a " << parent->sage_class_name() << endl;
13781 // cout << "parent is " << parent->unparseToString() << endl;
13782 // cout << "stmt is " << stmt->unparseToString() << endl;
13783 SgName varname = "rose_temp__";
13784 if (newName == "") {
13785 varname << ++SageInterface::gensym_counter;
13786 } else {
13787 varname = newName;
13788 }
13789
13790 SgType* vartype = from->get_type();
13791 SgNode* fromparent = from->get_parent();
13792 vector<SgExpression*> ancestors;
13793 for (SgExpression *expr = from, *anc = isSgExpression(fromparent); anc != 0;
13794 expr = anc, anc = isSgExpression(anc->get_parent()))
13795 {
13796 if ((isSgAndOp(anc) && expr != isSgAndOp(anc)->get_lhs_operand()) ||
13797 (isSgOrOp(anc) && expr != isSgOrOp(anc)->get_lhs_operand()) ||
13798 (isSgConditionalExp(anc) && expr != isSgConditionalExp(anc)->get_conditional_exp()))
13799 ancestors.push_back(anc); // Closest first
13800 }
13801 // cout << "This expression to split has " << ancestors.size() << " ancestor(s)" << endl;
13802 for (vector<SgExpression*>::reverse_iterator ai = ancestors.rbegin(); ai != ancestors.rend(); ++ai)
13803 {
13804 StatementGenerator* gen;
13805 switch ((*ai)->variantT()) {
13806 case V_SgAndOp:
13807 gen = new AndOpGenerator(isSgAndOp(*ai)); break;
13808 case V_SgOrOp:
13809 gen = new OrOpGenerator(isSgOrOp(*ai)); break;
13810 case V_SgConditionalExp:
13811 gen = new ConditionalExpGenerator(isSgConditionalExp(*ai)); break;
13812 default: assert (!"Should not happen"); abort();
13813 }
13815 delete gen;
13816 } // for
13817 if (ancestors.size() != 0) {
13818 return splitExpression(from);
13819 // Need to recompute everything if there were ancestors
13820 }
13821 SgVariableDeclaration* vardecl = SageBuilder::buildVariableDeclaration(varname, vartype, NULL, parent);
13823 ROSE_ASSERT (sym);
13824 SgInitializedName* initname = sym->get_declaration();
13825 ROSE_ASSERT (initname);
13827 replaceExpressionWithExpression(from, varref);
13828 // std::cout << "Unparsed 3: " << fromparent->sage_class_name() << " --- " << fromparent->unparseToString() << endl;
13829 // cout << "From is a " << from->sage_class_name() << endl;
13831 initname->set_initializer(ai);
13832 ai->set_parent(initname);
13833 myStatementInsert(stmt, vardecl, true);
13834 // vardecl->set_parent(stmt->get_parent());
13835 // FixSgTree(vardecl);
13836 // FixSgTree(parent);
13837 return ai;
13838
13839#else
13840 return NULL;
13841#endif
13842
13843} //splitExpression()
13844
13847 struct SplitStatementGenerator: public StatementGenerator {
13848 SgExpression* expr;
13849 virtual SgStatement* generate(SgExpression* answer) {
13850 using namespace SageBuilder;
13851 return buildBasicBlock(buildAssignStatement(answer, expr));
13852 }
13853 };
13854 SplitStatementGenerator gen;
13855 gen.expr = expr;
13857 }
13858
13860 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,
13861 V_SgGotoStatement);
13862 map<SgLabelStatement*, SgLabelStatement*> labelsToReplace; for
13863 (size_t i = 0; i < gotos.size(); ++i) {
13864 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13865 SgBasicBlock* gsParent = isSgBasicBlock(gs->get_parent());
13866 if (!gsParent) continue;
13867 SgStatementPtrList& bbStatements = gsParent->get_statements();
13868 size_t j = std::find(bbStatements.begin(), bbStatements.end(), gs)
13869 - bbStatements.begin();
13870 ROSE_ASSERT (j != bbStatements.size());
13871 if (j == 0) continue;
13872 if (isSgLabelStatement(bbStatements[j - 1])) {
13873 labelsToReplace[isSgLabelStatement(bbStatements[j - 1])] =
13874 gs->get_label();
13875 }
13876 }
13877 for (size_t i = 0; i < gotos.size(); ++i) {
13878 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13879 SgLabelStatement* oldLabel = gs->get_label();
13880 while (labelsToReplace.find(oldLabel) != labelsToReplace.end()) {
13881 oldLabel = labelsToReplace[oldLabel];
13882 }
13883 gs->set_label(oldLabel);
13884 }
13885 }
13886
13888 switch (e->variantT()) {
13889#ifdef _MSC_VER
13890 // DQ (11/28/2009): This fixes a warning in MSVC (likely p_value should be a "bool" instead of an "int").
13891 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() != 0);
13892#else
13893 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() == true);
13894#endif
13895 case V_SgIntVal: return isSgIntVal(e)->get_value() != 0;
13896 case V_SgCastExp: return isConstantTrue(isSgCastExp(e)->get_operand());
13897 case V_SgNotOp: return isConstantFalse(isSgNotOp(e)->get_operand());
13898 case V_SgAddressOfOp: return true;
13899 default: return false;
13900 }
13901 }
13902
13904 switch (e->variantT()) {
13905 case V_SgBoolValExp: return isSgBoolValExp(e)->get_value() == false;
13906 case V_SgIntVal: return isSgIntVal(e)->get_value() == 0;
13907 case V_SgCastExp: return
13908 isConstantFalse(isSgCastExp(e)->get_operand());
13909 case V_SgNotOp: return isConstantTrue(isSgNotOp(e)->get_operand());
13910 default: return false;
13911 }
13912 }
13913
13915 SgExpression* e) {
13916 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13917 if (!fc) return false;
13918 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13919 if (fr == NULL) return false;
13920 return fr->get_symbol()->get_declaration() == decl;
13921 }
13922
13923 bool SageInterface::isCallToParticularFunction(const std::string& qualifiedName, size_t
13924 arity, SgExpression* e) {
13925 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13926 if (!fc) return false;
13927 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13928 if (fr == NULL) return false;
13929 string name =
13930 fr->get_symbol()->get_declaration()->get_qualified_name().getString();
13931 return (name == qualifiedName &&
13932 fc->get_args()->get_expressions().size() == arity);
13933 }
13934
13936 {
13937 ROSE_ASSERT( e != NULL);
13938 // We enforce that the source expression is fully attached to the AST
13939 // Too strict, the source expression can be just built and not attached.
13940 // Liao, 9/21/2009
13941// ROSE_ASSERT( e->get_parent() != NULL);
13942 return deepCopy(e);
13943 }
13944
13946 {
13947 return deepCopy(s);
13948 }
13949
13950 //----------------- add into AST tree --------------------
13952 {
13953 ROSE_ASSERT(expList);
13954 ROSE_ASSERT(exp);
13955 expList->append_expression(exp);
13956 exp->set_parent(expList);
13957 }
13958
13959 void SageInterface::appendExpressionList(SgExprListExp *expList, const std::vector<SgExpression*>& exp)
13960 {
13961 for (size_t i = 0; i < exp.size(); ++i)
13962 appendExpression(expList, exp[i]);
13963 }
13964
13965# if 0
13966 // DQ (11/25/2011): Moved to the header file so that it could be seen as a template function.
13967
13968 // TODO consider the difference between C++ and Fortran
13969 // fixup the scope of arguments,no symbols for nondefining function declaration's arguments
13970template <class actualFunction>
13971void
13972// SageInterface::setParameterList(SgFunctionDeclaration * func,SgFunctionParameterList * paralist)
13973SageInterface::setParameterList(actualFunction * func,SgFunctionParameterList * paralist)
13974 {
13975 // DQ (11/25/2011): Modified this to be a templated function so that we can handle both
13976 // SgFunctionDeclaration and SgTemplateFunctionDeclaration (and their associated member
13977 // function derived classes).
13978
13979 ROSE_ASSERT(func);
13980 ROSE_ASSERT(paralist);
13981
13982 // Warn to users if a paralist is being shared
13983 if (paralist->get_parent() !=NULL)
13984 {
13985 cerr << "Waring! Setting a used SgFunctionParameterList to function: "
13986 << (func->get_name()).getString()<<endl
13987 << " Sharing parameter lists can corrupt symbol tables!"<<endl
13988 << " Please use deepCopy() to get an exclusive parameter list for each function declaration!"<<endl;
13989 // ROSE_ASSERT(false);
13990 }
13991
13992 // Liao,2/5/2008 constructor of SgFunctionDeclaration will automatically generate SgFunctionParameterList, so be cautious when set new paralist!!
13993 if (func->get_parameterList() != NULL)
13994 if (func->get_parameterList() != paralist)
13995 delete func->get_parameterList();
13996
13997 func->set_parameterList(paralist);
13998 paralist->set_parent(func);
13999 }
14000#endif
14001
14002// static
14003SgVariableSymbol* addArg(SgFunctionParameterList *paraList, SgInitializedName* initName, bool isPrepend)
14004 {
14005 ROSE_ASSERT(paraList != NULL);
14006 ROSE_ASSERT(initName != NULL);
14007
14008 if (isPrepend == true)
14009 paraList->prepend_arg(initName);
14010 else
14011 paraList->append_arg(initName);
14012
14013 // DQ (12/4/2011): If this is going to be set, make sure it will not be over written.
14014 // initName->set_parent(paraList);
14015 if (initName->get_parent() == NULL)
14016 initName->set_parent(paraList);
14017
14018 ROSE_ASSERT(initName->get_parent() == paraList);
14019
14020 SgFunctionDeclaration* func_decl= isSgFunctionDeclaration(paraList->get_parent());
14021
14022 // DQ (12/4/2011): This will not be true for function parameter lists in SgTemplateFunctionDeclaration cases.
14023 // Also in typical use the SgFunctionDeclaration is not known yet so the parent is not set.
14024 // ROSE_ASSERT(paraList->get_parent() != NULL);
14025 // ROSE_ASSERT(func_decl != NULL);
14026
14027 SgScopeStatement* scope = NULL;
14028 if (func_decl != NULL)
14029 {
14030 if ((func_decl->get_definingDeclaration()) == func_decl )
14031 {
14032 // defining function declaration, set scope and symbol table
14033 SgFunctionDefinition* func_def = func_decl->get_definition();
14034 ROSE_ASSERT(func_def);
14035 scope = func_def;
14036 }
14037 else
14038 {
14039 // nondefining declaration, set scope only, currently set to decl's scope, TODO
14040 scope = func_decl->get_scope();
14041 }
14042
14043 // fix up declptr of the init name
14044 initName->set_declptr(func_decl);
14045 }
14046
14047 // 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
14048 // that initName already has a scope.
14049 //
14050 // DQ (12/4/2011): Added check...(fails for case of SgTypeEllipse).
14051 // ROSE_ASSERT(initName->get_scope() != NULL);
14052 // ROSE_ASSERT(initName->get_scope() != NULL || isSgTypeEllipse(initName->get_type()) != NULL);
14053
14054 // ROSE_ASSERT (scope); -- scope may not be set because the function declaration may not have been inserted anywhere
14055
14056 initName->set_scope(scope);
14057 if (scope != NULL)
14058 {
14059 SgVariableSymbol* sym = isSgVariableSymbol(initName->get_symbol_from_symbol_table());
14060 if (sym == NULL)
14061 {
14062 sym = new SgVariableSymbol(initName);
14063 scope->insert_symbol(initName->get_name(), sym);
14064 sym->set_parent(scope->get_symbol_table());
14065 }
14066 return sym;
14067 }
14068 else
14069 {
14070 return NULL;
14071 }
14072 }
14073
14075{
14076 return addArg(paraList,initName,false);
14077}
14078
14080{
14081 return addArg(paraList,initName,true);
14082}
14083
14085{
14086 ROSE_ASSERT(decl);
14087 ROSE_ASSERT(pragma);
14088 if (decl->get_pragma()!=NULL) delete (decl->get_pragma());
14089 decl->set_pragma(pragma);
14090 pragma->set_parent(decl);
14091}
14092
14093
14095//TODO should we ensureBasicBlockAsScope(scope) ? like ensureBasicBlockAsParent(targetStmt);
14096//It might be well legal to append the first and only statement in a scope!
14098 {
14099 // DQ (4/3/2012): Simple globally visible function to call (used for debugging in ROSE).
14100 void testAstForUniqueNodes ( SgNode* node );
14101
14102#if 0
14103 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14104#endif
14105
14106 // DQ (6/19/2012): Exit as a test...
14107 // ROSE_ASSERT(isSgClassDeclaration(stmt) == NULL);
14108
14109 if (scope == NULL)
14110 {
14111#if 0
14112 printf (" --- scope was not specified as input! \n");
14113#endif
14115 }
14116
14117 ROSE_ASSERT(stmt != NULL);
14118 ROSE_ASSERT(scope != NULL);
14119
14120#if 0
14121 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14122#endif
14123
14124#if 0
14125 // DQ (2/2/2010): This fails in the projects/OpenMP_Translator "make check" tests.
14126 // DQ (1/2/2010): Introducing test that are enforced at lower levels to catch errors as early as possible.
14127 SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(stmt);
14128 if (declarationStatement != NULL)
14129 {
14130 ROSE_ASSERT(declarationStatement->get_firstNondefiningDeclaration() != NULL);
14131 ROSE_ASSERT(declarationStatement->get_definingDeclaration() != NULL);
14132 }
14133#endif
14134
14135#if 0
14136 // This fix breaks other transformations.
14137 // It is better to do this explicitly as needed before calling appendStatement();
14138 // Liao 10/19/2010
14139 // In rare cases, we are moving the statement from its original scope to another scope
14140 // We have to remove it from its original scope before append it to the new scope
14141 SgNode* old_parent= stmt->get_parent();
14142 if (old_parent)
14143 {
14144 removeStatement(stmt);
14145 }
14146#endif
14147
14148#if 0
14149 // catch-all for statement fixup
14150 // Must fix it before insert it into the scope,
14151 fixStatement(stmt,scope);
14152
14153 //-----------------------
14154 // append the statement finally
14155 // scope->append_statement (stmt);
14156 scope->insertStatementInScope(stmt,false);
14157 stmt->set_parent(scope); // needed?
14158#else
14159 // DQ (7/12/2012): Skip adding when this is a non-autonomous type declaration.
14160 bool skipAddingStatement = false;
14161 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
14162 if (classDeclaration != NULL)
14163 {
14164 // DQ (7/9/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14165#if 0
14166 if (classDeclaration->get_parent() != NULL)
14167 {
14168 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());
14169 }
14170#endif
14171
14172#if 1
14173 // DQ (6/9/2013): This is the original code...
14174 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false);
14175#else
14176 // 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).
14177 // This fails to add enough statements to the AST.
14178 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false) || (classDeclaration->get_parent() != NULL);
14179#endif
14180
14181 // DQ (6/26/2013): Don't just check for SgTemplateInstantiationDecl, but also for SgClassDeclaration.
14182 // DQ (6/9/2013): Check if this is a SgTemplateInstantiationDecl, since it might be appearing
14183 // twice as a result of a template argument being instantiated and we only want to add it into
14184 // the scope once. This happens for test2013_198.C and I can't find a better solution.
14185 if (classDeclaration != NULL && scope->containsOnlyDeclarations() == true)
14186 {
14187 // Check if this instnatiated template has already been added to the scope.
14188
14189 // DQ (6/26/2013): This is a newer alternative to test for an existing statement in a scope.
14190 // const SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
14191 // SgDeclarationStatementPtrList::const_iterator existingDeclaration = find(declarationList.begin(),declarationList.end(),classDeclaration);
14192 bool statementAlreadyExistsInScope = scope->statementExistsInScope(classDeclaration);
14193 if (statementAlreadyExistsInScope == true)
14194 {
14195 if (isSgTemplateInstantiationDecl(classDeclaration) != NULL)
14196 {
14197// DQ (9/13/2014): Clean up this output when not printing developer warnings.
14198// #if 1
14199#if PRINT_DEVELOPER_WARNINGS
14200 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",
14201 classDeclaration,classDeclaration->class_name().c_str(),scope,scope->class_name().c_str());
14202#endif
14203 }
14204#if 1
14205 else
14206 {
14207#if 1
14208 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",
14209 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14210#endif
14211 }
14212#endif
14213 skipAddingStatement = true;
14214 }
14215 }
14216 }
14217 else
14218 {
14219 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(stmt);
14220 if (enumDeclaration != NULL)
14221 {
14222 // DQ (7/12/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14223 skipAddingStatement = (enumDeclaration->get_isAutonomousDeclaration() == false);
14224 }
14225 }
14226
14227#if 0
14228 // DQ (6/26/2013): This is an attempt to support better testing of possible redundant statements
14229 // that would be inserted into the current scope. This is however a bit expensive so we are using
14230 // this as a way to also debug the new cases where this happens.
14231 bool statementAlreadyExistsInScope = scope->statementExistsInScope(stmt);
14232 if (skipAddingStatement == false && statementAlreadyExistsInScope == true)
14233 {
14234#if 0
14235 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",
14236 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14237#endif
14238#if 0
14239 printf ("Exiting as a test! \n");
14240 ROSE_ABORT();
14241#endif
14242 skipAddingStatement = true;
14243 }
14244#endif
14245
14246#if 0
14247 printf (" --- skipAddingStatement = %s \n",skipAddingStatement ? "true" : "false");
14248#endif
14249
14250 if (skipAddingStatement == false)
14251 {
14252 // catch-all for statement fixup
14253 // Must fix it before insert it into the scope,
14254 // printf ("In appendStatementList(): Calling fixStatement() \n");
14255 fixStatement(stmt,scope);
14256 // printf ("DONE: In appendStatementList(): Calling fixStatement() \n");
14257
14258 //-----------------------
14259 // append the statement finally
14260 // scope->append_statement (stmt);
14261#if 0
14262 printf (" --- calling insertStatementInScope(): scope = %p = %s stmt = %p = %s \n",scope,scope->class_name().c_str(),stmt,stmt->class_name().c_str());
14263#endif
14264 scope->insertStatementInScope(stmt,false);
14265
14266 // DQ (6/9/2013): Added comment only: This is needed because some declaration have to have the
14267 // setting of there paremtn pointes delayed until now based on if they appear nested inside of
14268 // other declarations (e.g. "typedef struct { int x; } y;").
14269 stmt->set_parent(scope); // needed?
14270 }
14271#endif
14272
14273 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14274 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14275 // this). Also since this is only operating within a single scope it is likely too specific to C
14276 // instead of addressing the details of C++ where functions can be placed in alternative scopes and
14277 // use name qualification).
14278 // update the links after insertion!
14280 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14281 {
14282 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14283 }
14284
14285#if 0
14286 // DQ (6/26/2013): Turn on this test for debugging ROSE compiling rose.h header file.
14287 // Note that this is a stronger AST subtree test and not the weaker test for a redundant
14288 // statement in a single scope.
14289 // DQ (9/1/2012): this is a debugging mode that we need to more easily turn on and off.
14290 // DQ (4/3/2012): Added test to make sure that the pointers are unique.
14291 testAstForUniqueNodes(scope);
14292#else
14293 // printf ("In SageInterface::appendStatement(): Skipping test for unique statements in subtree \n");
14294#endif
14295 }
14296
14299{
14300 ROSE_ASSERT (stmt != NULL);
14301 ROSE_ASSERT (for_init_stmt != NULL);
14302
14303#if 0
14304 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());
14305#endif
14306
14307 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14308 // to record it being moved (and thus the macroExpansions that it might be associated with having
14309 // to force the macroExpansion's associated statements to be marked as a transformation.
14311
14312#if 0
14313 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());
14314#endif
14315
14316 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14317 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14318 // prepend, we only need to look at the scope.
14320
14321 for_init_stmt->append_init_stmt (stmt);
14322}
14323
14324void
14325SageInterface::appendStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14326 {
14327 for (size_t i = 0; i < stmts.size(); ++i)
14328 {
14329#if 0
14330#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14331 printf ("In appendStatementList(): stmts[i = %" PRIuPTR "] = %p = %s \n",i,stmts[i],stmts[i]->class_name().c_str());
14332 // printf ("In appendStatementList(): stmts[i = %" PRIuPTR "]->get_parent() = %p \n",i,stmts[i]->get_parent());
14333#endif
14334#endif
14335 appendStatement(stmts[i], scope); // Liao 5/15/2013, defer the logic of checking parent pointers to appendStatement()
14336#if 0
14337 if (stmts[i]->get_parent() != NULL)
14338 {
14339#if 0
14340#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14341 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());
14342#endif
14343#endif
14344 appendStatement(stmts[i], scope);
14345 }
14346 else
14347 {
14348 printf (" --- WARNING: In appendStatementList(): stmts[i = %" PRIuPTR "] not added to scope (because stmts[i]->get_parent() == NULL) \n",i);
14349 }
14350#endif
14351 }
14352 }
14353
14356 {
14357 ROSE_ASSERT (stmt != NULL);
14358
14359#if 0
14360 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14361#endif
14362
14363 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.1") == false);
14364
14365 if (scope == NULL)
14366 {
14368 }
14369
14370 ROSE_ASSERT(scope != NULL);
14371 // TODO handle side effect like SageBuilder::appendStatement() does
14372
14373 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.1a") == false);
14374
14375 // Must fix it before insert it into the scope,
14376 // otherwise assertions in insertStatementInScope() would fail
14377 fixStatement(stmt,scope);
14378
14379#if 0
14380 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",
14381 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14382#endif
14383
14384 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.2") == false);
14385
14386 // DQ (12/1/2015): If this is a moved statement then cause it to update internal data structures
14387 // to record it being moved (and thus the macroExpansions that it might be associated with having
14388 // to force the macroExpansion's associated statements to be marked as a transformation.
14390
14391#if 0
14392 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",
14393 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14394#endif
14395
14396 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.3") == false);
14397
14398 // DQ (12/1/2015): Also look at the statements on either side of the location where this statement
14399 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14400 // prepend, we only need to look at the scope.
14402
14403#if 0
14404 printf ("Calling insertStatementInScope() \n");
14405#endif
14406
14407 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.4") == false);
14408 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.4a") == false);
14409
14410 scope->insertStatementInScope(stmt,true);
14411 stmt->set_parent(scope); // needed?
14412
14413 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.5") == false);
14414
14415 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14416 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14417 // this). Also since this is only operating within a single scope it is likely too specific to C
14418 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14419 // use name qualification).
14420 // update the links after insertion!
14422 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14423 {
14424 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14425 }
14426
14427 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.6") == false);
14428
14429#if 0
14430 printf ("Leaving SageInterface::prependStatement() \n");
14431#endif
14432 } // prependStatement()
14433
14434
14437{
14438 ROSE_ASSERT (stmt != NULL);
14439 ROSE_ASSERT (for_init_stmt != NULL);
14440
14441#if 0
14442 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());
14443#endif
14444
14445 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14446 // to record it being moved (and thus the macroExpansions that it might be associated with having
14447 // to force the macroExpansion's associated statements to be marked as a transformation.
14449
14450#if 0
14451 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());
14452#endif
14453
14454 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14455 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14456 // prepend, we only need to look at the scope.
14458
14459 for_init_stmt->prepend_init_stmt (stmt);
14460}
14461
14462void SageInterface::prependStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14463 {
14464 for (size_t i = stmts.size(); i > 0; --i)
14465 {
14466 prependStatement(stmts[i - 1], scope);
14467 }
14468 }
14469
14474{
14475 bool rt = false;
14476 ROSE_ASSERT (scope != NULL);
14477 switch (scope->variantT())
14478 {
14479 case V_SgBasicBlock:
14480 case V_SgClassDefinition:
14481 case V_SgFunctionDefinition:
14482 case V_SgGlobal:
14483 case V_SgNamespaceDefinitionStatement: //?
14484 rt = true;
14485 break;
14486
14487 case V_SgAssociateStatement :
14488 case V_SgBlockDataStatement :
14489 case V_SgCatchOptionStmt:
14490 case V_SgDoWhileStmt:
14491 case V_SgForAllStatement:
14492 case V_SgForStatement:
14493 case V_SgFortranDo:
14494 case V_SgIfStmt:
14495 case V_SgSwitchStatement:
14496 case V_SgUpcForAllStatement:
14497 case V_SgWhileStmt:
14498 rt = false;
14499 break;
14500
14501 default:
14502 cout<<"unrecognized or unhandled scope type for SageInterface::hasSimpleChildrenList() "<<endl;
14503 break;
14504 }
14505 return rt;
14506}
14507
14508
14509// 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.
14511 {
14512 // When inserting a statement into global scope, if inserting at the top of scope it is best to insert
14513 // after the last statement from the preinclude file rose_edg_required_macros_and_functions.h.
14514
14515 SgDeclarationStatementPtrList & declarationList = globalScope->get_declarations();
14516
14517 SgStatement* last_statement = NULL;
14518 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
14519 // while (i != declarationList.end())
14520 while (i != declarationList.end() && (*i)->get_file_info() != NULL && (*i)->get_file_info()->isFrontendSpecific() == true)
14521 {
14522#if 0
14523 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");
14524#endif
14525 last_statement = *i;
14526
14527 i++;
14528 }
14529
14530 ROSE_ASSERT(last_statement != NULL);
14531#if 1
14532 printf ("last_statement = %p = %s \n",last_statement,last_statement->class_name().c_str());
14533#endif
14534#if 0
14535 printf ("Exiting as a test! \n");
14536 ROSE_ABORT();
14537#endif
14538
14539 return last_statement;
14540 }
14541
14542
14543 //TODO handle more side effect like SageBuilder::append_statement() does
14544 //Merge myStatementInsert()
14545 // insert SageInterface::insertStatement()
14546void SageInterface::insertStatement(SgStatement *targetStmt, SgStatement* newStmt, bool insertBefore, bool autoMovePreprocessingInfo /*= true */)
14547 {
14548 ROSE_ASSERT(targetStmt &&newStmt);
14549 ROSE_ASSERT(targetStmt != newStmt); // should not share statement nodes!
14550
14551 if (isSgGlobal(targetStmt) ||
14552 isSgClassDefinition(targetStmt)||
14553 isSgNamespaceDefinitionStatement(targetStmt)||
14554 isSgFunctionParameterList(targetStmt)||
14555 isSgFunctionDefinition(targetStmt)||
14556 isSgCtorInitializerList(targetStmt))
14557 {
14558 string className = targetStmt->class_name();
14559 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.";
14560 cerr<<err_msg<<endl;
14561 ROSE_ASSERT (false);
14562 }
14563
14564#if 0 // it is allowed to have different types of statements inserted after SgCaseOptionStmt
14565 if (isSgCaseOptionStmt(targetStmt))
14566 {
14567 if (!isSgCaseOptionStmt(newStmt))
14568 {
14569 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;
14570 ROSE_ASSERT(false);
14571 }
14572 }
14573#endif
14574 SgNode* parent = targetStmt->get_parent();
14575 if (parent == NULL)
14576 {
14577 cerr << "Empty parent pointer for target statement. May be caused by the wrong order of target and new statements in insertStatement(targetStmt, newStmt)"<<endl;
14578 ROSE_ASSERT(parent);
14579 }
14580
14581 // Issuing an error due to variable initialization inside a switch statement block without enclosing braces {}.
14582 //
14583 // This is a tricky situation: C++ allows a flat list of statements following case option statement, even though they are indented
14584 //case HORIZONTAL_TAB:
14585 // foundHorizontalTab = true;
14586 // break;
14587 // case VERTICAL_TAB:
14588 // foundVerticalTab = true;
14589 // break;
14590 // ...
14591 //
14592 // Unparser will flatten them out.
14593 //
14594 // when we try to inserat a variable decl stmt into the list after case option statement, compilers will complain
14595 // error: jump to case label
14596 // crosses initialization of "int variablexyz"
14597 //
14598 //
14599 // if targetStmt's parent is SgCaseOptionStmt,
14600 if (SgCaseOptionStmt * case_opt_stmt = isSgCaseOptionStmt(parent))
14601 {
14602 if (SgVariableDeclaration* var_stmt = isSgVariableDeclaration(newStmt))
14603 {
14604 cerr<<"Error: you cannot insert a variable declaration stmt inside a case option statement without enclosing brances in between."<<endl;
14605 cerr<<"parent of target is a case option stmt:"<<parent <<endl;
14606 cerr<<"new statement is a variable statement:"<<newStmt <<endl;
14607 ASSERT_require(false);
14608 }
14609 }
14610
14611 if (isSgLabelStatement(parent) != nullptr)
14612 {
14613 SgLabelStatement* labelStatement = isSgLabelStatement(parent);
14614 parent = labelStatement->get_parent();
14615 ROSE_ASSERT(isSgLabelStatement(parent) == NULL);
14616 }
14617
14618 if (isSgFunctionDefinition(parent) ||
14619 isSgTypedefDeclaration(parent) ||
14620 isSgSwitchStatement(parent) ||
14621 isSgVariableDeclaration(parent))
14622 {
14623 string className = parent->class_name();
14624 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.";
14625 cerr<<err_msg<<endl;
14626 if (SgSwitchStatement * switch_stmt = isSgSwitchStatement(parent))
14627 {
14628 if (switch_stmt->get_item_selector() == targetStmt)
14629 {
14630 cerr<<"The target statement is the item selector of a switch statement. You cannot insert any statement before or after it."<<endl;
14631 }
14632 }
14633
14634 ROSE_ASSERT (false);
14635 }
14636
14637#if 0
14638 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());
14639#endif
14640
14641 // DQ (12/2/2014): Not sure why this was here in the first place (likely debugging code from the fix for the SgLableStatement insertion.
14642 // SgFunctionDefinition* functionDefinition = SageInterface::getEnclosingProcedure(targetStmt);
14643 // ROSE_ASSERT(functionDefinition != NULL);
14644
14645 // Liao 3/2/2012. The semantics of ensureBasicBlockAsParent() are messy. input targetStmt may be
14646 // returned as it is if it is already a basic block as a body of if/while/catch/ etc.
14647 // We now have single statement true/false body for IfStmt etc
14648 // However, IfStmt::insert_child() is ambiguous and not implemented
14649 // So we make SgBasicBlock out of the single statement and
14650 // essentially call SgBasicBlock::insert_child() instead.
14651 // TODO: add test cases for If, variable, variable/struct inside if, etc
14652 // parent = ensureBasicBlockAsParent(targetStmt);
14653
14654 // must get the new scope after ensureBasicBlockAsParent ()
14655 SgScopeStatement* scope = targetStmt->get_scope();
14656 ROSE_ASSERT(scope);
14657
14658#if 0
14659 printf ("targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14660 printf ("scope = %p = %s \n",scope,scope->class_name().c_str());
14661#endif
14662
14663 // DQ (11/16/2014): This step is problematic if the targetStmt has been transformed to be associated with a SgLabelStatement.
14664 // The reason is that the targetStmt's parent will have been reset to be the SgLabelStatement and the logic in the set_parent()
14665 // function will assert fail when the parent is being set to itself (which is a good idea in general). A better solution might
14666 // 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
14667 // more sense in this special case of a SgLabelStatement.
14668 // newStmt->set_parent(targetStmt->get_parent());
14669 newStmt->set_parent(scope);
14670
14671 // 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.
14672 // The fix was the reuse the one that was found.
14673 fixStatement(newStmt,scope);
14674
14675 // DQ (9/16/2010): Added assertion that appears to be required to be true.
14676 // However, if this is required to be true then what about statements in
14677 // SgStatementExpression IR nodes?
14678 ROSE_ASSERT(isSgStatement(parent) != NULL);
14679
14680 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
14681 // appear before the statement to be attached to the inserted statement (and marked
14682 // to appear before that statement).
14683 ROSE_ASSERT(targetStmt != NULL);
14684 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
14685
14686#if 0
14687 printf ("In SageInterface::insertStatement(): after checking for associated comments \n");
14688 reportNodesMarkedAsModified(scope);
14689#endif
14690
14691 // TODO refactor this portion of code into a separate function
14692 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14693 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
14694 if (autoMovePreprocessingInfo) // Do this only if automatically handling of preprocessing information is request by users
14695 {
14696 if (comments != NULL && isSgBasicBlock(newStmt) == NULL)
14697 {
14698 vector<int> captureList;
14699#if 0
14700 printf ("Found attached comments (at %p = %s, inserting %p = %s insertBefore = %s): comments->size() = %" PRIuPTR " \n",
14701 targetStmt,targetStmt->class_name().c_str(),newStmt,newStmt->class_name().c_str(),insertBefore ? "true" : "false",comments->size());
14702#endif
14703 // DQ (9/17/2010): Assert that the new statement being inserted has no attached comments or CPP directives.
14704 if (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false)
14705 {
14706 // If the inserted statment has attached comments or CPP directives then this is gets a little
14707 // bit more comple and we don't support that at present.
14708 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");
14709 }
14710 // DQ (9/17/2010): commented out because it fails test in projects/OpenMP_Translator/for_firstprivate.c
14711 ROSE_ASSERT((newStmt->getAttachedPreprocessingInfo() == NULL) || (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false));
14712
14713 int commentIndex = 0;
14714 AttachedPreprocessingInfoType::iterator i;
14715 for (i = comments->begin(); i != comments->end(); i++)
14716 {
14717 ROSE_ASSERT ( (*i) != NULL );
14718#if 0
14719 printf (" Attached Comment (relativePosition=%s): %s\n",
14720 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
14721 (*i)->getString().c_str());
14722 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
14723 (*i)->get_file_info()->display("comment/directive location");
14724#endif
14725 PreprocessingInfo::RelativePositionType relativePosition = (insertBefore == true) ? PreprocessingInfo::before : PreprocessingInfo::after;
14726 if ((*i)->getRelativePosition() == relativePosition)
14727 {
14728 // accumulate into list
14729 captureList.push_back(commentIndex);
14730 }
14731
14732 commentIndex++;
14733 }
14734
14735 // printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
14736 if (captureList.empty() == false)
14737 {
14738 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
14739 // SgStatement* surroundingStatement = (insertBefore == true) ? getPreviousStatement(targetStmt) : getNextStatement(targetStmt);
14740 // SgStatement* surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14741 SgStatement* surroundingStatement = newStmt;
14742 ROSE_ASSERT(surroundingStatement != targetStmt);
14743 ROSE_ASSERT(surroundingStatement != NULL);
14744#if 0
14745 if (surroundingStatement == NULL)
14746 {
14747 // printf ("Warning: the surrounding statement for insertBefore = %s is NULL (so use the newStmt) \n",insertBefore ? "true" : "false");
14748 surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14749 }
14750#endif
14751 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
14752 // printf ("This is a valid surrounding statement = %s for insertBefore = %s \n",surroundingStatement->class_name().c_str(),insertBefore ? "true" : "false");
14753 vector<int>::iterator j = captureList.begin();
14754 while (j != captureList.end())
14755 {
14756 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
14757 // printf ("Attaching comments to newStmt = %p = %s \n",newStmt,newStmt->class_name().c_str());
14758 newStmt->addToAttachedPreprocessingInfo((*comments)[*j]);
14759
14760 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
14761 // printf ("Removing entry from comments list on targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14762 (*comments)[*j] = NULL;
14763
14764 j++;
14765 }
14766
14767 // Now remove each NULL entries in the comments vector.
14768 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
14769 for (size_t n = 0; n < captureList.size(); n++)
14770 {
14771 AttachedPreprocessingInfoType::iterator k = comments->begin();
14772 while (k != comments->end())
14773 {
14774 // Only modify the list once per iteration over the captureList
14775 if (*k == NULL)
14776 {
14777 comments->erase(k);
14778 break;
14779 }
14780 k++;
14781 }
14782 }
14783 }
14784 }
14785 else
14786 {
14787 // printf ("No attached comments (at %p of type: %s): \n",targetStmt,targetStmt->class_name().c_str());
14788 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14789 // I think that special rules apply to inserting a SgBasicBlock so disable comment relocation when inserting a SgBasicBlock.
14790 if (comments != NULL)
14791 {
14792 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");
14793 }
14794 }
14795 } // end if autoMovePreprocessingInfo
14796
14797
14798#if 0
14799 printf ("In SageInterface::insertStatement(): after processing associated comments \n");
14800 reportNodesMarkedAsModified(scope);
14801#endif
14802
14803 if (isSgIfStmt(parent))
14804 {
14805 if (isSgIfStmt(parent)->get_conditional()==targetStmt)
14806 {
14807 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14808 }
14809 else
14810 {
14811 if (isSgIfStmt(parent)->get_true_body()==targetStmt)
14812 {
14813 // Liao 3/2/2012
14814 // We have some choices:
14815 // 1) if the targeStmt is a basic block, we can append/prepend the new stmt
14816 // within the targetStmt. But this is not the exact semantics of insertStatment. It will break the outliner.
14817 // Since the targetStmt will have new content inside of it, which is not the semantics of
14818 // inserting anything before/or after it.
14819 // 2) always insert a padding basic block between parent and targetStmt
14820 // and we can legally insert before/after the target statement within the
14821 // padding basic block.
14822 //TODO: this insertion of padding basic block should ideally go into some AST normalization phase
14823 // so the transformation function (insertStatement) only does what it means to do, no more and no less.
14824 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14825 isSgIfStmt(parent)->set_true_body(newparent);
14826 newparent->set_parent(parent);
14827 insertStatement(targetStmt, newStmt,insertBefore);
14828 }
14829 else
14830 {
14831 if (isSgIfStmt(parent)->get_false_body()==targetStmt)
14832 {
14833 // ensureBasicBlockAsParent(targetStmt);
14834 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14835 isSgIfStmt(parent)->set_false_body(newparent);
14836 newparent->set_parent(parent);
14837 insertStatement(targetStmt, newStmt,insertBefore);
14838 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14839 }
14840 }
14841 }
14842 }
14843 else
14844 {
14845 if (isSgWhileStmt(parent))
14846 {
14847 if (isSgWhileStmt(parent)->get_condition()==targetStmt)
14848 {
14849 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14850 }
14851 else
14852 {
14853 if (isSgWhileStmt(parent)->get_body()==targetStmt)
14854 {
14855 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14856 isSgWhileStmt(parent)->set_body(newparent);
14857 newparent->set_parent(parent);
14858 insertStatement(targetStmt, newStmt,insertBefore);
14859 // ensureBasicBlockAsParent(targetStmt);
14860 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14861 }
14862 }
14863 }
14864 else
14865 {
14866 if (isSgDoWhileStmt(parent))
14867 {
14868 if (isSgDoWhileStmt(parent)->get_condition()==targetStmt)
14869 {
14870 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14871 }
14872 else
14873 {
14874 if (isSgDoWhileStmt(parent)->get_body()==targetStmt)
14875 {
14876 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14877 isSgDoWhileStmt(parent)->set_body(newparent);
14878 newparent->set_parent(parent);
14879 insertStatement(targetStmt, newStmt,insertBefore);
14880 // ensureBasicBlockAsParent(targetStmt);
14881 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14882 }
14883 }
14884 }
14885 else
14886 {
14887 if (isSgForStatement(parent))
14888 {
14889 if (isSgForStatement(parent)->get_loop_body()==targetStmt)
14890 {
14891 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14892 isSgForStatement(parent)->set_loop_body(newparent);
14893 newparent->set_parent(parent);
14894 insertStatement(targetStmt, newStmt,insertBefore);
14895 // ensureBasicBlockAsParent(targetStmt);
14896 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14897 }
14898 else
14899 {
14900 if (isSgForStatement(parent)->get_test()==targetStmt)
14901 {
14902 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14903 }
14904 }
14905 }
14906 else // \pp (2/24/2011) added support for UpcForAll
14907 {
14908 if (SgUpcForAllStatement* p = isSgUpcForAllStatement(parent))
14909 {
14910 //const bool stmt_present = (p->get_loop_body() == targetStmt || p->get_test() == targetStmt);
14911
14912 // \pp \todo what if !stmt_present
14913 // ROSE_ASSERT(stmt_present != NULL);
14914 insertStatement(p, newStmt, insertBefore);
14915 }
14916 else
14917 {
14918 if (SgOmpBodyStatement * p = isSgOmpBodyStatement (parent))
14919 {
14920 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14921 p->set_body(newparent);
14922 newparent->set_parent(parent);
14923 insertStatement(targetStmt, newStmt,insertBefore);
14924 }
14925 else
14926 {
14927 // It appears that all of the recursive calls are untimately calling this location.
14928 SgStatement* stmnt = isSgStatement(parent);
14929 ROSE_ASSERT(stmnt != NULL);
14930 stmnt->insert_statement(targetStmt,newStmt,insertBefore);
14931 }
14932 }
14933 }
14934 }
14935 }
14936 }
14937
14938 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14939 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14940 // this). Also since this is only operating within a single scope it is likely too specific to C
14941 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14942 // use name qualification).
14943 // update the links after insertion!
14945 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(newStmt) != NULL) )
14946 {
14947 updateDefiningNondefiningLinks(isSgFunctionDeclaration(newStmt),scope);
14948 }
14949
14950#if 0
14951 printf ("In SageInterface::insertStatement(): at BASE of function \n");
14952 reportNodesMarkedAsModified(scope);
14953#endif
14954 }
14955
14956
14957void SageInterface::insertStatementList(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts, bool insertBefore)
14958 {
14959 if (insertBefore)
14960 {
14961 for (size_t i = 0; i < newStmts.size(); ++i)
14962 {
14963 insertStatementBefore(targetStmt, newStmts[i]);
14964 }
14965 }
14966 else
14967 {
14968 for (size_t i = newStmts.size(); i > 0; --i)
14969 {
14970 insertStatementAfter(targetStmt, newStmts[i - 1]);
14971 }
14972 }
14973 }
14974
14975void SageInterface::insertStatementAfter(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true*/)
14976 {
14977 insertStatement(targetStmt,newStmt,false, autoMovePreprocessingInfo);
14978 }
14979
14980void SageInterface::insertStatementListAfter(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14981 {
14982 insertStatementList(targetStmt,newStmts,false);
14983 }
14984
14987 {
14988 ROSE_ASSERT (stmt != NULL);
14989 ROSE_ASSERT (scope != NULL);
14990 // Insert to be the declaration after current declaration sequence, if any
14991 SgStatement* l_stmt = findLastDeclarationStatement (scope);
14992 if (l_stmt)
14993 insertStatementAfter(l_stmt,stmt);
14994 else
14995 prependStatement(stmt, scope);
14996 }
14997
14999void SageInterface::insertStatementAfterLastDeclaration(std::vector<SgStatement*> stmt_list, SgScopeStatement* scope)
15000 {
15001 ROSE_ASSERT (scope != NULL);
15002 vector <SgStatement* >::iterator iter;
15003 SgStatement* prev_stmt = NULL;
15004 for (iter= stmt_list.begin(); iter != stmt_list.end(); iter++)
15005 {
15006 if (iter == stmt_list.begin())
15007 {
15009 }
15010 else
15011 {
15012 ROSE_ASSERT (prev_stmt != NULL);
15013 insertStatementAfter (prev_stmt, *iter);
15014 }
15015 prev_stmt = *iter;
15016 }
15017 }
15018
15020{
15021 ROSE_ASSERT(newStmt!=NULL);
15022 ROSE_ASSERT(scope!=NULL);
15023 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
15024 if (!isSgDeclarationStatement(targetStmt)) {
15025 insertStatementBefore(targetStmt, newStmt, movePreprocessingInfo);
15026 return;
15027 }
15028 }
15029 appendStatement(newStmt, scope);
15030}
15031
15032void SageInterface::insertStatementListBeforeFirstNonDeclaration(const std::vector<SgStatement*> &newStmts,SgScopeStatement *scope)
15033{
15034 ROSE_ASSERT(scope!=NULL);
15035 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
15036 if (!isSgDeclarationStatement(targetStmt)) {
15037 insertStatementListBefore(targetStmt, newStmts);
15038 return;
15039 }
15040 }
15041 appendStatementList(newStmts, scope);
15042}
15043
15044void SageInterface::insertStatementBefore(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true */)
15045 {
15046 insertStatement(targetStmt,newStmt,true, autoMovePreprocessingInfo);
15047 }
15048
15049void SageInterface::insertStatementListBefore(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
15050 {
15051 insertStatementList(targetStmt,newStmts,true);
15052 }
15053
15054 //a wrapper for set_expression(), set_operand(), set_operand_exp() etc
15055 // special concern for lvalue, parent,
15056 // todo: warning overwriting existing operands
15058 {
15059 ROSE_ASSERT(target);
15060 ROSE_ASSERT(operand);
15061 ROSE_ASSERT(target!=operand);
15062 switch (target->variantT())
15063 {
15064 case V_SgActualArgumentExpression:
15065 isSgActualArgumentExpression(target)->set_expression(operand);
15066 break;
15067 case V_SgAsmOp:
15068 isSgAsmOp(target)->set_expression(operand);
15069 break;
15070 case V_SgSizeOfOp:
15071 isSgSizeOfOp(target)->set_operand_expr(operand);
15072 break;
15073 case V_SgTypeIdOp:
15074 isSgTypeIdOp(target)->set_operand_expr(operand);
15075 break;
15076 case V_SgVarArgOp:
15077 isSgVarArgOp(target)->set_operand_expr(operand);
15078 break;
15079 case V_SgVarArgStartOneOperandOp:
15080 isSgVarArgStartOneOperandOp(target)->set_operand_expr(operand);
15081 break;
15082 case V_SgAssignInitializer:
15083 isSgAssignInitializer (target)->set_operand(operand);
15084 break;
15085 default:
15086 if (isSgUnaryOp(target)!=NULL)
15087 isSgUnaryOp(target)->set_operand_i(operand);
15088 else
15089 {
15090 cerr<<"\tSageInterface::setOperand(): unhandled case for target expression of type "
15091 <<target->class_name()<<endl;
15092 ROSE_ABORT();
15093 }
15094 }// end switch
15095 operand->set_parent(target);
15096 markLhsValues(target);
15097 }
15098
15099 // binary and SgVarArgCopyOp, SgVarArgStartOp
15101 {
15102 ROSE_ASSERT(target);
15103 ROSE_ASSERT(lhs);
15104 ROSE_ASSERT(target!=lhs);
15105 bool hasrhs = false;
15106
15107 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
15108 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
15109 SgBinaryOp* binary = isSgBinaryOp(target);
15110
15111 if (varargcopy!=NULL)
15112 {
15113 varargcopy->set_lhs_operand(lhs);
15114 if( varargcopy->get_rhs_operand()!=NULL) hasrhs= true;
15115 }
15116 else if(varargstart!=NULL)
15117 {
15118 varargstart->set_lhs_operand(lhs);
15119 if( varargstart->get_rhs_operand()!=NULL) hasrhs= true;
15120 }
15121 else if(binary!=NULL)
15122 {
15123 binary->set_lhs_operand(lhs);
15124 if( binary->get_rhs_operand()!=NULL) hasrhs= true;
15125 }
15126 else
15127 {
15128 cout<<"SageInterface::setLhsOperand(): unhandled case for target expression of type "
15129 <<target->class_name()<<endl;
15130 ROSE_ABORT();
15131 }
15132 lhs->set_parent(target);
15133// only when both lhs and rhs are available, can we set lvalue
15134// there is assertion(rhs!=NULL) in markLhsValues()
15135 if (hasrhs)
15136 markLhsValues(target);
15137 }
15138
15140 {
15141 ROSE_ASSERT(target);
15142 ROSE_ASSERT(rhs);
15143 ROSE_ASSERT(target!=rhs);
15144 bool haslhs = false;
15145
15146 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
15147 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
15148 SgBinaryOp* binary = isSgBinaryOp(target);
15149
15150 if (varargcopy!=NULL)
15151 {
15152 varargcopy->set_rhs_operand(rhs);
15153 if( varargcopy->get_lhs_operand()!=NULL) haslhs= true;
15154 }
15155 else if(varargstart!=NULL)
15156 {
15157 varargstart->set_rhs_operand(rhs);
15158 if( varargstart->get_lhs_operand()!=NULL) haslhs= true;
15159 }
15160 else if(binary!=NULL)
15161 {
15162 binary->set_rhs_operand(rhs);
15163 if( binary->get_lhs_operand()!=NULL) haslhs= true;
15164 }
15165 else
15166 {
15167 cout<<"SageInterface::setRhsOperand(): unhandled case for target expression of type "
15168 <<target->class_name()<<endl;
15169 ROSE_ABORT();
15170 }
15171 rhs->set_parent(target);
15172// only when both lhs and rhs are available, can we set lvalue
15173 if (haslhs)
15174 markLhsValues(target);
15175 }
15176
15177// DQ (1/25/2010): Added to simplify handling of directories (e.g. for code generation).
15178void SageInterface::moveToSubdirectory ( std::string directoryName, SgFile* file )
15179 {
15180 // This support makes use of the new SgDirectory IR node. It causes the unparser to
15181 // generate a subdirectory and unparse the file into the subdirectory. It works
15182 // by internally calling the system function "system()" to call "mkdir directoryName"
15183 // and then chdir()" to change the current directory. These steps are handled by the
15184 // unparser.
15185
15186 // This function just does the transformation to insert a SgDirectory IR node between
15187 // the referenced SgFile and it's project (fixing up parents and file lists etc.).
15188
15189 // Add a directory and unparse the code (to the new directory)
15190 SgDirectory* directory = new SgDirectory(directoryName);
15191
15192 SgFileList* parentFileList = isSgFileList(file->get_parent());
15193 ROSE_ASSERT(parentFileList != NULL);
15194 directory->set_parent(file->get_parent());
15195
15196 SgProject* project = NULL;
15197 SgDirectory* parentDirectory = isSgDirectory(parentFileList->get_parent());
15198
15199 if (parentDirectory != NULL)
15200 {
15201 // Add a directory to the list in the SgDirectory node.
15202 parentDirectory->get_directoryList()->get_listOfDirectories().push_back(directory);
15203
15204 // Erase the reference to the file in the project's file list.
15205 // parentDirectory->get_fileList().erase(find(parentDirectory->get_fileList().begin(),parentDirectory->get_fileList().end(),file));
15206 }
15207 else
15208 {
15209 project = isSgProject(parentFileList->get_parent());
15210 ROSE_ASSERT(project != NULL);
15211
15212 // Add a directory to the list in the SgProject node.
15213 project->get_directoryList()->get_listOfDirectories().push_back(directory);
15214
15215 // Erase the reference to the file in the project's file list.
15216 // project->get_fileList().erase(find(project->get_fileList().begin(),project->get_fileList().end(),file));
15217 }
15218
15219 // Put the file into the new directory.
15220 directory->get_fileList()->get_listOfFiles().push_back(file);
15221
15222 // Erase the reference to the file in the project's file list.
15223 parentFileList->get_listOfFiles().erase(find(parentFileList->get_listOfFiles().begin(),parentFileList->get_listOfFiles().end(),file));
15224
15225 file->set_parent(directory);
15226}
15227
15228
15229//------------------------- AST repair----------------------------
15230//----------------------------------------------------------------
15232 {
15233 ROSE_ASSERT(structDecl != NULL);
15234 ROSE_ASSERT(scope != NULL);
15235 SgClassDeclaration* nondefdecl = isSgClassDeclaration(structDecl->get_firstNondefiningDeclaration());
15236 ROSE_ASSERT(nondefdecl != NULL);
15237
15238 // ROSE_ASSERT(structDecl->get_definingDeclaration() != NULL);
15239 SgClassDeclaration* defdecl = isSgClassDeclaration(structDecl->get_definingDeclaration());
15240 // ROSE_ASSERT(defdecl != NULL);
15241
15242 // Liao, 9/2/2009
15243 // fixup missing scope when bottomup AST building is used
15244 if (structDecl->get_scope() == NULL)
15245 structDecl->set_scope(scope);
15246 if (nondefdecl->get_scope() == NULL)
15247 nondefdecl->set_scope(scope);
15248
15249#if 0
15250 if (structDecl->get_parent() == NULL)
15251 structDecl->set_parent(scope);
15252 if (nondefdecl->get_parent() == NULL)
15253 nondefdecl->set_parent(scope);
15254#else
15255 // 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");
15256
15257 // DQ (7/21/2012): Can we assert this here? NO!
15258 // ROSE_ASSERT(structDecl->get_parent() == NULL);
15259 // ROSE_ASSERT(nondefdecl->get_parent() == NULL);
15260#endif
15261
15262 SgName name = structDecl->get_name();
15263
15264 // This is rare case (translation error) when scope->lookup_class_symbol(name) will find something
15265 // but nondefdecl->get_symbol_from_symbol_table() returns NULL
15266 // But symbols are associated with nondefining declarations whenever possible
15267 // and AST consistent check will check the nondefining declarations first
15268 // Liao, 9/2/2009
15269 // SgClassSymbol* mysymbol = scope->lookup_class_symbol(name);
15270 SgClassSymbol* mysymbol = isSgClassSymbol(nondefdecl->get_symbol_from_symbol_table());
15271
15272 // DQ (3/14/2014): This is false for a copy of a class declaration being inserted into the AST.
15273 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15274 // ROSE_ASSERT(mysymbol != NULL);
15275
15276 if (mysymbol == NULL)
15277 {
15278 printf ("Note: SageInterface::fixStructDeclaration(): structDecl = %p nondefdecl = %p (mysymbol == NULL) \n",structDecl,nondefdecl);
15279
15280 // 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...
15281 // DQ (12/4/2011): Only generate symbols and set the scope if this is the correct scope.
15282 ROSE_ASSERT(structDecl->get_scope() != NULL);
15283
15284 if (scope == structDecl->get_scope())
15285 {
15286 mysymbol = new SgClassSymbol(nondefdecl);
15287 ROSE_ASSERT(mysymbol);
15288
15289 // I need to check the rest of these functions.
15290 printf ("############## DANGER:DANGER:DANGER ################\n");
15291
15292 printf ("In SageInterface::fixStructDeclaration(): Adding class symbol to scope = %p = %s \n",scope,scope->class_name().c_str());
15293 scope->insert_symbol(name, mysymbol);
15294
15295 // ROSE_ASSERT(defdecl != NULL);
15296 if (defdecl)
15297 defdecl->set_scope(scope);
15298 nondefdecl->set_scope(scope);
15299
15300 printf ("*** WARNING: In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Commented out the setting of the parent to be the same as the scope \n");
15301#if 0
15302 if (defdecl)
15303 defdecl->set_parent(scope);
15304 nondefdecl->set_parent(scope);
15305#endif
15306 }
15307 else
15308 {
15309 printf ("In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Skipped building an associated symbol! \n");
15310 }
15311 }
15312
15313 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15314 ROSE_ASSERT(nondefdecl->get_type() != NULL);
15315
15316 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15317 ROSE_ASSERT(nondefdecl->get_type()->variantT() != V_SgNode);
15318
15319 // DQ (9/4/2012): This should be a SgClassType IR node.
15320 ROSE_ASSERT(isSgClassType(nondefdecl->get_type()) != NULL);
15321
15322 // fixup SgClassType, which is associated with the first non-defining declaration only
15323 // and the other declarations share it.
15324 if (nondefdecl->get_type() == NULL)
15325 {
15326 nondefdecl->set_type(SgClassType::createType(nondefdecl));
15327 }
15328 ROSE_ASSERT (nondefdecl->get_type() != NULL);
15329
15330 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15331 if (defdecl != NULL)
15332 {
15333 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15334 ROSE_ASSERT(defdecl->get_type()->variantT() != V_SgNode);
15335
15336 // DQ (9/4/2012): This should be a SgClassType IR node.
15337 ROSE_ASSERT(isSgClassType(defdecl->get_type()) != NULL);
15338 }
15339
15340 // ROSE_ASSERT(defdecl != NULL);
15341 if (defdecl != NULL)
15342 {
15343 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15344 ROSE_ASSERT(defdecl->get_type() != NULL);
15345 if (defdecl->get_type() != nondefdecl->get_type())
15346 {
15347 printf ("ERROR: defdecl->get_type() != nondefdecl->get_type(): what are these: \n");
15348 printf (" defdecl->get_type() = %p = %s \n",defdecl ->get_type(),defdecl ->get_type()->class_name().c_str());
15349 SgNamedType* namedType_definingDecl = isSgNamedType(defdecl->get_type());
15350 if (namedType_definingDecl != NULL)
15351 {
15352 printf ("namedType_definingDecl->get_declaration() = %p = %s \n",namedType_definingDecl->get_declaration(),namedType_definingDecl->get_declaration()->class_name().c_str());
15353 }
15354 printf (" nondefdecl->get_type() = %p = %s \n",nondefdecl->get_type(),nondefdecl->get_type()->class_name().c_str());
15355 SgNamedType* namedType_nondefiningDecl = isSgNamedType(nondefdecl->get_type());
15356 if (namedType_nondefiningDecl != NULL)
15357 {
15358 printf ("namedType_nondefiningDecl->get_declaration() = %p = %s \n",namedType_nondefiningDecl->get_declaration(),namedType_nondefiningDecl->get_declaration()->class_name().c_str());
15359 }
15360 }
15361 //ROSE_ASSERT(defdecl->get_type() == nondefdecl->get_type());
15362 }
15363 }
15364
15365
15367 {
15368 fixStructDeclaration(classDecl,scope);
15369 }
15370
15371
15373 {
15374 ROSE_ASSERT(structDecl);
15375 ROSE_ASSERT(scope);
15376 SgNamespaceDeclarationStatement* nondefdecl = isSgNamespaceDeclarationStatement(structDecl->get_firstNondefiningDeclaration());
15377 ROSE_ASSERT(nondefdecl);
15378 // Liao, 9/2/2009
15379 // fixup missing scope when bottomup AST building is used
15380 if (structDecl->get_parent() == NULL)
15381 structDecl->set_parent(scope);
15382 if (nondefdecl->get_parent() == NULL)
15383 nondefdecl->set_parent(scope);
15384
15385 // tps : (09/03/2009) Namespace should not have a scope
15386 /*
15387 if (structDecl->get_scope() == NULL)
15388 structDecl->set_scope(scope);
15389 if (nondefdecl->get_scope() == NULL)
15390 nondefdecl->set_scope(scope);
15391 */
15392
15393 SgName name= structDecl->get_name();
15394 // SgNamespaceSymbol* mysymbol = scope->lookup_namespace_symbol(name);
15395 SgNamespaceSymbol* mysymbol = isSgNamespaceSymbol(nondefdecl->get_symbol_from_symbol_table());
15396 if (mysymbol==NULL)
15397 {
15398 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15399 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15400 if (scope == structDecl->get_scope())
15401 {
15402 mysymbol = new SgNamespaceSymbol(name,nondefdecl);
15403 ROSE_ASSERT(mysymbol);
15404
15405 printf ("In SageInterface::fixNamespaceDeclaration(): inserting namespace symbol into scope = %p = %s \n",scope,scope->class_name().c_str());
15406 scope->insert_symbol(name, mysymbol);
15407
15408 SgNamespaceDeclarationStatement* defdecl = isSgNamespaceDeclarationStatement(structDecl->get_definingDeclaration());
15409 ROSE_ASSERT(defdecl);
15410 defdecl->set_scope(scope);
15411 nondefdecl->set_scope(scope);
15412
15413 defdecl->set_parent(scope);
15414 nondefdecl->set_parent(scope);
15415 }
15416 }
15417 }
15418
15419#define DEBUG__SageInterface__fixVariableDeclaration 0
15420
15422 {
15423 ROSE_ASSERT(varDecl != NULL);
15424 ROSE_ASSERT(scope != NULL);
15425
15426 SgInitializedNamePtrList namelist = varDecl->get_variables();
15427 SgTemplateVariableInstantiation * tplinst = isSgTemplateVariableInstantiation(varDecl);
15428
15429 // printf ("In SageInterface::fixVariableDeclaration(): Is this a recursive call! \n");
15430
15431#if DEBUG__SageInterface__fixVariableDeclaration
15432 printf ("In SageInterface::fixVariableDeclaration():\n");
15433 printf (" varDecl = %p scope = %p = %s \n", varDecl);
15434 printf (" scope = %p : %s \n", scope, scope->class_name().c_str());
15435#endif
15436
15437 ROSE_ASSERT(namelist.size() > 0);
15438
15439 SgInitializedNamePtrList::iterator i;
15440 for (i = namelist.begin(); i != namelist.end(); i++)
15441 {
15442 SgInitializedName *initName = *i;
15443 ROSE_ASSERT(initName != NULL);
15444#if DEBUG__SageInterface__fixVariableDeclaration
15445 printf (" initName = %p\n", initName);
15446 printf (" initName->get_scope() = %p : %s\n", initName->get_scope(), initName->get_scope() ? initName->get_scope()->class_name().c_str() : "");
15447#endif
15448
15449 SgName name = initName->get_name();
15450#if DEBUG__SageInterface__fixVariableDeclaration
15451 printf (" name = %s\n", name.str());
15452#endif
15453 if (tplinst) {
15454 name = appendTemplateArgumentsToName(name, tplinst->get_templateArguments());
15455 }
15456#if DEBUG__SageInterface__fixVariableDeclaration
15457 printf (" name = %s\n", name.str());
15458#endif
15459
15460 // DQ (11/19/2011): When used with C++, the variable may already have an associated scope
15461 // and be using name qualification, so might not be associated with the current scope.
15462 SgScopeStatement* requiredScope = scope;
15463 SgScopeStatement* preAssociatedScope = initName->get_scope();
15464 if (preAssociatedScope != NULL) {
15465 requiredScope = preAssociatedScope;
15466 }
15467
15468 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15469 initName->set_scope(requiredScope);
15470 if (topScopeStack() != NULL) {
15471 varDecl->set_parent(topScopeStack());
15472 ROSE_ASSERT(varDecl->get_parent() != NULL);
15473 }
15474 ROSE_ASSERT(requiredScope != NULL);
15475 SgVariableSymbol* varSymbol = requiredScope->lookup_variable_symbol(name);
15476#if DEBUG__SageInterface__fixVariableDeclaration
15477 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15478#endif
15479 if (varSymbol == NULL) {
15480 if (scope == initName->get_scope()) {
15481 if (isSgTemplateVariableDeclaration(varDecl)) {
15482 varSymbol = new SgTemplateVariableSymbol(initName);
15483 } else {
15484 varSymbol = new SgVariableSymbol(initName);
15485 }
15486 ROSE_ASSERT(varSymbol);
15487 scope->insert_symbol(name, varSymbol);
15488 }
15489 } else {
15490 SgInitializedName* prev_decl = varSymbol->get_declaration();
15491 ROSE_ASSERT(prev_decl);
15492 if (initName != prev_decl) {
15493 initName->set_prev_decl_item(prev_decl);
15494 }
15495 ROSE_ASSERT(initName->get_prev_decl_item() != initName);
15496 }
15497#if DEBUG__SageInterface__fixVariableDeclaration
15498 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15499#endif
15500 } //end for
15501
15502 // Liao 12/8/2010
15503 // For Fortran, a common statement may refer to a variable which is declared later.
15504 // In this case, a fake symbol is used for that variable reference.
15505 // But we have to replace the fake one with the real one once the variable declaration is inserted into AST
15507 {
15508 fixVariableReferences(scope);
15509 }
15510 }
15511
15512int SageInterface::fixVariableReferences(SgNode* root, bool cleanUnusedSymbols/*=true*/)
15513{
15514 ROSE_ASSERT(root);
15515 int counter=0;
15516 Rose_STL_Container<SgNode*> varList;
15517
15518 SgVarRefExp* varRef=NULL;
15519 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(root, V_SgVarRefExp);
15520 for (Rose_STL_Container<SgNode*>::iterator i=reflist.begin();i!=reflist.end();i++)
15521 {
15522 varRef= isSgVarRefExp(*i);
15523 ROSE_ASSERT(varRef->get_symbol());
15524 SgInitializedName* initname= varRef->get_symbol()->get_declaration();
15525
15526 ROSE_ASSERT (initname != NULL);
15527 if (initname->get_type()==SgTypeUnknown::createType())
15528 {
15529 SgName varName=initname->get_name();
15530 SgSymbol* realSymbol = NULL;
15531
15532#if 1
15533 // CH (5/7/2010): Before searching SgVarRefExp objects, we should first deal with class/structure
15534 // members. Or else, it is possible that we assign the wrong symbol to those members if there is another
15535 // variable with the same name in parent scopes. Those members include normal member referenced using . or ->
15536 // operators, and static members using :: operators.
15537 //
15538 if (SgArrowExp* arrowExp = isSgArrowExp(varRef->get_parent()))
15539 {
15540 if (varRef == arrowExp->get_rhs_operand_i())
15541 {
15542 // make sure the lhs operand has been fixed
15543 counter += fixVariableReferences(arrowExp->get_lhs_operand_i());
15544 SgType* lhs_type = arrowExp->get_lhs_operand_i()->get_type() ;
15545 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15546 SgPointerType* ptrType = isSgPointerType(lhs_type);
15547 ROSE_ASSERT(ptrType);
15548 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));
15549 ROSE_ASSERT(clsType);
15550 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15551 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15552 ROSE_ASSERT(decl);
15553
15554 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15555 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15556 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15557 }
15558 else
15559 {
15560 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15561 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15562 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15563 }
15564 }
15565 else if (SgDotExp* dotExp = isSgDotExp(varRef->get_parent()))
15566 {
15567 if (varRef == dotExp->get_rhs_operand_i())
15568 {
15569 // make sure the lhs operand has been fixed
15570 counter += fixVariableReferences(dotExp->get_lhs_operand_i());
15571
15572 SgType* lhs_type = dotExp->get_lhs_operand_i()->get_type() ;
15573 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15574 SgClassType* clsType = isSgClassType(lhs_type);
15575 ROSE_ASSERT(clsType);
15576 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15577 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15578 ROSE_ASSERT(decl);
15579
15580 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15581 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15582 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15583 }
15584 else
15585 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15586 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15587 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15588 }
15589 else
15590#endif
15591 {
15592 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15593 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15594 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15595 }
15596
15597 // should find a real symbol at this final fixing stage!
15598 // This function can be called any time, not just final fixing stage
15599 if (realSymbol==NULL)
15600 {
15601 //cerr<<"Error: cannot find a symbol for "<<varName.getString()<<endl;
15602 //ROSE_ASSERT(realSymbol);
15603 }
15604 else {
15605 // release placeholder initname and symbol
15606 ROSE_ASSERT(realSymbol!=(varRef->get_symbol()));
15607#if 0
15608 // CH (5/12/2010):
15609 // To delete a symbol node, first check if there is any node in memory
15610 // pool which points to this symbol node. Only if no such node exists,
15611 // this symbol together with its initialized name can be deleted.
15612 //
15613 bool toDelete = true;
15614
15615 SgSymbol* symbolToDelete = varRef->get_symbol();
15616 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15617 counter ++;
15618
15619 if (varList.empty())
15620 {
15621 VariantVector vv(V_SgVarRefExp);
15622 varList = NodeQuery::queryMemoryPool(vv);
15623 }
15624
15625 for (Rose_STL_Container<SgNode*>::iterator i = varList.begin();
15626 i != varList.end(); ++i)
15627 {
15628 if (SgVarRefExp* var = isSgVarRefExp(*i))
15629 {
15630 if (var->get_symbol() == symbolToDelete)
15631 {
15632 toDelete = false;
15633 break;
15634 }
15635 }
15636 }
15637 if (toDelete)
15638 {
15639 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15640 delete symbolToDelete;
15641 }
15642
15643#else
15644
15645 // CH (2010/7/26): We cannot delete those initname and symbol here, since there may be other variable references
15646 // which point to them. We will delay this clear just before AstTests.
15647#if 0
15648 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15649 delete (varRef->get_symbol());
15650#endif
15651
15652 //std::cout << "Fixed variable reference: " << realSymbol->get_name().str() << std::endl;
15653 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15654 counter ++;
15655#endif
15656 }
15657 }
15658 } // end for
15659 // Liao 2/1/2013: delete unused initname and symbol, considering possible use by the current subtree from root node
15660 if (cleanUnusedSymbols)
15662 return counter;
15663}
15664
15666{
15667 Rose_STL_Container<SgNode*> symbolList;
15668 VariantVector sym_vv(V_SgVariableSymbol);
15669 symbolList = NodeQuery::queryMemoryPool(sym_vv);
15670
15671 Rose_STL_Container<SgNode*> varList;
15672 VariantVector var_vv(V_SgVarRefExp);
15673 //varList = NodeQuery::queryMemoryPool(var_vv);
15674 if (root != NULL)
15675 {
15676 varList = NodeQuery::querySubTree(root, V_SgVarRefExp);
15677 }
15678
15679 for (Rose_STL_Container<SgNode*>::iterator i = symbolList.begin();
15680 i != symbolList.end(); ++i)
15681 {
15682 SgVariableSymbol* symbolToDelete = isSgVariableSymbol(*i);
15683 ROSE_ASSERT(symbolToDelete);
15684 if (symbolToDelete->get_declaration()->get_type() != SgTypeUnknown::createType())
15685 continue;
15686 // symbol with a declaration of SgTypeUnknown will be deleted
15687 bool toDelete = true;
15688
15689 if (root != NULL) // if root is specified. We further check if the symbol is referenced by any nodes of the tree rooted at "root"
15690 {
15691 for (Rose_STL_Container<SgNode*>::iterator j = varList.begin();
15692 j != varList.end(); ++j)
15693 {
15694 SgVarRefExp* var = isSgVarRefExp(*j);
15695 ROSE_ASSERT(var);
15696
15697 if (var->get_symbol() == symbolToDelete)
15698 {
15699 toDelete = false;
15700 break;
15701 }
15702 }
15703 }
15704
15705 if (toDelete)
15706 {
15707#if 0
15708 std::cout << "Symbol " << symbolToDelete->get_name().str() << ' ' << symbolToDelete <<
15709 ' ' << symbolToDelete->get_declaration() << " is deleted." << std::endl;
15710#endif
15711 delete symbolToDelete->get_declaration();
15712 delete symbolToDelete;
15713 }
15714 }
15715}
15716
15717
15719/*
15720 * label statement has special scope: the closest function definition , not SgBasicBlock or others!
15721 */
15723 {
15724 SgLabelStatement* label_stmt = isSgLabelStatement(stmt);
15725 ROSE_ASSERT(label_stmt);
15726 SgName name = label_stmt->get_label();
15727
15728 // PP (07/18/23): In Ada, label symbols should be inserted in the current scope's symbol table
15729 const bool symbolAtFunctionLevel = !is_Ada_language();
15730 SgScopeStatement* label_scope = symbolAtFunctionLevel ? getEnclosingFunctionDefinition(scope,true)
15731 : scope;
15732
15733 // DQ (11/16/2014): Added error checking for when the input scope is the SgFunctionDefinition instead of a nested scope.
15734 if (isSgFunctionDefinition(scope) != nullptr)
15735 {
15736 ASSERT_not_null(label_scope);
15737 }
15738
15739 if (label_scope) //Should we assert this instead? No for bottom up AST building
15740 {
15741 label_stmt->set_scope(label_scope);
15742 SgLabelSymbol* lsymbol = label_scope->lookup_label_symbol(name);
15743
15744 if (lsymbol == nullptr)
15745 {
15746 // SgLabelStatement should always be in the function scope
15747 // PP (07/18/23): in Ada symbols should be at the innermost scope
15748 lsymbol= new SgLabelSymbol(label_stmt);
15749 ASSERT_not_null(lsymbol);
15750 label_scope->insert_symbol(lsymbol->get_name(), lsymbol);
15751 }
15752 }
15753 }
15754
15755
15757//efExp are created transparently as needed.
15759 SgLabelSymbol::label_type_enum label_type, SgScopeStatement* label_scope)
15760 {
15761 ROSE_ASSERT (stmt != NULL);
15762 ROSE_ASSERT (label_value >0 && label_value <=99999); //five digits for Fortran label
15763
15764 // Added optional label_type and label_scope [Rasmussen 2019.01.20]
15765 if (label_scope == NULL)
15766 {
15767 label_scope = getEnclosingFunctionDefinition(stmt);
15768 }
15769 ROSE_ASSERT (label_scope != NULL);
15770 SgName label_name(StringUtility::numberToString(label_value));
15771 SgLabelSymbol * symbol = label_scope->lookup_label_symbol (label_name);
15772 if (symbol == NULL)
15773 {
15774 // DQ (12/4/2011): This is the correct handling for SgLabelStatement (always in the function scope, same as C and C++).
15775 // DQ (2/2/2011): We want to call the old constructor (we now have another constructor that takes a SgInitializedName pointer).
15776 // symbol = new SgLabelSymbol(NULL);
15777 symbol = new SgLabelSymbol((SgLabelStatement*) NULL);
15778 ROSE_ASSERT(symbol != NULL);
15779 symbol->set_fortran_statement(stmt);
15780 symbol->set_numeric_label_value(label_value);
15781 label_scope->insert_symbol(label_name,symbol);
15782 }
15783 else
15784 {
15785 cerr<<"Error. SageInterface::setFortranNumericLabel() tries to set a duplicated label value!"<<endl;
15786 ROSE_ASSERT (false);
15787 }
15788
15789 // SgLabelRefExp
15790 SgLabelRefExp* ref_exp = buildLabelRefExp(symbol);
15791 ref_exp->set_parent(stmt);
15792
15793 switch(label_type)
15794 {
15795 case SgLabelSymbol::e_start_label_type:
15796 {
15797 stmt->set_numeric_label(ref_exp);
15798 break;
15799 }
15800 case SgLabelSymbol::e_end_label_type:
15801 {
15802 stmt->set_end_numeric_label(ref_exp);
15803 break;
15804 }
15805 default:
15806 {
15807 std::cerr << "SageInterface::setFortranNumericLabel: unimplemented for label_type " << label_type << "\n";
15808 ROSE_ABORT(); // NOT IMPLEMENTED
15809 }
15810 }
15811
15812 }
15813
15814
15817{
15818 int result =10;
15819 ROSE_ASSERT (func_def != NULL);
15820 ROSE_ASSERT (SageInterface::is_Fortran_language()== true);
15821 std::set<SgNode*> symbols = func_def->get_symbol_table()->get_symbols();
15822
15823 // find the max label value, +10 to be the suggested next label value
15824 std::set<SgNode*>::iterator iter ;
15825 for (iter=symbols.begin(); iter !=symbols.end(); iter++)
15826 {
15827 SgLabelSymbol * l_symbol = isSgLabelSymbol(*iter);
15828 if (l_symbol)
15829 {
15830 int cur_val = l_symbol->get_numeric_label_value();
15831 if (result <=cur_val)
15832 result = cur_val +10;
15833 }
15834 }
15835
15836 ROSE_ASSERT (result <= 99999); // max 5 digits for F77 label
15837 return result;
15838}
15839
15841/*
15842 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15843 */
15845 {
15846 // DQ (3/5/2012): Added test.
15847 ROSE_ASSERT(scope != NULL);
15848
15849 // fix function type table's parent edge
15850 // Liao 5/4/2010
15852 ROSE_ASSERT(fTable != NULL);
15853
15854 if (fTable->get_parent() == NULL)
15855 {
15856 // DQ (3/5/2012): This is a problem for test2012_13.C (test code taken from test2004_42.C).
15857 // fTable->set_parent(getGlobalScope(scope));
15858#if 0
15859 printf ("WARNING: Skip setting the scope of the SgFunctionTypeTable scope = %p = %s \n",scope,scope->class_name().c_str());
15860#endif
15861 fTable->set_parent(getGlobalScope(scope));
15862 }
15863
15864#if 0
15865 printf ("In SageInterface::fixStatement(): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15866#endif
15867
15868 // Liao 4/23/2010, Fix function symbol
15869 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15870 // Added SgProgramHeaderStatement [Rasmussen, 2020.01.19]
15871 SgFunctionDeclaration * func = isSgFunctionDeclaration(stmt);
15872 SgMemberFunctionDeclaration * mfunc = isSgMemberFunctionDeclaration(stmt);
15873 SgTemplateFunctionDeclaration * tfunc = isSgTemplateFunctionDeclaration(stmt);
15874 SgTemplateMemberFunctionDeclaration * tmfunc = isSgTemplateMemberFunctionDeclaration(stmt);
15875 SgProcedureHeaderStatement * procfunc = isSgProcedureHeaderStatement(stmt);
15876 SgProgramHeaderStatement * progfunc = isSgProgramHeaderStatement(stmt);
15877
15878 if (tmfunc != NULL)
15879 assert(tmfunc->variantT() == V_SgTemplateMemberFunctionDeclaration);
15880 else if (mfunc != NULL)
15881 assert(mfunc->variantT() == V_SgMemberFunctionDeclaration || mfunc->variantT() == V_SgTemplateInstantiationMemberFunctionDecl);
15882 else if (tfunc != NULL)
15883 assert(tfunc->variantT() == V_SgTemplateFunctionDeclaration);
15884 else if (procfunc != NULL)
15885 assert(procfunc->variantT() == V_SgProcedureHeaderStatement);
15886 else if (progfunc != NULL)
15887 assert(progfunc->variantT() == V_SgProgramHeaderStatement);
15888 else if (func != NULL)
15889 assert(func->variantT() == V_SgFunctionDeclaration || func->variantT() == V_SgTemplateInstantiationFunctionDecl);
15890 else ROSE_ABORT();
15891
15892#if 0
15893 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15894 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15895#endif
15896
15897 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15898 // It is an error to put the symbol for a function into the current scope if the function's scope
15899 // is explicitly set to be different. So this should be allowed only if the function's scope is
15900 // not explicitly set, or if the scopes match. This is an example of something different for C++
15901 // than for C or other simpler languages.
15902 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15903 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15904 {
15905#if 0
15906 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());
15907#endif
15908 SgFunctionSymbol* func_symbol = NULL;
15909
15910 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
15911 // In this case these are unavailable from this point.
15912 if (tmfunc != NULL)
15913 {
15914 SgTemplateParameterPtrList & templateParameterList = tmfunc->get_templateParameters();
15915 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type());
15916 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),NULL);
15917 func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15918 }
15919 else if (mfunc != NULL)
15920 {
15921 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(mfunc);
15922 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationMemberFunctionDecl != NULL) ? &(templateInstantiationMemberFunctionDecl->get_templateArguments()) : NULL;
15923 // func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),NULL);
15924 func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15925 }
15926 else if (tfunc != NULL)
15927 {
15928 SgTemplateParameterPtrList & templateParameterList = tfunc->get_templateParameters();
15929#if 0
15930 printf ("In SageInterface::fixStatement(): templateParameterList.size() = %" PRIuPTR " \n",templateParameterList.size());
15931#endif
15932 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type());
15933 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),NULL);
15934 func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15935 }
15936 else if (procfunc != NULL)
15937 {
15938#if 0
15939 printf ("In SageInterface::fixStatement(): procfunc->get_name() = %s calling lookup_function_symbol() \n",procfunc->get_name().str());
15940#endif
15941 func_symbol = scope->lookup_function_symbol (procfunc->get_name(), procfunc->get_type());
15942 assert(func_symbol != NULL);
15943 }
15944 else if (progfunc != NULL)
15945 {
15946 func_symbol = scope->lookup_function_symbol (progfunc->get_name(), progfunc->get_type());
15947 assert(func_symbol != NULL);
15948 }
15949 else if (func != NULL)
15950 {
15951#if 0
15952 printf ("In SageInterface::fixStatement(): func->get_name() = %s calling lookup_function_symbol() \n",func->get_name().str());
15953#endif
15954 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(func);
15955 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationFunctionDecl != NULL) ? &(templateInstantiationFunctionDecl->get_templateArguments()) : NULL;
15956 // func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),NULL);
15957 func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15958
15959 // 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
15960 // 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
15961 // opportunity to fixup the function to have a symbol in the scope's symbol table.
15962 if (func_symbol == NULL)
15963 {
15964 // scope->print_symboltable("In SageInterface::fixStatement()");
15965 func_symbol = new SgFunctionSymbol(func);
15966 scope->insert_symbol(func->get_name(), func_symbol);
15967 }
15968 }
15969 else
15970 {
15971 ROSE_ABORT();
15972 }
15973#if 0
15974 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15975#endif
15976 assert(func_symbol != NULL);
15977 }
15978 }
15979
15981/*
15982 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15983 */
15985 {
15986 // DQ (12/4/2011): This function has not been implemented yet. It will assert fail if it is required.
15987 printf ("Need to handle SgTemplateDeclaration IR nodes as well...(implement later) \n");
15988 }
15989
15990
15993 {
15994 // fix symbol table
15995 if (isSgVariableDeclaration(stmt))
15996 {
15997 fixVariableDeclaration(isSgVariableDeclaration(stmt), scope);
15998 }
15999 else if (isStructDeclaration(stmt))
16000 {
16001 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
16002 ROSE_ASSERT(classDeclaration != nullptr);
16003 fixStructDeclaration(classDeclaration,scope);
16004 }
16005 else if (isSgClassDeclaration(stmt))
16006 {
16007 fixClassDeclaration(isSgClassDeclaration(stmt),scope);
16008 }
16009 else if (isSgLabelStatement(stmt))
16010 {
16011 fixLabelStatement(isSgLabelStatement(stmt),scope);
16012 }
16013 else if (isSgFunctionDeclaration(stmt))
16014 {
16015#if 1
16016 fixFunctionDeclaration(isSgFunctionDeclaration(stmt),scope);
16017#else
16018 // fix function type table's parent edge
16019 // Liao 5/4/2010
16021 ROSE_ASSERT(fTable);
16022 if (fTable->get_parent() == NULL)
16023 fTable->set_parent(getGlobalScope(scope));
16024
16025 // Liao 4/23/2010, Fix function symbol
16026 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
16027 SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt);
16028 SgMemberFunctionDeclaration* mfunc = isSgMemberFunctionDeclaration(stmt);
16029
16030 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
16031 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
16032
16033 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
16034 // It is an error to put the symbol for a function into the current scope if the function's scope
16035 // is explicitly set to be different. So this should be allowed only if the function's scope is
16036 // not explicitly set, or if the scopes match. This is an example of something different for C++
16037 // than for C or other simpler languages.
16038 // If the scope of the function is not set, or if it matches the current scope then allow this step.
16039 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
16040 {
16041#if 0
16042 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());
16043#endif
16044 SgFunctionSymbol* func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type());
16045
16046 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
16047 if (func_symbol == NULL)
16048 {
16049 // DQ (12/3/2011): Added support for C++ member functions.
16050 // func_symbol = new SgFunctionSymbol (func);
16051 if (mfunc != NULL)
16052 {
16053 func_symbol = new SgMemberFunctionSymbol (func);
16054 }
16055 else
16056 {
16057 func_symbol = new SgFunctionSymbol (func);
16058 }
16059 ROSE_ASSERT (func_symbol != NULL);
16060
16061 scope->insert_symbol(func->get_name(), func_symbol);
16062 }
16063 else
16064 {
16065 printf ("In SageInterface::fixStatement(): found a valid function so no need to insert new symbol \n");
16066 }
16067 }
16068#if 0
16069 // Fix local symbol, a symbol directly refer to this function declaration
16070 // This could happen when a non-defining func decl is copied, the corresonding symbol will point to the original source func
16071 // symbolTable->find(this) used inside get_symbol_from_symbol_table() won't find the copied decl
16072 SgSymbol* local_symbol = func ->get_symbol_from_symbol_table();
16073 if (local_symbol == NULL) //
16074 {
16075 if (func->get_definingDeclaration() == NULL) // prototype function
16076 {
16077 SgFunctionDeclaration * src_func = func_symbol->get_declaration();
16078 if (func != src_func )
16079 {
16080 ROSE_ASSERT (src_func->get_firstNondefiningDeclaration () == src_func);
16081 func->set_firstNondefiningDeclaration (func_symbol->get_declaration());
16082 }
16083 }
16084 }
16085#endif
16086#endif
16087 }
16088 else if (isSgTemplateDeclaration(stmt) != NULL)
16089 {
16090 // DQ (12/3/2011): Added new case for SgTemplateDeclaration (adding template declarations to the AST).
16091 fixTemplateDeclaration(isSgTemplateDeclaration(stmt),scope);
16092 }
16093
16094#if 0
16095 // DQ (12/4/2011): This WAS not the correct behavior for C++ since declarations can appear structureally in different
16096 // scopes than where the are positioned (e.g. member functions defined outside of there associated class).
16097 // This this code is very dangerous.
16098
16099 // fix scope pointer for statements explicitly storing scope pointer
16100 switch (stmt->variantT())
16101 {
16102 // The case of SgLabelStatement should maybe be included.
16103 case V_SgEnumDeclaration:
16104 case V_SgTemplateDeclaration:
16105 case V_SgTypedefDeclaration:
16106 case V_SgFunctionDeclaration:
16107 case V_SgMemberFunctionDeclaration:
16108 case V_SgTemplateInstantiationFunctionDecl:
16109 {
16110 // DQ (12/4/2011): We can't just set the scope this simily (except in C). In C++ the scope should have
16111 // already been set or we can let it default to the current scope where it si located structurally.
16112 // stmt->set_scope(scope);
16113 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
16114 {
16115 stmt->set_scope(scope);
16116 }
16117 break;
16118 }
16119
16120 default:
16121 {
16122 // debugging support...
16123 printf ("In SageInterface::fixStatement(): switch default case used (likely OK): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
16124 ROSE_ASSERT(stmt->hasExplicitScope() == false);
16125#if 0
16126 printf ("switch case not handled properly: stmt = %p = %s \n",stmt,stmt->class_name().c_str());
16127 ROSE_ABORT();
16128#endif
16129 break;
16130 }
16131 }
16132#else
16133 // If the scoep has to be set and it has not yet been set, then set it directly.
16134 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
16135 {
16136 stmt->set_scope(scope);
16137 }
16138#endif
16139 }
16140
16141
16154 {
16155 // DQ (11/19/2012): Note that this appears to be an expensive function presently taking 22.5% of the total time
16156 // to process the tests/CompilerTests/Cxx_tests/rosePerformance.C file. So this is a performance problem.
16157
16158 ROSE_ASSERT(func != NULL && scope != NULL);
16159
16160 ROSE_ASSERT(func != NULL);
16161 ROSE_ASSERT(scope != NULL);
16162
16163 SgStatementPtrList stmtList, sameFuncList;
16164
16165 // SgFunctionDeclaration* first_nondef = NULL;
16166 // Some annoying part of scope
16167 if (scope->containsOnlyDeclarations())
16168 {
16169 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
16170 SgDeclarationStatementPtrList::iterator i;
16171 for (i=declList.begin();i!=declList.end();i++)
16172 stmtList.push_back(*i);
16173 }
16174 else
16175 {
16176 stmtList = scope->getStatementList();
16177 }
16178
16179 SgFunctionDeclaration* firstNondefiningFunctionDeclaration = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
16180 if (firstNondefiningFunctionDeclaration != NULL)
16181 {
16182 // If there exists a non-NULL reference to a firstNondefiningFunctionDeclaration
16183 // then use it (unless we want to handle where it might be set wrong).
16184#if 0
16185 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid pointer to a firstNondefiningFunctionDeclaration = %p \n",func,firstNondefiningFunctionDeclaration);
16186#endif
16187 }
16188
16189 // DQ (3/12/2012): Added assertion
16190 // ROSE_ASSERT(scope == func->get_firstNondefiningDeclaration()->get_scope());
16191 ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope() != NULL);
16192
16193 // 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.
16194 if (func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) == NULL)
16195 {
16196 printf ("WARNING: symbol for func->get_firstNondefiningDeclaration() = %p = %s = %s is not present in the scope = %p = %s associated with the firstNondefiningDeclaration \n",
16197 func->get_firstNondefiningDeclaration(),func->get_firstNondefiningDeclaration()->class_name().c_str(),func->get_name().str(),
16199 }
16200 // ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) != NULL);
16201
16202#if 0
16203 // It would be better to find the first non-defining declaration via the symbol.
16204 SgSymbol* functionSymbol = scope->lookup_function_symbol(func->get_name(),func->get_type());
16205 if (functionSymbol != NULL)
16206 {
16207 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid symbol = %p \n",func,functionSymbol);
16208 }
16209 else
16210 {
16211 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p functionSymbol == NULL \n",func);
16212 }
16213#endif
16214
16215 // Find the same function declaration list, including func itself
16216 SgStatementPtrList::iterator j;
16217 for (j = stmtList.begin(); j != stmtList.end(); j++)
16218 {
16219 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16220 if (func_decl != NULL)
16221 {
16222 // DQ (11/19/2012): This call to the isSameFunction() function is taking a total of 22.1%
16223 // of the total execution time of the tests/CompilerTests/Cxx_tests/rosePerformance.C file.
16224 if (isSameFunction(func_decl, func))
16225 {
16226 // Assume all defining functions have definingdeclaration links set properly already!!
16227 sameFuncList.push_back(func_decl);
16228 }
16229 }
16230 }
16231
16232#if 0
16233 printf ("func = %p \n",func);
16234 printf ("func->get_definingDeclaration() = %p \n",func->get_definingDeclaration());
16235#endif
16236
16237 ROSE_ASSERT(func != NULL);
16238
16239 if (func->get_definingDeclaration() == func)
16240 {
16241 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16242 isSgFunctionDeclaration(*j)->set_definingDeclaration(func);
16243 }
16244 else
16245 {
16246 ROSE_ASSERT(func != NULL);
16247
16248 // DQ (3/9/2012): Added assertion to avoid empty list that would be an error in both cases below.
16249 ROSE_ASSERT(sameFuncList.empty() == false);
16250
16251 if (func == isSgFunctionDeclaration(*(sameFuncList.begin()))) // is first_nondefining declaration
16252 {
16253 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16254 {
16255 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16256#if 0
16257 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Testing j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16258#endif
16259 // DQ (3/9/2012): Avoid setting the function to be it's own firstNondefiningDeclaration.
16260 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16261 if (func_decl != func)
16262 {
16263 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16264 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16265 if (func_decl->get_firstNondefiningDeclaration() == NULL)
16266 {
16267#if 0
16268 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Calling j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16269#endif
16270 func_decl->set_firstNondefiningDeclaration(func);
16271 }
16272 }
16273 }
16274 }
16275 else // is a following nondefining declaration, grab any other's first nondefining link then
16276 {
16277#if 0
16278 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Testing func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16279#endif
16280 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16281 // func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16282 if (func->get_firstNondefiningDeclaration() == NULL)
16283 {
16284#if 0
16285 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Calling func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16286#endif
16287 func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16288 }
16289 }
16290 }
16291 }
16292
16293PreprocessingInfo* SageInterface::attachComment(SgSourceFile * source_file, const std::string & content, PreprocessingInfo::DirectiveType directive_type, PreprocessingInfo::RelativePositionType position) {
16294 assert(source_file != NULL);
16295 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16296
16297 SgGlobal * global_scope = source_file->get_globalScope();
16298
16299 PreprocessingInfo* result = new PreprocessingInfo(directive_type, content, "Transformation generated",0, 0, 0, position);
16300 ROSE_ASSERT(result);
16301
16302 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16303 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16304 // when multiple files are used on the command line.
16305 result->get_file_info()->setTransformation();
16306
16307 global_scope->addToAttachedPreprocessingInfo(result, position);
16308
16309 return result;
16310}
16311
16312//---------------------------------------------------------------
16314 SgLocatedNode* target, const string& content,
16315 PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/,
16316 PreprocessingInfo::DirectiveType dtype /* PreprocessingInfo::CpreprocessorUnknownDeclaration */)
16317 {
16318 ASSERT_not_null(target); //dangling comment is not allowed
16319
16320 PreprocessingInfo* result = NULL;
16321 PreprocessingInfo::DirectiveType mytype=dtype;
16322 string comment;
16323
16324 // Rasmussen (11/3/2020): Added Ada and Jovial style comments
16325 // DQ (5/5/2010): infer comment type from target's language
16326 if (mytype == PreprocessingInfo::CpreprocessorUnknownDeclaration)
16327 {
16328 // This is a rather expensive way to detect the language type (chases pointers back to the SgFile object).
16329 if (is_C_language() || is_C99_language())
16330 {
16331 // Comment = "/* "+ content + " */";
16332 mytype = PreprocessingInfo::C_StyleComment;
16333 }
16334 else if (is_Cxx_language() || is_Java_language())
16335 {
16336 // Comment = "// "+ content;
16337 mytype = PreprocessingInfo::CplusplusStyleComment;
16338 }
16339 else if (is_Fortran_language() || is_CAF_language()) //FMZ:3/23/2009
16340 {
16341 // Comment = "! "+ content;
16342 mytype = PreprocessingInfo::F90StyleComment;
16343 }
16344 else if (is_Ada_language())
16345 {
16346 // Comment = "-- " + content;
16347 mytype = PreprocessingInfo::AdaStyleComment;
16348 }
16349 else if (is_Jovial_language())
16350 {
16351 // Comment = "% " + content + " %";
16352 mytype = PreprocessingInfo::JovialStyleComment;
16353 }
16354 else
16355 {
16356 cout << "WARNING: SageInterface::attachComment(): Unknown programming language \n";
16357 ROSE_ABORT();
16358 }
16359 }
16360
16361 // Once the langauge type is set (discovered automatically or more directly specified by the user).
16362 bool resetPositionInfo = false;
16363 switch (mytype)
16364 {
16365 case PreprocessingInfo::C_StyleComment: comment = "/* " + content + " */"; break;
16366 case PreprocessingInfo::CplusplusStyleComment: comment = "// " + content; break;
16367 case PreprocessingInfo::FortranStyleComment: comment = " C " + content; break;
16368 case PreprocessingInfo::F90StyleComment: comment = "!" + content; break;
16369 case PreprocessingInfo::AdaStyleComment: comment = "-- " + content; break;
16370 case PreprocessingInfo::JovialStyleComment:
16371 // The Jovial comment content will already have the comment delimiters, '%' or '"'
16372 comment = content;
16373 break;
16374 case PreprocessingInfo::CpreprocessorLineDeclaration:
16375 comment = "#myline " + content;
16376 mytype = PreprocessingInfo::CplusplusStyleComment;
16377 resetPositionInfo = true;
16378 break;
16379 case PreprocessingInfo::CpreprocessorIfndefDeclaration: comment = "#ifndef " + content + "\n"; break;
16380 case PreprocessingInfo::CpreprocessorDefineDeclaration: comment = "#define " + content + "\n"; break;
16381 case PreprocessingInfo::CpreprocessorEndifDeclaration: comment = "#endif" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16382 case PreprocessingInfo::CpreprocessorEnd_ifDeclaration: comment = "#end if" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16383
16384 default:
16385 {
16386 printf ("Error: default in switch reached in SageInterface::attachComment() PreprocessingInfo::DirectiveType == %d \n",mytype);
16387 ROSE_ABORT();
16388 }
16389 }
16390
16391 result = new PreprocessingInfo (mytype,comment, "transformation-generated", 0, 0, 0, position);
16392
16393 // If this is a Cpp Line declaration then we have to set the position to match the statement.
16394 if (resetPositionInfo == true)
16395 {
16396 // Call the Sg_File_Info::operator=() member function.
16397 *(result->get_file_info()) = *(target->get_file_info());
16398 }
16399 else
16400 {
16401 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16402 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16403 // when multiple files are used on the command line.
16404 result->get_file_info()->setTransformation();
16405 }
16406
16407 ASSERT_not_null(result);
16408 target->addToAttachedPreprocessingInfo(result);
16409 return result;
16410 }
16411
16412void SageInterface::guardNode(SgLocatedNode * target, std::string guard) {
16413 PreprocessingInfo * if_macro = new PreprocessingInfo(
16414 PreprocessingInfo::CpreprocessorIfDeclaration,
16415 "#if " + guard,
16416 "transformation-generated", 0, 0, 0,
16417 PreprocessingInfo::before
16418 );
16419 target->addToAttachedPreprocessingInfo(if_macro);
16420
16421 PreprocessingInfo * endif_macro = new PreprocessingInfo(
16422 PreprocessingInfo::CpreprocessorEndifDeclaration,
16423 "#endif",
16424 "transformation-generated", 0, 0, 0,
16425 PreprocessingInfo::after
16426 );
16427 target->addToAttachedPreprocessingInfo(endif_macro);
16428
16429// DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16430// This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16431// when multiple files are used on the command line.
16432 if_macro->get_file_info()->setTransformation();
16433 endif_macro->get_file_info()->setTransformation();
16434}
16435
16436// internal hash table to cache the results: fileHeaderDict[file][header-key]
16437// header-key:
16438// system header : <header.h>
16439// non-system headers : "header.h"
16440static map<SgSourceFile*, map<string, PreprocessingInfo*> > fileHeaderDict;
16442PreprocessingInfo * SageInterface::findHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader)
16443{
16444 string header_key;
16445 if (isSystemHeader)
16446 header_key="<"+header_file_name+">";
16447 else
16448 header_key="\""+header_file_name+"\"";
16449
16450 if (fileHeaderDict.count(source_file) && fileHeaderDict[source_file].count(header_key))
16451 return fileHeaderDict[source_file][header_key];
16452
16453 vector<SgLocatedNode*> candidates;
16454 // do a fresh check. we only check global scope's declarations since we insert header into global scope
16455 // check SgGlobal
16456 SgGlobal* global= source_file -> get_globalScope();
16457
16458 candidates.push_back(global);
16459
16460 //check declarations within the global scope
16461 SgDeclarationStatementPtrList decl_stmt_list = global->get_declarations();
16462 for (SgDeclarationStatementPtrList::iterator iter= decl_stmt_list.begin(); iter!=decl_stmt_list.end(); iter++)
16463 candidates.push_back(*iter);
16464
16465 bool found = false;
16466 for (size_t ci=0; ci<candidates.size(); ci++)
16467 {
16468 SgLocatedNode* locatedNode= candidates[ci];
16469 AttachedPreprocessingInfoType *comments = locatedNode->getAttachedPreprocessingInfo ();
16470
16471 if (comments == NULL) continue;
16472 AttachedPreprocessingInfoType::iterator i;
16473 for (i = comments->begin (); i != comments->end (); i++)
16474 {
16475 if ((*i)->getTypeOfDirective () != PreprocessingInfo::CpreprocessorIncludeDeclaration) continue;
16476 string content = (*i)->getString ();
16477 if (content.find(header_key) != string::npos)
16478 {
16479 fileHeaderDict[source_file][header_key] = *i;
16480 found =true;
16481 break;
16482 }
16483
16484 } // each comment
16485
16486 if (found) break;
16487 } // each node
16488
16489 if (found)
16490 return fileHeaderDict[source_file][header_key];
16491 return NULL;
16492}
16493
16495SageInterface::insertHeader(SgSourceFile * source_file, const string & header_file_name, bool isSystemHeader, PreprocessingInfo::RelativePositionType position)
16496 {
16497 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16498 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16499 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16500 bool supportTokenUnparsing = false;
16501
16502 assert(source_file != NULL);
16503 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16504
16505 SgGlobal * global_scope = source_file->get_globalScope();
16506
16507 string content;
16508 if (isSystemHeader)
16509 content = "#include <" + header_file_name + "> \n";
16510 else
16511 content = "#include \"" + header_file_name + "\" \n";
16512
16513 PreprocessingInfo* result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, position);
16514 ROSE_ASSERT(result);
16515
16516 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16517 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16518 // when multiple files are used on the command line.
16519 result->get_file_info()->setTransformation();
16520
16521 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16522 supportTokenUnparsing = source_file->get_unparse_tokens();
16523 bool supportUnparseHeaders = source_file->get_unparseHeaderFiles();
16524
16525#if 0
16526 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16527 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16528 printf ("source_file = %p \n",source_file);
16529 printf ("global_scope = %p \n",global_scope);
16530#endif
16531#if 0
16532 printf ("Exiting as a test! \n");
16533 ROSE_ABORT();
16534#endif
16535
16536 // global_scope->addToAttachedPreprocessingInfo(result, position);
16537 if (supportTokenUnparsing == false)
16538 {
16539 global_scope->addToAttachedPreprocessingInfo(result, position);
16540 }
16541 else
16542 {
16543 // global_scope->prepend_statement(null_statement);
16544 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16545
16546 if (supportUnparseHeaders == true)
16547 {
16548 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16549 int physical_file_id = global_scope->get_startOfConstruct()->get_physical_file_id();
16550#if 0
16551 printf ("physical_file_id = %d \n",physical_file_id);
16552#endif
16553 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16554 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16555#if 0
16556 printf ("Exiting as a test! \n");
16557 ROSE_ABORT();
16558#endif
16559 }
16560
16561 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16562
16563 global_scope->prepend_statement(emptyDeclaration);
16564 }
16565
16566#if 0
16567 printf ("Exiting as a test! \n");
16568 ROSE_ASSERT(false);
16569#endif
16570
16571 return result;
16572 }
16573
16574PreprocessingInfo* SageInterface::insertHeader(const string& filename, PreprocessingInfo::RelativePositionType position /*=after*/, bool isSystemHeader /*=false*/, SgScopeStatement* scope /*=NULL*/)
16575 {
16576 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16577 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16578 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16579 bool supportTokenUnparsing = false;
16580
16581 // DQ (8/12/2020): This is a compiler warning.
16582 // bool successful = false;
16583
16584#if 0
16585 printf ("In SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16586 printf (" --- position = %s \n",PreprocessingInfo::relativePositionName(position).c_str());
16587#endif
16588
16589 if (scope == NULL)
16591
16592 ROSE_ASSERT(scope);
16593
16594 SgGlobal* globalScope = getGlobalScope(scope);
16595 ROSE_ASSERT(globalScope != NULL);
16596
16597 // 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
16598 // if the input scope is within a header file,
16599 // its global scope will jump to a .cpp file. Later looping will not find a match.
16600 SgScopeStatement* srcScope = globalScope;
16601 PreprocessingInfo* result=NULL;
16602 string content;
16603 if (isSystemHeader)
16604 content = "#include <" + filename + "> \n";
16605 else
16606 content = "#include \"" + filename + "\" \n";
16607
16608 // DQ (11/21/2019): Token based unparsing has an additional requirement, we need to mark that the
16609 // whitespace around the statement has been modified. This will trigger the unparser to output
16610 // the comments and CPP directives when using the token-based unparsing. The insertion of a header
16611 // file requires this support else the original token stream will not have the added header file.
16612
16613 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16614 SgSourceFile* sourceFile = getEnclosingSourceFile(scope);
16615 ROSE_ASSERT(sourceFile != NULL);
16616
16617 supportTokenUnparsing = sourceFile->get_unparse_tokens();
16618
16619 bool supportUnparseHeaders = sourceFile->get_unparseHeaderFiles();
16620 // if unparsing header and the scope is within a header file, we adjust srcScope to be scope, not its enclosing global scope
16621 if (supportUnparseHeaders)
16622 {
16623 string filename= scope->get_file_info()->get_filename();
16624 string suffix = Rose::StringUtility ::fileNameSuffix(filename);
16625
16626 // vector.tcc: This is an internal header file, included by other library headers
16627 if (suffix=="h" ||suffix=="hpp"|| suffix=="hh"||suffix=="H" ||suffix=="hxx"||suffix=="h++" ||suffix=="tcc")
16628 srcScope = scope;
16629 }
16630
16631#if 0
16632 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16633 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16634 printf ("sourceFile = %p \n",sourceFile);
16635 printf ("globalScope = %p \n",globalScope);
16636#endif
16637#if 0
16638 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16639#endif
16640#if 0
16641 printf ("Exiting as a test! \n");
16642 ROSE_ABORT();
16643#endif
16644
16645 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations();
16646
16647#if 0
16648 printf ("stmtList.size() = %zu \n",stmtList.size());
16649#endif
16650
16651 if (stmtList.size() > 0) // the source file is not empty
16652 {
16653 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16654 {
16655 // must have this judgement, otherwise wrong file will be modified!
16656 // It could also be the transformation generated statements with #include attached
16657 if ( ((*j)->get_file_info())->isSameFile(srcScope->get_file_info ()) || ((*j)->get_file_info ())->isTransformation() )
16658 {
16659 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16660 ROSE_ASSERT(result != NULL);
16661#if 0
16662 printf ("Building a PreprocessingInfo: result = %p \n",result);
16663#endif
16664 // DQ (3/22/2019): Fixing this to work with the token-based unparsing.
16665 // add to the last position
16666 // TODO: support to add to the first,
16667 // TODO: support fine positioning with #include directives
16668 // (*j)->addToAttachedPreprocessingInfo(result,position);
16669
16670 if (supportTokenUnparsing == false)
16671 {
16672 (*j)->addToAttachedPreprocessingInfo(result,position);
16673 }
16674 else
16675 {
16676 (*j)->addToAttachedPreprocessingInfo(result,position);
16677#if 0
16678 printf ("In SageInterface::insertHeader(): Calling set_containsTransformationToSurroundingWhitespace(true) \n");
16679#endif
16680#if 1
16681 // DQ (12/31/2020): Set the whitespace around the statement as being modified.
16682 (*j)->set_containsTransformationToSurroundingWhitespace(true);
16683#endif
16684#if 0
16685 SgDeclarationStatement* declarationStatement = *j;
16686
16687 // DQ (1/5/2021): Don't call unparseToString, since this triggers the unparer which then unparses
16688 // from the token stream and makrs some token stream elements as already unparsed.
16689 // printf ("declarationStatement = %p = %s unparseToString() = %s \n",declarationStatement,
16690 // declarationStatement->class_name().c_str(),declarationStatement->unparseToString().c_str());
16691 printf ("In SageInterface::insertHeader(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
16692 printf ("In SageInterface::insertHeader(): declarationStatement->get_containsTransformationToSurroundingWhitespace() = %s \n",
16693 declarationStatement->get_containsTransformationToSurroundingWhitespace() ? "true" : "false");
16694#endif
16695#if 0
16696 // Liao, let's try the new way.
16697 // global_scope->prepend_statement(null_statement);
16698 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16699
16700 if (supportUnparseHeaders == true)
16701 {
16702 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16703 int physical_file_id = globalScope->get_startOfConstruct()->get_physical_file_id();
16704#if 0
16705 printf ("physical_file_id = %d \n",physical_file_id);
16706#endif
16707 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16708 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16709#if 0
16710 printf ("Exiting as a test! \n");
16711 ROSE_ASSERT(false);
16712#endif
16713 }
16714
16715 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16716
16717 globalScope->insert_statement(*j,emptyDeclaration);
16718#endif
16719 }
16720#if 0
16721 printf ("break out of for loop: result = %p \n",result);
16722#endif
16723 // DQ (8/12/2020): This is a compiler warning.
16724 // successful = true;
16725 break;
16726 }
16727 }
16728 }
16729 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16730 {
16731 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16732 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16733 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16734 ROSE_ASSERT(false);
16735 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16736 ROSE_ASSERT(result);
16737 globalScope->addToAttachedPreprocessingInfo(result,position);
16738
16739 // DQ (8/12/2020): This is a compiler warning.
16740 // successful = true;
16741 }
16742
16743 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16744 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16745 // when multiple files are used on the command line.
16746 // DQ (3/12/2019): This can be NULL for the omp tests.
16747 if (result != NULL)
16748 {
16749 result->get_file_info()->setTransformation();
16750 }
16751
16752 // must be inserted once somehow
16753 // 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
16754 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16755 // ROSE_ASSERT(successful==true);
16756
16757#if 0
16758 printf ("Exiting as a test! \n");
16759 ROSE_ASSERT(false);
16760#endif
16761
16762#if 0
16763 printf ("Leaving SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16764#endif
16765
16766#if 0
16767 printf ("Exiting as a test! \n");
16768 ROSE_ASSERT(false);
16769#endif
16770
16771 return result;
16772 }
16773
16774
16775// 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
16776void SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader)
16777{
16778 ROSE_ASSERT (stmt != NULL);
16779 ROSE_ASSERT (newheader != NULL);
16780
16781#if 0
16782 printf ("In SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader) \n");
16783#endif
16784
16786
16787 if (asLastHeader )
16788 position = PreprocessingInfo::after;
16789 else
16790 position = PreprocessingInfo::before;
16791
16792
16793 // Find existing first and last header.
16794 AttachedPreprocessingInfoType *comments = stmt->getAttachedPreprocessingInfo ();
16795
16796 if (comments != NULL)
16797 {
16798 PreprocessingInfo * firstExistingHeader = NULL;
16799 PreprocessingInfo * lastExistingHeader = NULL;
16800 PreprocessingInfo * firstExistingEndif = NULL;
16801
16802 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16803 // PreprocessingInfo * lastExistingEndif = NULL;
16804
16805 AttachedPreprocessingInfoType::iterator i, firsti, lasti;
16806 for (i = comments->begin (); i != comments->end (); i++)
16807 {
16808 // DQ (9/12/2020): this original code is not sufficent since when the final #include is enclosed in a
16809 // #ifdef #endif the added include directive might not be visible in the generated file.
16810 // This actually happened in the case of wget application: wget.c source file.
16811#if 0
16812 // Original version of code.
16813 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16814 {
16815 // Only set first header for the first time
16816 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16817 {
16818 if (firstExistingHeader == NULL)
16819 {
16820 firstExistingHeader = (*i);
16821 firsti = i;
16822 }
16823 // always updates last header
16824 lastExistingHeader = (*i);
16825 lasti = i;
16826 }
16827 }
16828#else
16829 // DQ (9/12/2020): New version of code. Addresses insertion after last endif if it is after any #include.
16830 if ( (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration ||
16831 (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration )
16832 {
16833 // Only set first header for the first time
16834 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16835 {
16836 if (firstExistingHeader == NULL)
16837 {
16838 firstExistingHeader = (*i);
16839 firsti = i;
16840 }
16841 // always updates last header
16842 lastExistingHeader = (*i);
16843 lasti = i;
16844 }
16845 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration)
16846 {
16847 if (firstExistingEndif == NULL)
16848 {
16849 firstExistingEndif = (*i);
16850 firsti = i;
16851 }
16852 // always updates last header
16853 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16854 // lastExistingEndif = (*i);
16855 lasti = i;
16856 }
16857 }
16858#endif
16859 }
16860
16861 // based on existing header positions, insert the new header
16862 if (asLastHeader)
16863 {
16864 if (lastExistingHeader == NULL) // No last header at all, just append to after
16865 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16866 else
16867 {
16868 comments->insert (lasti+1, newheader);
16869 }
16870 }
16871 else // add as the first header
16872 {
16873 if (firstExistingHeader == NULL) // no existing header at all, just append to after
16874 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16875 else
16876 {
16877 comments->insert (firsti, newheader);
16878 }
16879 }
16880 }
16881 else // No comments at all, first and last header mean the same, just attach to the located node
16882 stmt->addToAttachedPreprocessingInfo(newheader, position);
16883
16884#if 0
16885 printf ("Exiting as a test! \n");
16886 ROSE_ASSERT(false);
16887#endif
16888
16889}
16890
16891
16892// The recommended version
16893PreprocessingInfo* SageInterface::insertHeader(SgSourceFile * source_file, const std::string & filename, bool isSystemHeader , bool asLastHeader)
16894{
16895 ROSE_ASSERT (source_file != NULL);
16896 SgGlobal* globalScope = source_file->get_globalScope();
16897 ROSE_ASSERT (globalScope != NULL);
16898
16899 PreprocessingInfo* result=NULL;
16900 string content;
16901 if (isSystemHeader)
16902 content = "#include <" + filename + "> \n";
16903 else
16904 content = "#include \"" + filename + "\" \n";
16905
16906#if 0
16907 // 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.
16909
16910 if (asLastHeader )
16911 position = PreprocessingInfo::after;
16912 else
16913 position = PreprocessingInfo::before;
16914#endif
16915
16916 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations ();
16917 if (stmtList.size()>0) // the source file is not empty
16918 {
16919 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16920 {
16921 // Attach to the first eligible located statement
16922 //must have this judgement, otherwise wrong file will be modified!
16923 //It could also be the transformation generated statements with #include attached
16924 if ( (*j)->get_file_info()->isSameFile(globalScope->get_file_info()) || (*j)->get_file_info()->isTransformation() )
16925 {
16926#if 0
16927 printf ("In SageInterface::insertHeader(): Found statement to attached #include: *j = %p = %s \n",*j,(*j)->class_name().c_str());
16928 printf (" --- unparseToString() = %s \n",(*j)->unparseToString().c_str());
16929#endif
16930 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16931 ROSE_ASSERT(result);
16932 insertHeader (*j, result, asLastHeader);
16933 //successful = true;
16934#if 0
16935 printf ("Exiting as a test! \n");
16936 ROSE_ABORT();
16937#endif
16938 break;
16939 }
16940 } // end for
16941 }
16942 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16943 {
16944 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16945 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16946 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16947 ROSE_ABORT();
16948#if 0 // [Robb Matzke 2021-03-24]: unreachable
16949 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration,
16950 content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16951 ROSE_ASSERT(result);
16952 globalScope->addToAttachedPreprocessingInfo(result,position);
16953#endif
16954 // successful = true;
16955 }
16956
16957#if 0
16958 printf ("In SageInterface::insertHeader(): Marking include file for filename = %s as a transformation \n",filename.c_str());
16959#endif
16960
16961 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16962 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16963 // when multiple files are used on the command line.
16964 if (result)
16965 result->get_file_info()->setTransformation();
16966
16967#if 0
16968 printf ("Exiting as a test! \n");
16969 ROSE_ASSERT(false);
16970#endif
16971
16972 // must be inserted once somehow
16973 // 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
16974 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16975 // ROSE_ASSERT(successful==true);
16976 return result;
16977
16978} // end insertHeader
16979
16980
16983SageInterface::attachArbitraryText(SgLocatedNode* target, const std::string & text, PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/)
16984 {
16985 // DQ (1/13/2014): This function needs a better mechanism than attaching text to the AST unparser as a CPP directive.
16986
16987 ROSE_ASSERT(target != NULL); //dangling #define xxx is not allowed in the ROSE AST
16988 PreprocessingInfo* result = NULL;
16989
16990 // DQ (1/13/2014): It is a mistake to attach arbitrary test to the AST as a #define
16991 // (since we evaluate all #define CPP declarations to be a self-referential macro).
16992 // For now I will make it a #if CPP declaration, since these are not evaluated internally.
16993 // PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorDefineDeclaration;
16994 PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorIfDeclaration;
16995
16996 // DQ (1/13/2014): Output a warning so that this can be fixed whereever it is used.
16997 printf ("Warning: attachArbitraryText(): attaching arbitrary text to the AST as a #if declaration: text = %s \n",text.c_str());
16998
16999 result = new PreprocessingInfo (mytype,text, "transformation-generated", 0, 0, 0, position);
17000 ROSE_ASSERT(result);
17001
17002 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
17003 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
17004 // when multiple files are used on the command line.
17005 result->get_file_info()->setTransformation();
17006
17007 target->addToAttachedPreprocessingInfo(result);
17008
17009 return result;
17010 }
17011
17012
17014// 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.
17016{
17017 // This is part of Wave support in ROSE.
17018// #if CAN_NOT_COMPILE_WITH_ROSE != true
17019// #if CAN_NOT_COMPILE_WITH_ROSE == 0
17020#ifndef USE_ROSE
17021 ROSE_ASSERT(target != NULL);
17022 AttachedPreprocessingInfoType *info= target->getAttachedPreprocessingInfo ();
17023 if (info == NULL) return;
17024 AttachedPreprocessingInfoType::iterator j;
17025 for (j = info->begin (); j != info->end (); j++)
17026 {
17027 if ((*j)->getTypeOfDirective()==PreprocessingInfo::CMacroCall)
17028 {
17029#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
17030 // DQ (2/17/2016): The token_container type is not defined if Wave is not available.
17031 std::ostringstream os;
17032 token_container tc = (*j)->get_macro_call()->expanded_macro;
17033 token_container::const_iterator iter;
17034 for (iter=tc.begin(); iter!=tc.end(); iter++)
17035 os<<(*iter).get_value();
17036 //cout<<"Found a macro call: "<<(*j)->getString()<<
17037 //"\nexpanding it to: "<<os.str()<<endl;
17038 string pragmaText = target->get_pragma()->get_pragma();
17039 string targetString = (*j)->getString();
17040 string replacement = os.str();
17041 // repeat until not found
17042 size_t pos1 = pragmaText.find(targetString);
17043 while (pos1 != string::npos)
17044 {
17045 pragmaText.replace(pos1, targetString.size(), replacement);
17046 pos1 = pragmaText.find(targetString);
17047 }
17048 delete target->get_pragma();
17049 target->set_pragma(buildPragma(pragmaText));
17050#endif
17051 } // end if
17052 } // end for
17053#endif
17054}
17055
17060 using namespace SageBuilder;
17061 SgStatement* body = NULL;
17062 if (isSgWhileStmt(loopOrSwitch) || isSgDoWhileStmt(loopOrSwitch) ||
17063 isSgForStatement(loopOrSwitch)) {
17064 body = SageInterface::getLoopBody(isSgScopeStatement(loopOrSwitch));
17065 } else if (isSgSwitchStatement(loopOrSwitch)) {
17066 body = isSgSwitchStatement(loopOrSwitch)->get_body();
17067 }
17068 ROSE_ASSERT (body);
17069 std::vector<SgBreakStmt*> breaks = SageInterface::findBreakStmts(body);
17070 if (!breaks.empty()) {
17071 static int breakLabelCounter = 0;
17072 SgLabelStatement* breakLabel =
17073 buildLabelStatement("breakLabel" +
17074StringUtility::numberToString(++breakLabelCounter),
17076 isSgScopeStatement(loopOrSwitch->get_parent()));
17077 insertStatement(loopOrSwitch, breakLabel, false);
17078 for (size_t j = 0; j < breaks.size(); ++j) {
17079 SgGotoStatement* newGoto = buildGotoStatement(breakLabel);
17080
17081 isSgStatement(breaks[j]->get_parent())->replace_statement(breaks[j],
17082 newGoto);
17083 newGoto->set_parent(breaks[j]->get_parent());
17084 }
17085 }
17086 }
17087
17089 {
17090 ROSE_ASSERT(node!=NULL);
17091 SgClassDeclaration *decl = isSgClassDeclaration(node);
17092 if (decl==NULL)
17093 return false;
17094 else
17095 return (decl->get_class_type() == SgClassDeclaration::e_struct)? true:false;
17096 }
17097
17099 {
17100 ROSE_ASSERT(node!=NULL);
17101 SgClassDeclaration *decl = isSgClassDeclaration(node);
17102 if (decl==NULL)
17103 return false;
17104 else
17105 return (decl->get_class_type() == SgClassDeclaration::e_union)? true:false;
17106 }
17107
17108
17109void
17110SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
17111 PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
17112 {
17113 ROSE_ASSERT(stmt_src != NULL);
17114 ROSE_ASSERT(stmt_dst != NULL);
17115 AttachedPreprocessingInfoType* infoList = stmt_src->getAttachedPreprocessingInfo();
17116
17117 if (infoList == NULL)
17118 {
17119#if 0
17120 printf ("In SageInterface::movePreprocessingInfo(): infoList == NULL: exiting movePreprocessingInfo() \n");
17121#endif
17122 return;
17123 }
17124
17125 AttachedPreprocessingInfoType* infoToRemoveList = new AttachedPreprocessingInfoType();
17126
17127#if 0
17128 printf ("In SageInterface::movePreprocessingInfo(): \n");
17129 printf (" --- stmt_src = %p = %s src_position = %d \n",stmt_src,stmt_src->class_name().c_str(),src_position);
17130 SgDeclarationStatement* src_declarationStatement = isSgDeclarationStatement(stmt_src);
17131 if (src_declarationStatement != NULL)
17132 {
17133 printf ("src_declarationStatement->get_firstNondefiningDeclaration() = %p \n",src_declarationStatement->get_firstNondefiningDeclaration());
17134 printf ("src_declarationStatement->get_definingDeclaration() = %p \n",src_declarationStatement->get_definingDeclaration());
17135 }
17136 printf (" --- stmt_dst = %p = %s dst_position = %d \n",stmt_dst,stmt_dst->class_name().c_str(),dst_position);
17137 SgDeclarationStatement* dst_declarationStatement = isSgDeclarationStatement(stmt_dst);
17138 if (dst_declarationStatement != NULL)
17139 {
17140 printf ("dst_declarationStatement->get_firstNondefiningDeclaration() = %p \n",dst_declarationStatement->get_firstNondefiningDeclaration());
17141 printf ("dst_declarationStatement->get_definingDeclaration() = %p \n",dst_declarationStatement->get_definingDeclaration());
17142 }
17143 printf (" --- src_position = %s \n",PreprocessingInfo::relativePositionName(src_position).c_str());
17144 printf (" --- dst_position = %s \n",PreprocessingInfo::relativePositionName(dst_position).c_str());
17145 printf (" --- usePrepend = %s \n",usePrepend ? "true" : "false");
17146
17147 printf (" --- infoList = %p \n",infoList);
17148 printf (" --- infoToRemoveList = %p \n",infoToRemoveList);
17149
17150 AttachedPreprocessingInfoType* dst_infoList = stmt_dst->getAttachedPreprocessingInfo();
17151 printf (" --- dst_infoList = %p \n",dst_infoList);
17152#endif
17153#if 0
17154 printf ("****************************************************************** \n");
17155 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_src \n");
17157 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_dst \n");
17159 printf ("****************************************************************** \n");
17160#endif
17161
17162 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
17163 // This is a bug in the support for building a new prototype from a defining function declaration
17164 // and caused this problem. This assertion will prevent this sort of error from happening again.
17165 ROSE_ASSERT(infoList == NULL || stmt_src->getAttachedPreprocessingInfo() != stmt_dst->getAttachedPreprocessingInfo());
17166
17167
17168#if 0
17169 printf (" --- infoList->size() = %zu \n",infoList->size());
17170 printf (" --- infoToRemoveList->size() = %zu \n",infoToRemoveList->size());
17171#endif
17172
17173#if 0
17174 int counter = 0;
17175
17176 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
17177 {
17178 // DQ (11/19/2020): Added assertion.
17179 ROSE_ASSERT(*i != NULL);
17180
17181 // DQ (11/19/2020): Why do we have a dynamic cast here.
17182 // PreprocessingInfo * info = dynamic_cast<PreprocessingInfo*> (*i);
17183 PreprocessingInfo * info = *i;
17184 ROSE_ASSERT(info != NULL);
17185
17186 // printf ("counter = %d \n",counter);
17187 printf ("counter = %d Processing PreprocessingInfo = %s \n",counter,info->getString().c_str());
17188 counter++;
17189 }
17190
17191 counter = 0;
17192#endif
17193
17194 PreprocessingInfo* prevItem = NULL;
17195
17196 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
17197 {
17198 ROSE_ASSERT(*i != NULL);
17199
17200 PreprocessingInfo * info = *i;
17201 ROSE_ASSERT(info != NULL);
17202
17203 if ( // match enum values in http://rosecompiler.org/ROSE_HTML_Reference/classPreprocessingInfo.html
17204 (info->getTypeOfDirective()==PreprocessingInfo::C_StyleComment)||
17205 (info->getTypeOfDirective()==PreprocessingInfo::CplusplusStyleComment)||
17206 (info->getTypeOfDirective()==PreprocessingInfo::FortranStyleComment)||
17207 (info->getTypeOfDirective()==PreprocessingInfo::F90StyleComment)||
17208 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeDeclaration )||
17209 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeNextDeclaration )||
17210 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDefineDeclaration )||
17211 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorUndefDeclaration)||
17212 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfdefDeclaration )||
17213 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfndefDeclaration )||
17214 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfDeclaration )||
17215 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDeadIfDeclaration )||
17216 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElseDeclaration )||
17217 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElifDeclaration )||
17218 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEndifDeclaration ) ||
17219 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEnd_ifDeclaration ) ||
17220 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorLineDeclaration) ||
17221 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorErrorDeclaration) ||
17222 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorWarningDeclaration) ||
17223 // DQ (12/28/2020): Added support for C linkage specifications.
17224 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationStart) ||
17225 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationEnd)
17226 )
17227 {
17228 // move all source preprocessing info if the desired source type is not specified or matching
17229 // a specified desired source type
17230 if ( src_position == PreprocessingInfo::undef || info->getRelativePosition() == src_position)
17231 {
17232 if (usePrepend == true)
17233 {
17234 // Liao (1/27/2015): modification to fix order of CPP directives when a list of them are moved.
17235 if (prevItem == NULL)
17236 {
17237 // addToAttachedPreprocessingInfo() is poorly designed, the last parameter is used
17238 // to indicate appending or prepending by reusing the type of relative position.
17239 // this is very confusing for users
17240 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::before);
17241 }
17242 else // there is a previous item, insert after it
17243 {
17244 stmt_dst->insertToAttachedPreprocessingInfo(info, prevItem);
17245 }
17246 prevItem = info;
17247 }
17248 else
17249 {
17250 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::after);
17251 }
17252 // 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.
17253 info->setAsTransformation();
17254
17255 // DQ (10/13/2015): This is a problem for the token-based unparsing since we don't want to have this
17256 // set_containsTransformationToSurroundingWhitespace() function cause the isModified flag to be set.
17257 // So we have to detect it being set and reset it as needed. An alternative would be to have a
17258 // non-ROSETTA generate function that didn't have the isModified flag set for the seter access function.
17259 // Note that the inputmoveDeclarationToInnermostScope_test2015_123.C file demonstrates this problem.
17260 bool isMarkedAsModified = stmt_dst->get_isModified();
17261 stmt_dst->set_containsTransformationToSurroundingWhitespace(true);
17262 if (isMarkedAsModified == false)
17263 {
17264 if (stmt_dst->get_isModified() == true)
17265 {
17266 stmt_dst->set_isModified(false);
17267 }
17268 }
17269 (*infoToRemoveList).push_back(*i);
17270 }
17271
17272 // adjust dst position if needed
17273 if (dst_position != PreprocessingInfo::undef)
17274 {
17275 info->setRelativePosition(dst_position);
17276 }
17277 } // end if
17278 } // end for
17279
17280 // Remove the element from the list of comments at the current astNode
17281 AttachedPreprocessingInfoType::iterator j;
17282 for (j = (*infoToRemoveList).begin(); j != (*infoToRemoveList).end(); j++)
17283 {
17284 infoList->erase( find(infoList->begin(),infoList->end(),*j) );
17285 }
17286 }
17287
17288
17289//----------------------------
17290// Sometimes, the preprocessing info attached to a declaration has to be
17291// moved 'up' if another declaration is inserted before it.
17292// This is a workaround for the broken LowLevelRewrite::insert() and the private
17293// LowLevelRewrite::reassociatePreprocessorDeclarations()
17294//
17295// input:
17296// *stmt_dst: the new inserted declaration
17297// *stmt_src: the existing declaration with preprocessing information
17298// tasks:
17299// judge if stmt_src has propressingInfo with headers, ifdef, etc..
17300// add them into stmt_dst
17301// delete them from stmt_dst
17302// More general usage: move preprocessingInfo of stmt_src to stmt_dst, should used before any
17303// LoweLevel::remove(stmt_src)
17305 PreprocessingInfo::RelativePositionType src_position/*=PreprocessingInfo::undef*/,
17306 PreprocessingInfo::RelativePositionType dst_position/*=PreprocessingInfo::undef*/,
17307 bool usePrepend /*= false */)
17308 {
17309 movePreprocessingInfo (stmt_src, stmt_dst, src_position, dst_position, usePrepend);
17310 } // moveUpPreprocessingInfo()
17311
17312
17317static bool isNotRelPos (const PreprocessingInfo* info,
17319{
17320 return info && (info->getRelativePosition () != pos);
17321}
17322
17327static bool isRelPos (const PreprocessingInfo* info,
17329{
17330 return info && !isNotRelPos (info, pos);
17331}
17332
17333
17335void SageInterface::cutPreprocessingInfo (SgLocatedNode* src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17336{
17337 ASSERT_not_null(src_node);
17338
17339 // [Rasmussen,Sottile 2023.01.10]: Replaced deleted bind2nd (as of 2017)
17340 AttachedPreprocessingInfoType* info = src_node->get_attachedPreprocessingInfoPtr();
17341 if (info)
17342 {
17343 // copy elements to save_buf where isRelPos() is false
17344 remove_copy_if(info->begin(),
17345 info->end(),
17346 back_inserter(save_buf),
17347 [pos](auto x) { return !isRelPos(x, pos); }
17348 );
17349
17350 // delete copied elements from save_buf
17351 AttachedPreprocessingInfoType::iterator
17352 new_end = remove_if(info->begin(),
17353 info->end(),
17354 [pos](auto x) { return isRelPos(x, pos); }
17355 );
17356 info->erase(new_end, info->end());
17357 }
17358}
17359
17360static AttachedPreprocessingInfoType *
17361createInfoList (SgLocatedNode* s)
17362{
17363 ROSE_ASSERT (s);
17364 AttachedPreprocessingInfoType* info_list = s->get_attachedPreprocessingInfoPtr ();
17365 if (!info_list)
17366 {
17367 info_list = new AttachedPreprocessingInfoType;
17368 ROSE_ASSERT (info_list);
17369 s->set_attachedPreprocessingInfoPtr (info_list);
17370 }
17371
17372 // Guarantee a non-NULL pointer.
17373 ROSE_ASSERT (info_list);
17374 return info_list;
17375}
17376
17378void SageInterface::pastePreprocessingInfo (SgLocatedNode* dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17379{
17380 if (save_buf.size()==0) return;
17381 // if front
17382 AttachedPreprocessingInfoType* info = createInfoList (dst_node);
17383 ROSE_ASSERT (info);
17384
17385 // DQ (9/26/2007): Commented out as part of move from std::list to std::vector
17386 // printf ("Commented out front_inserter() as part of move from std::list to std::vector \n");
17387 // copy (save_buf.rbegin (), save_buf.rend (), front_inserter (*info));
17388
17389 // Liao (10/3/2007), vectors can only be appended at the rear
17390 if (pos==PreprocessingInfo::before)
17391 {
17392 for(AttachedPreprocessingInfoType::reverse_iterator i=save_buf.rbegin();i!=save_buf.rend();i++)
17393 info->insert(info->begin(),*i);
17394 }
17395 // if back
17396 else if (pos==PreprocessingInfo::after)
17397 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17398 else if (pos==PreprocessingInfo::inside)
17399 {
17400 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17401 cerr<<"SageInterface::pastePreprocessingInfo() pos==PreprocessingInfo::inside is not supported."<<endl;
17402 save_buf[0]->display("ttt");
17403 }
17404}
17405
17407{
17408 ROSE_ASSERT(locatedNode != NULL);
17409 AttachedPreprocessingInfoType *comments =
17410 locatedNode->getAttachedPreprocessingInfo ();
17411
17412 if (comments != NULL)
17413 {
17414 printf ("-----------------------------------------------\n");
17415 printf ("Found an IR node (at %p of type: %s) in file %s \n",
17416 locatedNode, locatedNode->class_name ().c_str (),
17417 (locatedNode->get_file_info ()->get_filenameString ()).c_str ());
17418 int counter = 0;
17419 AttachedPreprocessingInfoType::iterator i;
17420 for (i = comments->begin (); i != comments->end (); i++)
17421 {
17422 printf
17423 ("with attached preprocessingInfo numbering #%d :------------- \nclassification= %s:\nString format:%s\n",
17424 counter++,
17425 PreprocessingInfo::directiveTypeName ((*i)->getTypeOfDirective ()).
17426 c_str (), (*i)->getString ().c_str ());
17427 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
17428 printf ("relative position is: inside\n");
17429 else
17430 printf ("relative position is: %s\n", \
17431 ((*i)->getRelativePosition () == PreprocessingInfo::before) ? "before" : "after");
17432 }
17433 }
17434 else
17435 {
17436 printf ("No attached preprocessing info. (at %p of type: %s): \n", locatedNode,
17437 locatedNode->sage_class_name ());
17438 }
17439}
17440
17452template <class ParentNode>
17453static
17454SgBasicBlock* ensureBasicBlock_aux( ParentNode& stmt,
17455 SgStatement* (ParentNode::*getter) () const,
17456 void (ParentNode::*setter) (SgStatement*)
17457 )
17458{
17459 SgStatement* const body_stmt = (stmt.*getter)();
17460 SgBasicBlock* basicblock = isSgBasicBlock(body_stmt);
17461
17462 if (basicblock == NULL) {
17463 basicblock = SageBuilder::buildBasicBlock(body_stmt);
17464 (stmt.*setter)(basicblock);
17465 basicblock->set_parent(&stmt);
17466 }
17467
17468 ROSE_ASSERT (basicblock != NULL);
17469 return basicblock;
17470}
17471
17473{
17474 SgStatement* b = fs->get_loop_body();
17475 if (!isSgBasicBlock(b)) {
17477 fs->set_loop_body(b);
17478 b->set_parent(fs);
17479
17480 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17482 }
17483 ROSE_ASSERT (isSgBasicBlock(b));
17484 return isSgBasicBlock(b);
17485}
17486
17488{
17489 SgStatement* b = cs->get_body();
17490 if (!isSgBasicBlock(b)) {
17492 cs->set_body(b);
17493 b->set_parent(cs);
17494
17495 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17497 }
17498 ROSE_ASSERT (isSgBasicBlock(b));
17499 return isSgBasicBlock(b);
17500}
17501
17503{
17504 SgStatement* b = cs->get_body();
17505 if (!isSgBasicBlock(b)) {
17507 cs->set_body(b);
17508 b->set_parent(cs);
17509
17510 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17512 }
17513 ROSE_ASSERT (isSgBasicBlock(b));
17514 return isSgBasicBlock(b);
17515}
17516
17518{
17519 ROSE_ASSERT (fs != NULL);
17520
17521 return ensureBasicBlock_aux(*fs, &SgUpcForAllStatement::get_loop_body, &SgUpcForAllStatement::set_loop_body);
17522}
17523
17525 SgStatement* b = fs->get_body();
17526 if (!isSgBasicBlock(b)) {
17528 fs->set_body(b);
17529 b->set_parent(fs);
17530
17531 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17533 }
17534 ROSE_ASSERT (isSgBasicBlock(b));
17535 return isSgBasicBlock(b);
17536 }
17537
17539 SgStatement* b = fs->get_body();
17540 if (!isSgBasicBlock(b)) {
17542 fs->set_body(b);
17543 b->set_parent(fs);
17544
17545 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17547 }
17548 ROSE_ASSERT (isSgBasicBlock(b));
17549 return isSgBasicBlock(b);
17550 }
17551
17553 SgStatement* b = fs->get_body();
17554 if (!isSgBasicBlock(b)) {
17556 fs->set_body(b);
17557 b->set_parent(fs);
17558
17559 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17561 }
17562 ROSE_ASSERT (isSgBasicBlock(b));
17563 return isSgBasicBlock(b);
17564 }
17565
17567 SgStatement* b = fs->get_true_body();
17568 if (!isSgBasicBlock(b)) {
17570 fs->set_true_body(b);
17571 b->set_parent(fs);
17572
17573 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17575#if 0
17576 printf ("In SageInterface::ensureBasicBlockAsTrueBodyOfIf(): Added SgBasicBlock b = %p to addedBasicBlockNodes.size() = %zu \n",b,addedBasicBlockNodes.size());
17577#endif
17578 }
17579 ROSE_ASSERT (isSgBasicBlock(b));
17580 return isSgBasicBlock(b);
17581 }
17582
17583// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17585 {
17586 // Record where normalization have been done so that we can preform denormalizations as required
17587 // for the token-based unparsing to generate minimal diffs.
17588
17589 SgBasicBlock* bb = isSgBasicBlock(s);
17590 ROSE_ASSERT(bb != NULL);
17591 addedBasicBlockNodes.push_back(bb);
17592#if 0
17593 printf ("In SageInterface::recordNormalizations(): Added SgBasicBlock = %p to addedBasicBlockNodes.size() = %zu \n",bb,addedBasicBlockNodes.size());
17594#endif
17595 }
17596
17597// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17599 {
17600 // Remove unused basic block IR nodes added as part of normalization.
17601 // This function should be called before the unparse step.
17602
17603#if 0
17604 printf ("In SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17605#endif
17606
17607 for (vector<SgBasicBlock*>::iterator i = addedBasicBlockNodes.begin(); i != addedBasicBlockNodes.end(); i++)
17608 {
17609 SgBasicBlock* b = *i;
17610 ROSE_ASSERT(b != NULL);
17611 if (b->get_statements().size() == 1)
17612 {
17613#if 0
17614 printf ("This SgBasicBlock can be denormalized: b = %p \n",b);
17615#endif
17616 SgStatement* parentOfBlock = isSgStatement(b->get_parent());
17617 ROSE_ASSERT(parentOfBlock != NULL);
17618
17619 bool wasPreviouslyModified = parentOfBlock->get_isModified();
17620
17621 SgStatement* s = b->get_statements()[0];
17622 ROSE_ASSERT(s != NULL);
17623
17624 switch (parentOfBlock->variantT())
17625 {
17626 case V_SgIfStmt:
17627 {
17628 SgIfStmt* ifStatement = isSgIfStmt(parentOfBlock);
17629 if (b == ifStatement->get_true_body())
17630 {
17631#if 0
17632 printf ("Calling set_true_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17633#endif
17634 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17635 ifStatement->set_true_body(s);
17636#if 0
17637 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17638#endif
17639 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17640 s->set_parent(ifStatement);
17641#if 0
17642 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17643#endif
17644 *i = NULL;
17645 // delete b;
17646 }
17647 else
17648 {
17649 ROSE_ASSERT(b == ifStatement->get_false_body());
17650#if 0
17651 printf ("Calling set_false_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17652#endif
17653 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17654 ifStatement->set_false_body(s);
17655#if 0
17656 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17657#endif
17658 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17659 s->set_parent(ifStatement);
17660#if 0
17661 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17662#endif
17663 *i = nullptr;
17664#if 0
17665 printf ("Mark as NOT modified after calling set_false_body on ifStatement = %p = %n \n",ifStatement,ifStatement->class_name().c_str());
17666#endif
17667#if 0
17668 printf ("Error: case not handled in case V_SgIfStmt: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17669 ROSE_ABORT();
17670#endif
17671 }
17672 break;
17673 }
17674
17675 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17676 case V_SgWhileStmt:
17677 {
17678 SgWhileStmt* whileStatement = isSgWhileStmt(parentOfBlock);
17679 if (b == whileStatement->get_body())
17680 {
17681 whileStatement->set_body(s);
17682 s->set_parent(whileStatement);
17683 }
17684 break;
17685 }
17686
17687 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17688 case V_SgSwitchStatement:
17689 {
17690 SgSwitchStatement* switchStatement = isSgSwitchStatement(parentOfBlock);
17691 if (b == switchStatement->get_body())
17692 {
17693 switchStatement->set_body(s);
17694 s->set_parent(switchStatement);
17695 }
17696 break;
17697 }
17698
17699 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17700 case V_SgForStatement:
17701 {
17702 SgForStatement* forStatement = isSgForStatement(parentOfBlock);
17703 if (b == forStatement->get_loop_body())
17704 {
17705 forStatement->set_loop_body(s);
17706 s->set_parent(forStatement);
17707 }
17708 break;
17709 }
17710
17711 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17712 case V_SgCaseOptionStmt:
17713 {
17714 SgCaseOptionStmt* caseOptionStatement = isSgCaseOptionStmt(parentOfBlock);
17715 if (b == caseOptionStatement->get_body())
17716 {
17717 caseOptionStatement->set_body(s);
17718 s->set_parent(caseOptionStatement);
17719 }
17720 break;
17721 }
17722
17723 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17724 case V_SgDefaultOptionStmt:
17725 {
17726 SgDefaultOptionStmt* defaultOptionStatement = isSgDefaultOptionStmt(parentOfBlock);
17727 if (b == defaultOptionStatement->get_body())
17728 {
17729 defaultOptionStatement->set_body(s);
17730 s->set_parent(defaultOptionStatement);
17731 }
17732 break;
17733 }
17734
17735 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17736 case V_SgDoWhileStmt:
17737 {
17738 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(parentOfBlock);
17739 if (b == doWhileStatement->get_body())
17740 {
17741 doWhileStatement->set_body(s);
17742 s->set_parent(doWhileStatement);
17743 }
17744 break;
17745 }
17746
17747 default:
17748 {
17749 printf ("Error: case not handled in switch: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17750 ROSE_ABORT();
17751 }
17752 }
17753
17754 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17755 if (wasPreviouslyModified == false)
17756 {
17757 if (parentOfBlock->get_isModified() == true)
17758 {
17759#if 0
17760 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());
17761#endif
17762 parentOfBlock->set_isModified(false);
17763 }
17764
17765 }
17766#if 0
17767 printf ("Exiting as a test! \n");
17768 ROSE_ABORT();
17769#endif
17770 }
17771 }
17772
17773#if 0
17774 printf ("Leaving SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17775#endif
17776 }
17777
17778
17780 SgStatement* b = fs->get_false_body();
17781 // if no false body at all AND no-create-empty-body
17782 if (!createEmptyBody && (b == NULL || isSgNullStatement(b)))
17783 return NULL;
17784 if (!isSgBasicBlock(b)) {
17785 b = SageBuilder::buildBasicBlock(b); // This works if b is NULL as well (producing an empty block)
17786 fs->set_false_body(b);
17787 b->set_parent(fs);
17788
17789 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17791 }
17792 ROSE_ASSERT (isSgBasicBlock(b));
17793 return isSgBasicBlock(b);
17794 }
17795
17797 SgStatement* b = fs->get_body();
17798 if (!isSgBasicBlock(b)) {
17800 fs->set_body(b);
17801 b->set_parent(fs);
17802 }
17803 ROSE_ASSERT (isSgBasicBlock(b));
17804 return isSgBasicBlock(b);
17805 }
17806
17808{
17809 SgStatement* b = fs->get_body();
17810 if (!isSgBasicBlock(b)) {
17812 fs->set_body(b);
17813 b->set_parent(fs);
17814 }
17815 ROSE_ASSERT (isSgBasicBlock(b));
17816 return isSgBasicBlock(b);
17817}
17818
17820{
17821 bool rt = false;
17822 ROSE_ASSERT(s);
17823 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17824 ROSE_ASSERT(p);
17825
17826 switch (p->variantT())
17827 {
17828 case V_SgForStatement:
17829 {
17830 if (isSgForStatement(p)->get_loop_body() == s)
17831 rt = true;
17832 break;
17833 }
17834 case V_SgUpcForAllStatement: // PP
17835 {
17836 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17837 if (upcforall.get_loop_body() == s)
17838 rt = true;
17839 break;
17840 }
17841 case V_SgWhileStmt:
17842 {
17843 if (isSgWhileStmt(p)->get_body() == s)
17844 rt = true;
17845 break;
17846 }
17847 case V_SgDoWhileStmt:
17848 {
17849 if (isSgDoWhileStmt(p)->get_body() == s)
17850 rt = true;
17851 break;
17852 }
17853 case V_SgSwitchStatement:
17854 {
17855 if (isSgSwitchStatement(p)->get_body() == s)
17856 rt = true;
17857 break;
17858 }
17859 case V_SgCaseOptionStmt:
17860 {
17861 if (isSgCaseOptionStmt(p)->get_body() == s)
17862 rt = true;
17863 break;
17864 }
17865 case V_SgDefaultOptionStmt:
17866 {
17867 if (isSgDefaultOptionStmt(p)->get_body() == s)
17868 rt = true;
17869 break;
17870 }
17871 case V_SgCatchOptionStmt:
17872 {
17873 if (isSgCatchOptionStmt(p)->get_body() == s)
17874 rt = true;
17875 break;
17876 }
17877 case V_SgIfStmt:
17878 {
17879 if (isSgIfStmt(p)->get_true_body() == s)
17880 rt = true;
17881 else if (isSgIfStmt(p)->get_false_body() == s)
17882 rt = true;
17883 break;
17884 }
17885 default:
17886 {
17887 if (isSgOmpBodyStatement(p))
17888 rt = true;
17889 break;
17890 }
17891 }
17892 return rt;
17893}
17894
17896//etc.
17898{
17899 ROSE_ASSERT (singleStmt != NULL); // not NULL
17900 ROSE_ASSERT (isSgBasicBlock(singleStmt) == NULL); //not a block
17901 ROSE_ASSERT (isBodyStatement(singleStmt) == true); // is a body statement
17902
17903 SgBasicBlock* rt = NULL;
17904
17905
17906
17907 SgStatement* s = singleStmt;
17908 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17909 ROSE_ASSERT(p);
17910 switch (p->variantT())
17911 {
17912 case V_SgForStatement:
17913 {
17914 if (isSgForStatement(p)->get_loop_body() == s)
17915 rt = ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17916 break;
17917 }
17918 case V_SgUpcForAllStatement: // PP
17919 {
17920 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17921
17922 if (upcforall.get_loop_body() == s)
17923 rt = ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17924 break;
17925 }
17926 case V_SgWhileStmt:
17927 {
17928 if (isSgWhileStmt(p)->get_body() == s)
17929 rt = ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17930 break;
17931 }
17932 case V_SgDoWhileStmt:
17933 {
17934 if (isSgDoWhileStmt(p)->get_body() == s)
17935 rt = ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17936 break;
17937 }
17938 case V_SgSwitchStatement:
17939 {
17940 if (isSgSwitchStatement(p)->get_body() == s)
17941 rt = ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17942 break;
17943 }
17944 case V_SgCaseOptionStmt:
17945 {
17946 if (isSgCaseOptionStmt(p)->get_body() == s)
17947 rt = ensureBasicBlockAsBodyOfCaseOption(isSgCaseOptionStmt(p));
17948 break;
17949 }
17950 case V_SgDefaultOptionStmt:
17951 {
17952 if (isSgDefaultOptionStmt(p)->get_body() == s)
17953 rt = ensureBasicBlockAsBodyOfDefaultOption(isSgDefaultOptionStmt(p));
17954 break;
17955 }
17956 case V_SgCatchOptionStmt:
17957 {
17958 if (isSgCatchOptionStmt(p)->get_body() == s)
17959 rt = ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17960 break;
17961 }
17962 case V_SgIfStmt:
17963 {
17964 if (isSgIfStmt(p)->get_true_body() == s)
17965 rt = ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17966 else if (isSgIfStmt(p)->get_false_body() == s)
17967 rt = ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17968 break;
17969 }
17970 default:
17971 {
17972 if (isSgOmpBodyStatement(p))
17973 {
17974 rt = ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17975 }
17976 break;
17977 }
17978 }
17979 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.
17980 return rt;
17981}
17982
17983#if 0
17984SgLocatedNode* SageInterface::ensureBasicBlockAsParent(SgStatement* s)
17985{
17986 ROSE_ASSERT(s);
17987
17988 //Vulov: The parent of a statement is not necessarily a statement. It could be SgStatementExpression
17989 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17990 ROSE_ASSERT(p);
17991 switch (p->variantT())
17992 {
17993 case V_SgBasicBlock: return isSgBasicBlock(p);
17994 case V_SgForStatement:
17995 {
17996 if (isSgForStatement(p)->get_loop_body() == s)
17997 return ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17998 else if (isSgForStatement(p)->get_test() == s)
17999 {
18000 }
18001 else if (isSgForStatement(p)->get_for_init_stmt() == s)
18002 {
18003 }
18004 else ROSE_ABORT();
18005 break;
18006 }
18007 case V_SgUpcForAllStatement: // PP
18008 {
18009 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
18010
18011 if (upcforall.get_loop_body() == s)
18012 return ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
18013
18014 ROSE_ASSERT( (s == upcforall.get_for_init_stmt())
18015 || (s == upcforall.get_test())
18016 );
18017 break;
18018 }
18019 case V_SgWhileStmt:
18020 {
18021 if (isSgWhileStmt(p)->get_body() == s)
18022 return ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
18023 else if (isSgWhileStmt(p)->get_condition() == s)
18024 {
18025 }
18026 else ROSE_ABORT();
18027 break;
18028 }
18029 case V_SgDoWhileStmt:
18030 {
18031 if (isSgDoWhileStmt(p)->get_body() == s)
18032 return ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
18033 else if (isSgDoWhileStmt(p)->get_condition() == s)
18034 {
18035 }
18036 else ROSE_ABORT();
18037 break;
18038 }
18039 case V_SgSwitchStatement:
18040 {
18041 if (isSgSwitchStatement(p)->get_body() == s)
18042 return ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
18043 else if (isSgSwitchStatement(p)->get_item_selector() == s)
18044 {
18045 }
18046 else ROSE_ABORT();
18047 break;
18048 }
18049 case V_SgCatchOptionStmt:
18050 {
18051 if (isSgCatchOptionStmt(p)->get_body() == s)
18052 return ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
18053 else if (isSgCatchOptionStmt(p)->get_condition() == s)
18054 {
18055 }
18056 else ROSE_ABORT();
18057 break;
18058 }
18059 case V_SgIfStmt:
18060 {
18061 if (isSgIfStmt(p)->get_true_body() == s)
18062 return ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
18063 else if (isSgIfStmt(p)->get_false_body() == s)
18064 return ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
18065 else if (isSgIfStmt(p)->get_conditional() == s)
18066 {
18067 }
18068 else ROSE_ABORT();
18069 break;
18070 }
18071 default:
18072 {
18073 if (isSgOmpBodyStatement(p))
18074 {
18075 return ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
18076 }
18077 else
18078 // Liao, 7/3/2008 We allow other conditions to fall through,
18079 // they are legal parents with list of statements as children.
18080 //cerr << "Unhandled parent block:"<< p->class_name() << endl;
18081 // ROSE_ASSERT (!"Bad parent in ensureBasicBlockAsParent");
18082 break;
18083 }
18084 }
18085 return p;
18086}
18087
18088 void SageInterface::changeAllLoopBodiesToBlocks(SgNode* top) {
18089 cerr<<"Warning: SageInterface::changeAllLoopBodiesToBlocks() is being replaced by SageInterface::changeAllBodiesToBlocks()."<<endl;
18090 cerr<<"Please use SageInterface::changeAllBodiesToBlocks() if you can."<<endl;
18092 }
18093
18094#endif
18095 void SageInterface::changeAllBodiesToBlocks(SgNode* top, bool createEmptyBody /*= true*/ ) {
18096 class Visitor: public AstSimpleProcessing {
18097 public:
18098 bool allowEmptyBody;
18099 Visitor (bool flag):allowEmptyBody(flag) {}
18100 virtual void visit(SgNode* n) {
18101
18102 bool wasPreviouslyModified = n->get_isModified();
18103
18104 switch (n->variantT()) {
18105 case V_SgForStatement: {
18106 ensureBasicBlockAsBodyOfFor(isSgForStatement(n));
18107 break;
18108 }
18109 case V_SgWhileStmt: {
18110 ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(n));
18111 break;
18112 }
18113 case V_SgDoWhileStmt: {
18114 ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(n));
18115 break;
18116 }
18117 case V_SgSwitchStatement: {
18118 ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(n));
18119 break;
18120 }
18121 case V_SgIfStmt: {
18122 ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(n));
18123 ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(n), allowEmptyBody);
18124#if 0
18125 // DQ (10/6/2015): Debugging why changes are being made to the AST for token-based unparsing.
18126 printf ("In changeAllBodiesToBlocks(): case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
18127#endif
18128#if 0
18129 // Reset this to false as a test.
18130 if (n->get_isModified() == true)
18131 {
18132 n->set_isModified(false);
18133 printf ("In changeAllBodiesToBlocks(): AFTER RESET: case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
18134 }
18135#endif
18136 break;
18137 }
18138 case V_SgCatchOptionStmt: {
18139 ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(n));
18140 break;
18141 }
18142 case V_SgUpcForAllStatement: {
18143 ensureBasicBlockAsBodyOfUpcForAll(isSgUpcForAllStatement(n));
18144 break;
18145 }
18146
18147 default:
18148 {
18149 if (isSgOmpBodyStatement(n))
18150 ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(n));
18151 break;
18152 }
18153 }
18154
18155 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
18156 if (wasPreviouslyModified == false)
18157 {
18158 if (n->get_isModified() == true)
18159 {
18160#if 0
18161 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());
18162#endif
18163 n->set_isModified(false);
18164 }
18165
18166 }
18167
18168 }
18169 };
18170 Visitor(createEmptyBody).traverse(top, postorder);
18171 }
18172
18173
18174// Replace a given expression with a list of statements produced by a
18175// generator. The generator, when given a variable as input, must produce
18176// some code which leaves its result in the given variable. The output
18177// from the generator is then inserted into the original program in such a
18178// way that whenever the expression had previously been evaluated, the
18179// statements produced by the generator are run instead and their result is
18180// used in place of the expression.
18181// Assumptions: not currently traversing from or the statement it is in
18182void
18184 {
18185 // DQ (3/11/2006): The problem here is that the test expression for a "for loop" (SgForStmt)
18186 // is assumed to be a SgExpression. This was changed in Sage III as part of a bugfix and so
18187 // the original assumptions upon which this function was based are not incorrect, hence the bug!
18188 // Note that a number of cases were changed when this fix was made to SageIII (see documentation
18189 // for SgScopeStatement).
18190
18191#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18192 SgStatement* enclosingStatement = getStatementOfExpression(from);
18193 SgExprStatement* exprStatement = isSgExprStatement(enclosingStatement);
18194
18195 SgForStatement* forStatement = isSgForStatement(enclosingStatement);
18196 SgReturnStmt* returnStatement = isSgReturnStmt(enclosingStatement);
18197 SgVariableDeclaration* varDeclarationStatement = isSgVariableDeclaration(enclosingStatement);
18198
18199
18200 // DQ (3/11/2006): Bugfix for special cases of conditional that are either SgStatement or SgExpression IR nodes.
18201
18202 ROSE_ASSERT (exprStatement || forStatement || returnStatement || varDeclarationStatement);
18203
18204 if (varDeclarationStatement)
18205 {
18207 }
18208 else
18209 {
18210 SgExpression* root = getRootOfExpression(from);
18211 ROSE_ASSERT (root);
18212 // printf ("root = %p \n",root);
18213 {
18214 if (forStatement && forStatement->get_increment() == root)
18215 {
18216 // printf ("Convert step of for statement \n");
18217 // Convert step of for statement
18218 // for (init; test; e) body; (where e contains from) becomes
18219 // for (init; test; ) {
18220 // body (with "continue" changed to "goto label");
18221 // label: e;
18222 // }
18223 // std::cout << "Converting for step" << std::endl;
18224 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(forStatement->get_increment());
18225 forStatement->get_increment()->set_parent(incrStmt);
18226
18227 SageInterface::addStepToLoopBody(forStatement, incrStmt);
18229 forStatement->set_increment(ne);
18230 ne->set_parent(forStatement);
18232 }
18233 else
18234 {
18235 SgStatement* enclosingStmtParent = isSgStatement(enclosingStatement->get_parent());
18236 assert (enclosingStmtParent);
18237 SgWhileStmt* whileStatement = isSgWhileStmt(enclosingStmtParent);
18238 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(enclosingStmtParent);
18239 SgIfStmt* ifStatement = isSgIfStmt(enclosingStmtParent);
18240 SgSwitchStatement* switchStatement = isSgSwitchStatement(enclosingStmtParent);
18241 SgForStatement* enclosingForStatement = isSgForStatement(enclosingStmtParent);
18242 if (enclosingForStatement && enclosingForStatement->get_test() == exprStatement)
18243 {
18244 // Convert test of for statement:
18245 // for (init; e; step) body; (where e contains from) becomes
18246 // for (init; true; step) {
18247 // bool temp;
18248 // temp = e;
18249 // if (!temp) break;
18250 // body;
18251 // }
18252 // in which "temp = e;" is rewritten further
18253 // std::cout << "Converting for test" << std::endl;
18254 pushTestIntoBody(enclosingForStatement);
18256 }
18257 else if (whileStatement && whileStatement->get_condition() == exprStatement)
18258 {
18259 // printf ("Convert while statements \n");
18260 // Convert while statement:
18261 // while (e) body; (where e contains from) becomes
18262 // while (true) {
18263 // bool temp;
18264 // temp = e;
18265 // if (!temp) break;
18266 // body;
18267 // }
18268 // in which "temp = e;" is rewritten further
18269 // std::cout << "Converting while test" << std::endl;
18270 pushTestIntoBody(whileStatement);
18271 // FixSgTree(whileStatement);
18273 }
18274 else if (doWhileStatement && doWhileStatement->get_condition() == exprStatement)
18275 {
18276 // printf ("Convert do-while statements \n");
18277 // Convert do-while statement:
18278 // do body; while (e); (where e contains from) becomes
18279 // {bool temp = true;
18280 // do {
18281 // body (with "continue" changed to "goto label";
18282 // label:
18283 // temp = e;} while (temp);}
18284 // in which "temp = e;" is rewritten further
18285 // std::cout << "Converting do-while test" << std::endl;
18286 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18287 // printf ("Building IR node #14: new SgBasicBlock = %p \n",new_statement);
18288 assert (doWhileStatement->get_parent());
18289 new_statement->set_parent(doWhileStatement->get_parent());
18290 myStatementInsert(doWhileStatement, new_statement, false);
18291 SageInterface::myRemoveStatement(doWhileStatement);
18292 SgName varname = "rose__temp1"; // Does not need to be unique, but must not be used in user code anywhere
18293 SgAssignInitializer* assignInitializer = buildAssignInitializer(
18294 buildBoolValExp(true));
18295 //SageInterface::getBoolType(doWhileStatement));
18297 varname, buildBoolType(), assignInitializer, new_statement);
18298
18299 SgInitializedName* initname = new_decl->get_variables().back();
18300 initname->set_scope(new_statement);
18301
18302 // DQ (12/14/2006): set the parent of the SgAssignInitializer to the variable (SgInitializedName).
18303 assignInitializer->set_parent(initname);
18304
18305#if 1
18306 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18308#else
18309 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18310 new_statement->insert_symbol(varname, varsym);
18311 varsym->set_parent(new_statement->get_symbol_table());
18312#endif
18313
18314 SageInterface::appendStatement(new_decl, new_statement);
18315 SageInterface::appendStatement(doWhileStatement, new_statement);
18316 assert (varsym);
18317 SgCastExp* castExp1 = buildCastExp(root,buildBoolType());
18318 SgVarRefExp* vr = buildVarRefExp(varsym);
18319 vr->set_lvalue(true);
18320
18321 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp1);
18322
18323 SageInterface::addStepToLoopBody(doWhileStatement, temp_setup);
18324 SgVarRefExp* varsymVr = buildVarRefExp(varsym);
18325
18327 varsymVr->set_parent(condStmt);
18328 doWhileStatement->set_condition(condStmt);
18329 condStmt->set_parent(doWhileStatement);
18331 }
18332 else if (ifStatement && ifStatement->get_conditional() == exprStatement)
18333 {
18334 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18335 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18336 assert (ifStatement->get_parent());
18337 new_statement->set_parent(ifStatement->get_parent());
18338 myStatementInsert(ifStatement, new_statement, false);
18340 SgName varname = "rose__temp2"; // Does not need to be unique, but must not be used in user code anywhere
18341 SgBoolValExp* trueVal = buildBoolValExp(true);
18342
18344
18346 buildBoolType(), ai,new_statement);
18347 SgInitializedName* initname = new_decl->get_variables().back();
18348 ai->set_parent(initname);
18349 initname->set_scope(new_statement);
18350#if 1
18351 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18353#else
18354 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18355 new_statement->insert_symbol(varname, varsym);
18356 varsym->set_parent(new_statement->get_symbol_table());
18357#endif
18358 SageInterface::appendStatement(new_decl, new_statement);
18359 ifStatement->set_parent(new_statement);
18360 assert (varsym);
18361
18362 SgCastExp* castExp2 = SageBuilder::buildCastExp(root, SageInterface::getBoolType(ifStatement));
18363 SgVarRefExp* vr = buildVarRefExp(varsym);
18364 vr->set_lvalue(true);
18365 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp2 );
18366 SageInterface::appendStatement(temp_setup, new_statement);
18367 SageInterface::appendStatement(ifStatement, new_statement);
18370 ifStatement->set_conditional(es);
18371 es->set_parent(ifStatement);
18373 }
18374 else if (switchStatement && switchStatement->get_item_selector() == exprStatement)
18375 {
18376 SgExpression* switchCond = exprStatement->get_expression();
18377 ROSE_ASSERT (switchCond);
18378 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18379 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18380 assert (switchStatement->get_parent());
18381 new_statement->set_parent(switchStatement->get_parent());
18382 myStatementInsert(switchStatement, new_statement, false);
18383 SageInterface::myRemoveStatement(switchStatement);
18384 SgName varname = "rose__temp3"; // Does not need to be unique, but must not be used in user code anywhere
18385 switchCond->set_parent(NULL);
18386 SgVariableDeclaration* new_decl = SageBuilder::buildVariableDeclaration(varname, switchCond->get_type(), SageBuilder::buildAssignInitializer(switchCond), new_statement);
18388 SageInterface::appendStatement(new_decl, new_statement);
18389 switchStatement->set_parent(new_statement);
18390 assert (varsym);
18391
18392
18393 SageInterface::appendStatement(switchStatement, new_statement);
18396 switchStatement->set_item_selector(es);
18397 es->set_parent(switchStatement);
18399 }
18400 else
18401 {
18402 // printf ("Handles expression and return statements \n");
18403 // Handles expression and return statements
18404 // std::cout << "Converting other statement" << std::endl;
18406 }
18407 }
18408 }
18409 }
18410
18411#endif
18412
18413 // printf ("Leaving replaceExpressionWithStatement(from,to) \n");
18414 }
18415
18424
18425// Similar to replaceExpressionWithStatement, but with more restrictions.
18426// Assumptions: from is not within the test of a loop or if
18427// not currently traversing from or the statement it is in
18429 {
18430
18431#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18432 SgStatement* stmt = getStatementOfExpression(from);
18433
18434 if (isSgExprStatement(stmt))
18435 {
18436 SgExpression* top = getRootOfExpression(from);
18437
18438
18439 if (top == from)
18440 {
18441 SgStatement* generated = to->generate(0);
18442 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18443 generated->set_parent(stmt->get_parent());
18444 return;
18445 }
18446 else
18447 {
18448 if (isSgAssignOp(top) && isSgAssignOp(top)->get_rhs_operand() == from)
18449 {
18450 SgAssignOp* t = isSgAssignOp(top);
18451 SgStatement* generated = to->generate(t->get_lhs_operand());
18452 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18453 generated->set_parent(stmt->get_parent());
18454 return;
18455 }
18456 else
18457 {
18458 // printf ("In replaceSubexpressionWithStatement(): Statement not generated \n");
18459 }
18460 }
18461 }
18462
18463 // cout << "1: " << getStatementOfExpression(from)->unparseToString() << endl;
18465 // cout << "2: " << getStatementOfExpression(from)->unparseToString() << endl;
18466 convertInitializerIntoAssignment(init);
18467 // cout << "3: " << getStatementOfExpression(from)->unparseToString() << endl;
18468 // cout << "3a: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18469 SgExprStatement* new_stmt = isSgExprStatement(getStatementOfExpression(from));
18470 assert (new_stmt != NULL); // Should now have this form because of conversion
18471 replaceAssignmentStmtWithStatement(new_stmt, to);
18472
18473 // printf ("In replaceSubexpressionWithStatement: new_stmt = %p = %s \n",new_stmt,new_stmt->class_name().c_str());
18474 // cout << "4: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18475
18476#endif
18477 }
18478
18479
18480 // Liao, 6/27/2008
18481 //Tasks
18482 // find all return statements
18483 // rewrite it to temp = expression; return temp; if expression is not a single value.
18484 // insert s right before 'return xxx;'
18486 {
18487 int result = 0;
18488 ROSE_ASSERT(func&&s);
18489 // vector<SgReturnStmt* > stmts = findReturnStmts(func);
18490 Rose_STL_Container <SgNode* > stmts = NodeQuery::querySubTree(func, V_SgReturnStmt);
18491 //vector<SgReturnStmt*>::iterator i;
18492 Rose_STL_Container<SgNode*>::iterator i;
18493 for (i=stmts.begin();i!=stmts.end();i++)
18494 {
18495 SgReturnStmt* cur_stmt = isSgReturnStmt(*i);
18496 ROSE_ASSERT(cur_stmt);
18497 SgExpression * exp = cur_stmt->get_expression();
18498 // TV (05/03/2011) Catch the case "return ;" where exp is NULL
18499 bool needRewrite = (exp != NULL) && !(isSgValueExp(exp));
18500 if (needRewrite)
18501 {
18502 splitExpression(exp);
18503 }
18504 // avoid reusing the statement
18505 if (result>=1 )
18506 s = copyStatement(s);
18507 insertStatementBefore(cur_stmt,s);
18508 result ++;
18509 } // for
18510 if (stmts.size()==0 ) // a function without any return at all,
18511 {
18512 SgBasicBlock * body = func->get_definition()->get_body();
18513 if (body== NULL)
18514 {
18515 cout<<"In instrumentEndOfFunction(), found an empty function body.! "<<endl;
18516 ROSE_ABORT();
18517 }
18518 appendStatement(s,body);
18519 result ++;
18520 }
18521 return result;
18522 } // instrumentEndOfFunction
18523
18525 {
18526 ROSE_ASSERT(stmt);
18527 return ((stmt->get_declarationModifier()).get_storageModifier()).isStatic();
18528 } // isStatic()
18529
18532 {
18533 ROSE_ASSERT(stmt);
18534 return ((stmt->get_declarationModifier()).get_storageModifier()).setStatic();
18535 }
18536
18538 {
18539 ROSE_ASSERT(stmt);
18540 return ((stmt->get_declarationModifier()).get_storageModifier()).isExtern();
18541 } // isExtern()
18542
18543
18546 {
18547 ROSE_ASSERT(stmt);
18548 return ((stmt->get_declarationModifier()).get_storageModifier()).setExtern();
18549 }
18550
18551 // Check if an SgInitializedName is "mutable' (has storage modifier set)
18553 {
18554 ROSE_ASSERT(name);
18555 return name->get_storageModifier().isMutable();
18556 }
18557
18558 // True if a parameter name is a Jovial output parameter
18560 {
18561 return isMutable(name);
18562 }
18563
18564 // Get a vector of Jovial input parameters from the function parameter list
18565 // TODO: Look into making this work for Fortran
18566 std::vector<SgInitializedName*> SageInterface::getInParameters(const SgInitializedNamePtrList &params)
18567 {
18568 std::vector<SgInitializedName*> in_params;
18569 BOOST_FOREACH (SgInitializedName* name, params)
18570 {
18571 if (!isJovialOutParam(name)) in_params.push_back(name);
18572 }
18573 return in_params;
18574 }
18575
18576 // Get a list of Jovial output parameters from the function parameter list
18577 // TODO: Look into making this work for Fortran
18578 std::vector<SgInitializedName*> SageInterface::getOutParameters(const SgInitializedNamePtrList &params)
18579 {
18580 std::vector<SgInitializedName*> out_params;
18581 BOOST_FOREACH (SgInitializedName* name, params)
18582 {
18583 if (isJovialOutParam(name)) out_params.push_back(name);
18584 }
18585 return out_params;
18586 }
18587
18589 switch (expr->variantT()) {
18590 case V_SgCharVal: return (long long)(isSgCharVal(expr)->get_value());
18591 case V_SgSignedCharVal: return (long long)(isSgSignedCharVal(expr)->get_value());
18592 case V_SgUnsignedCharVal: return isSgUnsignedCharVal(expr)->get_value();
18593 case V_SgShortVal: return (long long)(isSgShortVal(expr)->get_value());
18594 case V_SgUnsignedShortVal: return isSgUnsignedShortVal(expr)->get_value();
18595 case V_SgIntVal: return (long long)(isSgIntVal(expr)->get_value());
18596 case V_SgUnsignedIntVal: return isSgUnsignedIntVal(expr)->get_value();
18597 case V_SgLongIntVal: return (long long)(isSgLongIntVal(expr)->get_value());
18598 case V_SgUnsignedLongVal: return isSgUnsignedLongVal(expr)->get_value();
18599 case V_SgLongLongIntVal: return isSgLongLongIntVal(expr)->get_value();
18600 case V_SgUnsignedLongLongIntVal: return isSgUnsignedLongLongIntVal(expr)->get_value();
18601 case V_SgBoolValExp: return (long long )(isSgBoolValExp(expr)->get_value());
18602
18603 // DQ (2/18/2015): Make this a better error message.
18604 // default: ROSE_ASSERT (!"Bad kind in getIntegerConstantValue");
18605 default:
18606 {
18607 printf ("ERROR: In SageInterface::getIntegerConstantValue(): default reached: expr = %p = %s \n",expr,expr->class_name().c_str());
18608 ROSE_ASSERT (false);
18609 }
18610
18611 }
18612
18613 ROSE_ASSERT (!"Bad kind return in getIntegerConstantValue");
18614 return 0;
18615 }
18616
18617
18618#ifdef ROSE_ENABLE_BINARY_ANALYSIS
18619// tps : 28 Oct 2008 - support for finding the main interpretation
18620// rpm : 18 Sep 2009 - rewritten to support multiple files per interpretation
18624SageInterface::getMainInterpretation(SgAsmGenericFile *file)
18625{
18626 SgBinaryComposite *binary = getEnclosingNode<SgBinaryComposite>(file);
18627 ROSE_ASSERT(binary!=NULL);
18628
18629 /* Find the only header or the PE header of this file */
18630 SgAsmGenericHeader *requisite_header = NULL; /*the returned interpretation must point to this header*/
18631 const SgAsmGenericHeaderPtrList &headers = file->get_headers()->get_headers();
18632 if (1==headers.size()) {
18633 requisite_header = headers[0];
18634 } else {
18635 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18636 if (isSgAsmPEFileHeader(*hi)) {
18637 requisite_header = isSgAsmPEFileHeader(*hi);
18638 break;
18639 }
18640 }
18641 }
18642 ROSE_ASSERT(requisite_header!=NULL);
18643
18644 /* Find an interpretation that points to this header */
18645 const SgAsmInterpretationPtrList &interps = binary->get_interpretations()->get_interpretations();
18646 for (SgAsmInterpretationPtrList::const_iterator ii=interps.begin(); ii!=interps.end(); ++ii) {
18647 const SgAsmGenericHeaderPtrList &headers = (*ii)->get_headers()->get_headers();
18648 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18649 if ((*hi)==requisite_header)
18650 return *ii;
18651 }
18652 }
18653
18654 ROSE_ASSERT(!"no appropriate interpretation");
18655 return NULL;
18656}
18657#endif
18658
18660 {
18661 public:
18662 // This is the simpliest possible version of a deep copy SgCopyHelp::copyAst() member function.
18663 // Note that the root of the does not have its file info set like its children.
18664 virtual SgNode *copyAst(const SgNode *n)
18665 {
18666 // DQ (2/26/2009): This defines a simple concept of "deep" copy. It forms a more testable building block, I hope.
18667 SgNode* copy = n->copy(*this);
18668
18669 // Also mark this as a transformation and to be output in unparsing (so it will be output by the code generator).
18670 Sg_File_Info* fileInfo = copy->get_file_info();
18671 if (fileInfo != NULL)
18672 {
18673 // Must make this for output (checked in unparser), marking as a transformation is not checked
18674 fileInfo->setOutputInCodeGeneration();
18675 fileInfo->setTransformation();
18676 }
18677
18678 return copy;
18679 }
18680 } collectDependentDeclarationsCopyType;
18681
18682
18684 {
18685 // This traversal collects the includes at the top of a file.
18686
18687 public:
18688 vector<PreprocessingInfo*> cppDirectiveList;
18689
18690 void visit(SgNode *astNode);
18691 };
18692
18693
18694void
18696 {
18697 SgLocatedNode* locatedNode = isSgLocatedNode(astNode);
18698 if (locatedNode != NULL)
18699 {
18700 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
18701
18702 if (comments != NULL)
18703 {
18704#if 0
18705 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18706#endif
18707 AttachedPreprocessingInfoType::iterator i;
18708 for (i = comments->begin(); i != comments->end(); i++)
18709 {
18710 ROSE_ASSERT ( (*i) != NULL );
18711#if 0
18712 printf (" Attached Comment (relativePosition=%s): %s\n",
18713 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18714 (*i)->getString().c_str());
18715 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
18716 (*i)->get_file_info()->display("comment/directive location");
18717#endif
18718
18719 // We only save the #include directives, but likely we should be collecting ALL directives to
18720 // avoid the collection of #include that is meant to be hidden in an #if 0 ... #endif pairing.
18721 // if ((*i)->getTypeOfDirective() == PreprocessingInfo::CpreprocessorIncludeDeclaration)
18722 {
18723 // This is an include directive.
18724 cppDirectiveList.push_back(*i);
18725#if 0
18726 printf (" Attached include directive (relativePosition=%s): %s\n",
18727 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18728 (*i)->getString().c_str());
18729#endif
18730 }
18731 }
18732 }
18733 else
18734 {
18735#if 0
18736 printf ("No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18737#endif
18738 }
18739 }
18740 }
18741
18742
18743// This is part of a mechanism to collect directives from code that is to be outlined.
18744// However if we collect include directives we likely should really be collecting ALL
18745// directives (since the #include could be inside of an #if 0 ... #endif pairing.
18746// This level of detail will be addressed later (in an iterative approach).
18747vector<PreprocessingInfo*>
18748collectCppDirectives ( SgSourceFile* file )
18749 {
18750 // This function is used to collect include directives from the whole file.
18752 t.traverse(file,preorder);
18753
18754 return t.cppDirectiveList;
18755 }
18756
18757
18758vector<PreprocessingInfo*>
18759collectCppDirectives ( SgLocatedNode* n )
18760 {
18761 // This function is used to collect include directives from specific dependent declarations.
18763 t.traverse(n,preorder);
18764
18765 return t.cppDirectiveList;
18766 }
18767
18768// Debugging support.
18769void
18770outputPreprocessingInfoList ( const vector<PreprocessingInfo*> & l )
18771 {
18772 // This function support debugging the generated directive lists.
18773
18774 vector<PreprocessingInfo*>::const_iterator i = l.begin();
18775 while ( i != l.end() )
18776 {
18777 printf (" Attached include directive (relativePosition=%s): %s\n",
18778 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18779 (*i)->getString().c_str());
18780 i++;
18781 }
18782 }
18783
18784
18785
18787getAssociatedDeclaration( SgScopeStatement* scope )
18788 {
18789 //TODO This should become a member of SgScopeStatement
18790
18791 SgDeclarationStatement* declaration = NULL;
18792 switch(scope->variantT())
18793 {
18794 case V_SgNamespaceDefinitionStatement:
18795 {
18796 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
18797 declaration = namespaceDefinition->get_namespaceDeclaration();
18798 break;
18799 }
18800
18801 case V_SgClassDefinition:
18802 case V_SgTemplateInstantiationDefn: // Liao, 5/12/2009
18803 {
18804 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
18805 declaration = classDefinition->get_declaration();
18806 break;
18807 }
18808
18809 default:
18810 {
18811 printf ("Error: default reached in getAssociatedDeclaration(): scope = %p = %s \n",scope,scope->class_name().c_str());
18812 ROSE_ABORT();
18813 }
18814 }
18815
18816 // There may be some scopes that don't have an associated declaration.
18817 ROSE_ASSERT(declaration != NULL);
18818
18819 return declaration;
18820 }
18821
18822
18824 {
18825 public:
18826 // Accumulate a list of copies of associated declarations referenced in the AST subtree
18827 // (usually of the outlined functions) to insert in the separate file to support outlining.
18828 vector<SgDeclarationStatement*> declarationList;
18829
18830 // Save the list of associated symbols of dependent declarations identified so that we can
18831 // support their replacement in the new AST.
18832 vector<SgSymbol*> symbolList;
18833
18834 // Keep track of declarations already copied so that we don't copy them more than once and try to insert them.
18835 set<SgDeclarationStatement*> alreadySavedDeclarations;
18836
18837 // Required visit function for the AST traversal
18838 void visit(SgNode *astNode);
18839 private:
18840 void addDeclaration(SgDeclarationStatement* decl);
18841 };
18842
18844getGlobalScopeDeclaration( SgDeclarationStatement* inputDeclaration )
18845 {
18846 // DQ (2/16/2009): Basically if a class is used from a namespace (or any outer scope) and we
18847 // outline the reference to the class, we have to declare not the class but the outer scope
18848 // (which will have the class included).
18849
18850 SgDeclarationStatement* returnDeclaration = inputDeclaration;
18851
18852 // I think that we have to copy the outer scope if the declaration's scope is not SgGlobal.
18853 SgScopeStatement* scope = inputDeclaration->get_scope();
18854 ROSE_ASSERT(scope != NULL);
18855
18856 // printf ("inputDeclaration->get_scope() = %p = %s \n",scope,scope->class_name().c_str());
18857
18858 // If the input declaration is not in global scope then find the parent declaration that is in global scope!
18859 SgGlobal* globalScope = isSgGlobal(scope);
18860 if (globalScope == NULL)
18861 {
18862 // Traverse back to the global scope to include outer declarations which contain the "declaration"
18863 // printf ("Traverse back to the global scope to include outer declarations \n");
18864
18865 SgScopeStatement* parentScope = scope;
18866 SgDeclarationStatement* associatedDeclaration = returnDeclaration;
18867 ROSE_ASSERT(parentScope != NULL);
18868 while (globalScope == NULL)
18869 {
18870 associatedDeclaration = getAssociatedDeclaration(parentScope);
18871 ROSE_ASSERT(associatedDeclaration != NULL);
18872
18873 parentScope = parentScope->get_scope();
18874 globalScope = isSgGlobal(parentScope);
18875 }
18876
18877 returnDeclaration = associatedDeclaration;
18878 }
18879
18880 return returnDeclaration;
18881 }
18882
18883
18884// Debugging support.
18885void
18886outputDeclarationList ( const vector<SgDeclarationStatement*> & l )
18887 {
18888 // This function support debugging the generated declarations.
18889
18890 int counter = 0;
18891 vector<SgDeclarationStatement*>::const_iterator i = l.begin();
18892 while ( i != l.end() )
18893 {
18894 printf ("In outputDeclarationList(): list[%d] = %p = %s = %s \n",counter++,*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
18895 i++;
18896 }
18897 }
18898
18899void CollectDependentDeclarationsTraversal::addDeclaration(SgDeclarationStatement* declaration)
18900{
18901 // If there was a declaration found then handle it.
18902 if (declaration != NULL)
18903 {
18904 // Reset the defining declaration in case there is an outer declaration that is more important
18905 // to consider the dependent declaration (e.g. a class in a namespace). In general this will
18906 // find the associated outer declaration in the global scope.
18907 SgDeclarationStatement* dependentDeclaration = getGlobalScopeDeclaration(declaration);
18908
18909 // This declaration is in global scope so we just copy the declaration
18910 // For namespace declarations: they may have the save name but they have to be saved separated.
18911 if (alreadySavedDeclarations.find(dependentDeclaration) == alreadySavedDeclarations.end())
18912 {
18913#if 0
18914 printf ("In CollectDependentDeclarationsTraversal::visit(): selected dependentDeclaration = %p = %s = %s \n",
18915 dependentDeclaration,dependentDeclaration->class_name().c_str(),SageInterface::get_name(dependentDeclaration).c_str());
18916#endif
18917 // DQ (2/22/2009): Semantics change for this function, just save the original declaration, not a copy of it.
18918 declarationList.push_back(dependentDeclaration);
18919
18920 // Record this as a copied declaration
18921 alreadySavedDeclarations.insert(dependentDeclaration);
18922#if 0
18923 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18924 printf ("############### ADDING dependentDeclaration = %p = %s to alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18925 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18926#endif
18927 // DQ (2/21/2009): Added assertions (will be inforced in SageInterface::appendStatementWithDependentDeclaration()).
18928 // ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
18929 }
18930 else
18931 {
18932#if 0
18933 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18934 printf ("############### EXISTING dependentDeclaration = %p = %s found in alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18935 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18936#endif
18937 }
18938 }
18939}
18940
18942static std::vector<SgTypedefDeclaration*> collectTypedefDeclarations(SgType* type)
18943{
18944 ROSE_ASSERT(type != NULL);
18945 std::vector<SgTypedefDeclaration*> result;
18946 SgType* currentType = type;
18947
18948 SgModifierType* modType = NULL;
18949 SgPointerType* pointType = NULL;
18950 SgReferenceType* refType = NULL;
18951 SgArrayType* arrayType = NULL;
18952 SgTypedefType* typedefType = NULL;
18953
18954 while (true)
18955 {
18956 modType = isSgModifierType(currentType);
18957 if(modType)
18958 {
18959 currentType = modType->get_base_type();
18960 }
18961 else
18962 {
18963 refType = isSgReferenceType(currentType);
18964 if(refType)
18965 {
18966 currentType = refType->get_base_type();
18967 }
18968 else
18969 {
18970 pointType = isSgPointerType(currentType);
18971 if ( pointType)
18972 {
18973 currentType = pointType->get_base_type();
18974 }
18975 else
18976 {
18977 arrayType = isSgArrayType(currentType);
18978 if (arrayType)
18979 {
18980 currentType = arrayType->get_base_type();
18981 }
18982 else
18983 {
18984 typedefType = isSgTypedefType(currentType);
18985 if (typedefType)
18986 {
18987 currentType = typedefType->get_base_type();
18988 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(typedefType->get_declaration());
18989 // have to try to get the defining declaration for a defining typedef declaration
18990 // otherwise AST traversal will not visit the non-defining one for a defining typedef declaration
18991 // sortSgNodeListBasedOnAppearanceOrderInSource() won't work properly
18992 SgTypedefDeclaration* decl = isSgTypedefDeclaration(tdecl->get_definingDeclaration());
18993 if (decl ==NULL)
18994 decl = tdecl;
18995 result.push_back(decl);
18996 }
18997 else
18998 {
18999 // Exit the while(true){} loop!
19000 break;
19001 }
19002 }
19003 }
19004 }
19005 }
19006 }
19007#if 0
19008 // debug here
19009 if (result.size()>0)
19010 {
19011 cout<<"------------Found a chain of typedef decls: count="<<result.size()<<endl;
19012 for (vector <SgTypedefDeclaration*>::const_iterator iter = result.begin();
19013 iter!=result.end(); iter ++)
19014 cout<<(*iter)->unparseToString()<<endl;
19015 }
19016#endif
19017 return result;
19018}
19019
19021void
19023 {
19024 // Statements that can cause us to have declaration dependences:
19025 // 1) variable declarations (through their types)
19026 // 2) function calls
19027 // 3) typedefs (through their base types)
19028 // Not implemented:
19029 // 4) static member functions (through their class)
19030 // 5) static data members (through their class)
19031 // 6) namespaces
19032 // 7) #include<> CPP directives.
19033
19034 // DQ (2/22/2009): Changing the semantics for this function,
19035 // just save the original declaration, not a copy of it.
19036
19037#if 0
19038 // Debugging support.
19039 Sg_File_Info* fileInfo = astNode->get_file_info();
19040 if (fileInfo != NULL && fileInfo->isFrontendSpecific() == false && (isSgStatement(astNode) != NULL) )
19041 {
19042 printf ("\n\nIn CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
19043 // fileInfo->display("In CollectDependentDeclarationsTraversal::visit()");
19044 int counter = 0;
19045 printf ("alreadySavedDeclarations.size() = %" PRIuPTR " \n",alreadySavedDeclarations.size());
19046 for (set<SgDeclarationStatement*>::iterator i = alreadySavedDeclarations.begin(); i != alreadySavedDeclarations.end(); i++)
19047 {
19048 printf ("alreadySavedDeclarations %d: %p = %s \n",counter++,*i,(*i)->class_name().c_str());
19049 }
19050 }
19051#endif
19052
19053 // The following conditionals set this variable
19054 SgDeclarationStatement* declaration = NULL;
19055
19056 // 1) ------------------------------------------------------------------
19057 // Collect the declarations associated with referenced types in variable declarations (or any types associated with SgInitializedName IR nodes)
19058 SgInitializedName* initializedname = isSgInitializedName(astNode);
19059 if (initializedname != NULL)
19060 {
19061 SgType* type = initializedname->get_type();
19062
19063 // handle all dependent typedef declarations, if any
19064 std::vector <SgTypedefDeclaration*> typedefVec = collectTypedefDeclarations(type);
19065 for (std::vector <SgTypedefDeclaration*>::const_iterator iter =typedefVec.begin();
19066 iter != typedefVec.end(); iter++)
19067 {
19068 SgTypedefDeclaration* typedef_decl = *iter;
19069 addDeclaration(typedef_decl);
19070 symbolList.push_back(typedef_decl->get_symbol_from_symbol_table());
19071 }
19072
19073 // handle base type:
19074
19075 // We now can to strip typedefs since they are already handled by collectTypedefDeclarations()
19076 // this also reach to the defining body of a defining typedef declaration
19077 // and treat it as an independent declarations,
19078 // the assumption here is that a defining typedef declaration will only has its
19079 // nondefining declaration copied to avoid redefining of the struct.
19080 // This is also a workaround for an AST copy bug: defining body gets lost after copying
19081 // a defining typedef declaration.
19082 // Liao, 5/8/2009
19083 //
19084 // e.g. typedef struct hypre_BoxArray_struct
19085 // {
19086 // int alloc_size;
19087 // } hypre_BoxArray;
19088 //
19089 // struct hypre_BoxArray_struct will be treated as a strippedType and its declaration
19090 // will be inserted.
19091 //
19092 SgType* strippedType = type->stripType();
19093 SgNamedType* namedType = isSgNamedType(strippedType);
19094 if (namedType != NULL)
19095 {
19096 // Note that since this was obtained via the types and types are shared, this is the non-defining
19097 // declaration in original program (not the separate file is this is to support outlining into a
19098 // separate file.
19099 SgDeclarationStatement* named_decl = namedType->get_declaration();
19100 // the case of class declaration, including struct, union
19101 SgClassDeclaration* classDeclaration = isSgClassDeclaration(named_decl);
19102 if (classDeclaration != NULL)
19103 {
19104 // printf ("Found class declaration: classDeclaration = %p \n",classDeclaration);
19105 declaration = classDeclaration->get_definingDeclaration();
19106 // Liao, 12/09/2016.
19107 // In some cases, forward declaration of class types are used and sufficient, without providing defining declaration.
19108 // We should allow this.
19109 if (declaration != NULL)
19110 {
19111 // ROSE_ASSERT(declaration != NULL);
19112 addDeclaration(declaration);
19113 }
19114 else
19115 addDeclaration (classDeclaration); // we use the original forward declaration.
19116
19117 // Note that since types are shared in the AST, the declaration for a named type may be (is)
19118 // associated with the class declaration in the original file. However, we want to associated
19119 // class declaration in the current file, but since the AST copy mechanism work top-down, this
19120 // mapping form the declaration in the original file to the new declaration in the copied AST
19121 // is available in the SgCopyHelp map of copied IR nodes.
19122 // DQ (3/3/2009): Added support for symbol references to be saved (symbols in the original file).
19123 // these symbols will be mapped to their new symbols.
19124 ROSE_ASSERT(classDeclaration->hasAssociatedSymbol() == true);
19125 SgSymbol* classSymbol = classDeclaration->get_symbol_from_symbol_table();
19126 ROSE_ASSERT(classSymbol != NULL);
19127
19128 // printf ("Saving classSymbol = %p \n",classSymbol);
19129 symbolList.push_back(classSymbol);
19130 }
19131
19132 // handle Enum types
19133 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(named_decl);
19134 if (enum_decl != NULL)
19135 {
19136 declaration = enum_decl->get_definingDeclaration();
19137 ROSE_ASSERT(declaration != NULL);
19138 addDeclaration(declaration);
19139 ROSE_ASSERT(enum_decl->hasAssociatedSymbol() == true);
19140 // Liao 12/14/2012. use search_for_symbol_from_symbol_table() instead to avoid the defining/nondefing decl issue
19141 //SgSymbol* esymbol = enum_decl->get_symbol_from_symbol_table();
19142 SgSymbol* esymbol = enum_decl->search_for_symbol_from_symbol_table();
19143 ROSE_ASSERT(esymbol!= NULL);
19144 symbolList.push_back(esymbol);
19145 }
19146 } // end if namedType
19147#if 0
19148 printf ("Found reference to type = %p = %s strippedType = %p = %s \n",type,type->class_name().c_str(),strippedType,strippedType->class_name().c_str());
19149#endif
19150 }// end if (initializedname)
19151
19152 // 2) ------------------------------------------------------------------
19153 // Collect declarations associated with function calls.
19154 SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
19155 if (functionCallExp != NULL)
19156 {
19157 declaration = functionCallExp->getAssociatedFunctionDeclaration();
19158 //ROSE_ASSERT(declaration != NULL);
19159 // We allow a function pointer to have no specific declaration associated.
19160 if (declaration != NULL)
19161 addDeclaration(declaration);
19162
19163 // DQ (3/2/2009): Added support for symbol references to be saved (this can be a SgFunctionSymbol or a SgMemberFunctionSymbol).
19164 SgSymbol* functionSymbol = functionCallExp->getAssociatedFunctionSymbol();
19165 //ROSE_ASSERT(functionSymbol != NULL);
19166
19167 // printf ("Saving functionSymbol = %p \n",functionSymbol);
19168 if (functionSymbol)
19169 symbolList.push_back(functionSymbol);
19170 }
19171
19172 // 3) ------------------------------------------------------------------
19173 // Collect enumerate declarations associated with SgEnumVal
19174 SgEnumVal * eval = isSgEnumVal(astNode);
19175 if (eval != NULL)
19176 {
19177 declaration = eval->get_declaration();
19178 ROSE_ASSERT(declaration != NULL);
19179 addDeclaration(declaration);
19181 ROSE_ASSERT(symbol != NULL);
19182 symbolList.push_back(symbol);
19183 }
19184// addDeclaration(declaration); // do it in different cases individually
19185 }
19186
19187static std::map<const SgStatement*, bool> visitedDeclMap; // avoid infinite recursion
19188
19189
19191// Used to separate a function to a new source file and add necessary type declarations into the new file.
19192// NOTICE: each call to this function has to have call visitedDeclMap.clear() first!!
19193static void
19194getDependentDeclarations (SgStatement* stmt, vector<SgDeclarationStatement*> & declarationList, vector<SgSymbol*> & symbolList )
19195{
19196 // This function returns a list of the dependent declaration for any input statement.
19197 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19198#if 0
19199 printf ("\n\n********************************************************** \n");
19200 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19201 printf ("********************************************************** \n");
19202#endif
19203 visitedDeclMap[stmt]= true;
19205 t.traverse(stmt,preorder);
19206#if 0
19207 declarationList = t.declarationList;
19208 symbolList = t.symbolList;
19209#else
19210 // Merge to the parent level list
19211 copy(t.declarationList.begin(),t.declarationList.end(), back_inserter(declarationList));
19212 copy(t.symbolList.begin(),t.symbolList.end(), back_inserter(symbolList));
19213 // make their elements unique
19214 sort (declarationList.begin(), declarationList.end());
19215 vector<SgDeclarationStatement*>::iterator new_end = unique(declarationList.begin(), declarationList.end());
19216 declarationList.erase(new_end, declarationList.end());
19217
19218 sort (symbolList.begin(), symbolList.end());
19219 vector<SgSymbol*>::iterator end2 = unique(symbolList.begin(), symbolList.end());
19220 symbolList.erase(end2, symbolList.end());
19221
19222
19223 // Liao, 5/7/2009 recursively call itself to get dependent declarations' dependent declarations
19224 for (vector<SgDeclarationStatement*>::const_iterator iter = t.declarationList.begin();
19225 iter !=t.declarationList.end(); iter++)
19226 {
19227 SgDeclarationStatement* decl = *iter;
19228 SgType* base_type = NULL;
19229 SgStatement* body_stmt= NULL;
19230
19231 // grab base type for a declaration
19232 // For class declaration: grab their
19233 if (isSgClassDeclaration(decl))
19234 {
19235 base_type = isSgClassDeclaration(decl)->get_type();
19236 } else
19237 if (isSgTypedefDeclaration(decl))
19238 {
19239
19240 // we don't want to strip of nested typedef declarations
19241 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);
19242 }
19243
19244 //TODO variable declaration, function declaration: parameter list types,
19245 // multiple base_type then
19246
19247 // is the base type associated with a defining body?
19248 // TODO enum type
19249 if (isSgClassType(base_type))
19250 {
19251 SgClassDeclaration* class_decl = isSgClassDeclaration(isSgClassType(base_type)->get_declaration()->get_definingDeclaration());
19252 if (class_decl!=NULL)
19253 {
19254 body_stmt = class_decl->get_definition();
19255 }
19256 }
19257 // recursively collect dependent declarations for the body stmt
19258 if ((body_stmt!=NULL) &&(!visitedDeclMap[body_stmt]))
19259 { // avoid infinite recursion
19260 getDependentDeclarations(body_stmt, declarationList, symbolList);
19261 }
19262 }
19263#endif
19264} // end void getDependentDeclarations()
19265
19266
19267// Reorder a list of declaration statements based on their appearance order in source files
19268// This is essential to insert their copies into a new file in a right order
19269// Liao, 5/7/2009
19270vector<SgDeclarationStatement*>
19271SageInterface::sortSgNodeListBasedOnAppearanceOrderInSource(const vector<SgDeclarationStatement*>& nodevec)
19272{
19273 vector<SgDeclarationStatement*> sortedNode;
19274
19275 if (nodevec.size()==0 )
19276 return sortedNode;
19277 // no need to sort if there is only 1 element
19278 if (nodevec.size() ==1)
19279 return nodevec;
19280
19282 Rose_STL_Container<SgNode*> queryResult = NodeQuery::querySubTree(project,V_SgDeclarationStatement);
19283 for (Rose_STL_Container<SgNode*>::const_iterator iter = queryResult.begin();
19284 iter!= queryResult.end(); iter++)
19285 {
19286 // cerr<<"Trying to match:"<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19287 SgNode* cur_node = *iter;
19288 SgDeclarationStatement* cur_stmt = isSgDeclarationStatement(cur_node);
19289 ROSE_ASSERT(cur_stmt!=NULL);
19290 // Liao 12/14/2012. It is possible nodevec contains a first non-defining function declaration since the function is called in the outlined function
19291 // This is true even if the AST only has a defining function declaration.
19292 //
19293 // But that first non-defining function declaration is not traversable in AST due to it is hidden.
19294 // The solution here is to for each defining function decl traversed, convert it to the first nondefining one to do the match.
19295 SgFunctionDeclaration * func_decl = isSgFunctionDeclaration (cur_stmt);
19296 if (func_decl)
19297 {
19298 if (func_decl->get_definingDeclaration() == func_decl )
19299 {
19300 cur_stmt = func_decl->get_firstNondefiningDeclaration();
19301 ROSE_ASSERT (cur_stmt != func_decl);
19302 }
19303 }
19304 vector<SgDeclarationStatement*>::const_iterator i = find (nodevec.begin(), nodevec.end(), cur_stmt);
19305 if (i!=nodevec.end())
19306 {
19307 // It is possible we already visited a real prototype func decl before, now we see a prototype converted from a defining declaration.
19308 // We have to make sure only one copy is inserted.
19309 vector<SgDeclarationStatement*>::const_iterator j = find (sortedNode.begin(), sortedNode.end(), *i);
19310 if (j == sortedNode.end())
19311 sortedNode.push_back(*i);
19312 }
19313 }
19314
19315 if (nodevec.size() != sortedNode.size())
19316 {
19317 cerr<<"Fatal error in sortSgNodeListBasedOnAppearanceOrderInSource(): nodevec.size() != sortedNode.size()"<<endl;
19318 cerr<<"nodevec() have "<< nodevec.size()<<" elements. They are:"<<endl;
19319 for (vector<SgDeclarationStatement*>::const_iterator iter = nodevec.begin(); iter != nodevec.end(); iter++)
19320 {
19321 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19322 }
19323 cerr<<"sortedNode() have " << sortedNode.size() <<" elements. They are:"<<endl;
19324 for (vector<SgDeclarationStatement*>::const_iterator iter = sortedNode.begin(); iter != sortedNode.end(); iter++)
19325 {
19326 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19327 }
19328
19329 ROSE_ASSERT(nodevec.size() == sortedNode.size());
19330 }
19331 return sortedNode;
19332}
19333
19335// This function clears a history map transparently and return a sorted list of dependent declarations
19336std::vector<SgDeclarationStatement*>
19338 {
19339 // This function returns a list of the dependent declaration for any input statement.
19340 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19341#if 0
19342 printf ("\n\n********************************************************** \n");
19343 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19344 printf ("********************************************************** \n");
19345
19347 t.traverse(stmt,preorder);
19348
19349 return t.declarationList;
19350#else
19351 // share a single implementation for recursive lookup for dependent declaration
19352 visitedDeclMap.clear();
19353 vector<SgDeclarationStatement*> declarationList;
19354 vector<SgSymbol*> symbolList;
19355 getDependentDeclarations(stmt, declarationList, symbolList);
19356 declarationList = sortSgNodeListBasedOnAppearanceOrderInSource(declarationList);
19357#if 0
19358 printf ("\n\n ********************************************************** \n");
19359 cout<<"Found dependent decl: count="<<declarationList.size()<<endl;
19360 for ( vector<SgDeclarationStatement*>::const_iterator iter = declarationList.begin();
19361 iter != declarationList.end(); iter++)
19362 {
19363 cout<<"\t"<<(*iter)->class_name()<<" at line "<<(*iter)->get_file_info()->get_line()<<endl;
19364 if ((*iter)->variantT()== V_SgFunctionDeclaration)
19365 cout<<"func name is:"<<isSgFunctionDeclaration(*iter)->get_name().getString()<<endl;
19366 //<<(*iter)->unparseToString()<<endl; // unparseToString() won't work on outlined function
19367 }
19368 printf ("\n ********************************************************** \n");
19369#endif
19370
19371 return declarationList;
19372
19373#endif
19374 }
19375
19376
19377bool
19379 {
19380 bool returnValue = false;
19381
19382#if 0
19383 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());
19384#endif
19385
19386 if (functionName.is_null() == false)
19387 {
19388 // DQ (1/20/2019): Add operator~() to this list (see test2019_10.C).
19389 if ( functionName == "operator++" || functionName == "operator--" || functionName == "operator&" ||
19390 functionName == "operator!" || functionName == "operator*" || functionName == "operator+" ||
19391 functionName == "operator-" || functionName == "operator+" || functionName == "operator~")
19392 {
19393 returnValue = true;
19394 }
19395 }
19396
19397 return returnValue;
19398 }
19399
19400
19401// DQ (4/13/2013): We need these to support the unparing of operators defined by operator syntax or member function names.
19403bool
19405 {
19406 // DQ (4/21/2013): Reimplemented this function to support more of the prefix operators.
19407 // Also we now support when they are defined as member functions and non-member functions.
19408
19409 bool returnValue = false;
19410
19411 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(exp);
19412 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19413 // ROSE_ASSERT(memberFunctionRefExp != NULL);
19414
19415 SgName functionName;
19416 size_t numberOfOperands = 0;
19417
19418 if (memberFunctionRefExp != NULL)
19419 {
19420 ROSE_ASSERT(functionRefExp == NULL);
19421 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19422 if (memberFunctionDeclaration != NULL)
19423 {
19424 functionName = memberFunctionDeclaration->get_name();
19425 numberOfOperands = memberFunctionDeclaration->get_args().size();
19426 }
19427 }
19428 else
19429 {
19430 // This could be "friend bool operator!(const X & x);"
19431 if (functionRefExp != NULL)
19432 {
19433 SgFunctionDeclaration* functionDeclaration = functionRefExp->getAssociatedFunctionDeclaration();
19434 if (functionDeclaration != NULL)
19435 {
19436 functionName = functionDeclaration->get_name();
19437 numberOfOperands = functionDeclaration->get_args().size();
19438 }
19439 }
19440 else
19441 {
19442 // Note clear if this should be an error.
19443 printf ("In SageInterface::isPrefixOperator(): unknown case of exp = %p = %s \n",exp,exp->class_name().c_str());
19444 }
19445 }
19446
19447#if 0
19448 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);
19449#endif
19450
19451 if (isPrefixOperatorName(functionName) == true)
19452 {
19453 if (memberFunctionRefExp != NULL)
19454 {
19455 // This case is for member functions.
19456 ROSE_ASSERT(functionRefExp == NULL);
19457 if (numberOfOperands == 0)
19458 {
19459 // This is the C++ signature for the operator++() prefix operator.
19460 returnValue = true;
19461 }
19462 else
19463 {
19464 // This is the C++ signature for the operator++() postfix operator.
19465 returnValue = false;
19466 }
19467 }
19468 else
19469 {
19470 // This case is for non-member functions.
19471 ROSE_ASSERT(functionRefExp != NULL);
19472 ROSE_ASSERT(memberFunctionRefExp == NULL);
19473 if (numberOfOperands == 1)
19474 {
19475 // This is the C++ signature for the operator++() prefix operator.
19476 returnValue = true;
19477 }
19478 else
19479 {
19480 // This is the C++ signature for the operator++() postfix operator.
19481 ROSE_ASSERT(numberOfOperands == 2);
19482 returnValue = false;
19483 }
19484 }
19485 }
19486
19487#if 0
19488 printf ("Leaving SageInterface::isPrefixOperator(): returnValue = %s \n",returnValue ? "true" : "false");
19489#endif
19490
19491 return returnValue;
19492 }
19493
19494
19496bool
19498 {
19499 return ( (isPrefixOperator(exp) == false) && (isIndexOperator(exp) == false) );
19500 }
19501
19502
19504bool
19506 {
19507 bool returnValue = false;
19508 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19509 if (memberFunctionRefExp == NULL)
19510 return false;
19511
19512 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19513 if (memberFunctionDeclaration != NULL)
19514 {
19515 SgName functionName = memberFunctionDeclaration->get_name();
19516 if ( (functionName == "operator[]") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19517 {
19518 returnValue = true;
19519 }
19520 else
19521 {
19522 if ( (functionName == "operator()") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19523 {
19524 returnValue = true;
19525 }
19526 else
19527 {
19528 returnValue = false;
19529 }
19530 }
19531 }
19532
19533 return returnValue;
19534 }
19535
19536
19537// DQ (1/10/2014): Adding more general support for token based unparsing.
19539SageInterface::lastStatementOfScopeWithTokenInfo (SgScopeStatement* scope, std::map<SgNode*,TokenStreamSequenceToNodeMapping*> & tokenStreamSequenceMap)
19540 {
19541 // Return the last statement in the associated scope that has token information.
19542 SgStatement* lastStatement = NULL;
19543
19544 ROSE_ASSERT(scope != NULL);
19545
19546#if 0
19547 printf ("In SageInterface::lastStatementOfScopeWithTokenInfo(): scope = %p = %s \n",scope,scope->class_name().c_str());
19548#endif
19549
19550 SgIfStmt* ifStatement = isSgIfStmt(scope);
19551 if (ifStatement != NULL)
19552 {
19553 lastStatement = ifStatement->get_false_body();
19554 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19555 {
19556 lastStatement = ifStatement->get_true_body();
19557 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19558 {
19559 lastStatement = NULL;
19560 }
19561 }
19562
19563 printf ("Note: SgIfStmt scope in SageInterface::lastStatementOfScopeWithTokenInfo(): returning lastStatement = %p \n",lastStatement);
19564 if (lastStatement != NULL)
19565 {
19566 printf (" --- lastStatement = %p = %s \n",lastStatement,lastStatement->class_name().c_str());
19567 }
19568
19569 return lastStatement;
19570 }
19571
19572 SgStatementPtrList statementList = scope->generateStatementList();
19573 if (statementList.rbegin() != statementList.rend())
19574 {
19575 // Find the last statement with token stream information.
19576 SgStatementPtrList::reverse_iterator i = statementList.rbegin();
19577
19578 while (i != statementList.rend() && (tokenStreamSequenceMap.find(*i) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[*i] == NULL) )
19579 {
19580 i++;
19581 }
19582
19583 if (i == statementList.rend())
19584 {
19585 lastStatement = NULL;
19586 }
19587 else
19588 {
19589 lastStatement = *i;
19590 }
19591 }
19592
19593 return lastStatement;
19594 }
19595
19596
19597void
19599 {
19600 // DQ (8/12/2020): Check the access permissions of all defining and nodefining declarations (debugging support for Cxx_tests/test2020_28.C).
19601
19602 class DeclarationTraversal : public AstSimpleProcessing
19603 {
19604 public:
19605 // DeclarationTraversal() {}
19606
19607 void visit (SgNode* node)
19608 {
19609 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
19610 if (decl != NULL)
19611 {
19612 SgDeclarationStatement* definingDeclaration = isSgDeclarationStatement(decl->get_definingDeclaration());
19613 SgDeclarationStatement* firstNondefiningDeclaration = isSgDeclarationStatement(decl->get_firstNondefiningDeclaration());
19614 SgDeclarationStatement* otherDeclaration = NULL;
19615
19616 // Output access modifier information for each declaration.
19617 printf ("Found declaration = %p = %s name = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
19618 if (decl != definingDeclaration && decl != firstNondefiningDeclaration)
19619 {
19620 otherDeclaration = decl;
19621 }
19622
19623 if (definingDeclaration != NULL)
19624 {
19625 definingDeclaration->get_declarationModifier().get_accessModifier().display("definingDeclaration: accessModifier");
19626 }
19627
19628 if (firstNondefiningDeclaration != NULL)
19629 {
19630 firstNondefiningDeclaration->get_declarationModifier().get_accessModifier().display("firstNondefiningDeclaration: accessModifier");
19631 }
19632
19633 if (otherDeclaration != NULL)
19634 {
19635 otherDeclaration->get_declarationModifier().get_accessModifier().display("otherDeclaration: accessModifier");
19636 }
19637
19638 // Adding space for formatting.
19639 printf ("\n");
19640 }
19641 }
19642 };
19643
19644 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19645 DeclarationTraversal traversal;
19646 traversal.traverse(astNode, preorder);
19647 }
19648
19649
19650void
19652 {
19653 // DQ (8/14/2020): Check the symbol tables for specific scopes (debugging support).
19654
19655 class ScopeTraversal : public AstSimpleProcessing
19656 {
19657 public:
19658 void visit (SgNode* node)
19659 {
19660 SgScopeStatement* scope = isSgScopeStatement(node);
19661 if (scope != NULL)
19662 {
19663 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
19664 if (functionDefinition != NULL)
19665 {
19666 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
19667 ROSE_ASSERT(functionDeclaration != NULL);
19668
19669 string functionName = functionDeclaration->get_name();
19670
19671 printf ("functionName = %s \n",functionName.c_str());
19672
19673 if (functionName == "main")
19674 {
19675
19676 SgBasicBlock* functionBody = functionDefinition->get_body();
19677 ROSE_ASSERT(functionBody != NULL);
19678 SgSymbolTable* symbolTable = functionBody->get_symbol_table();
19679 ROSE_ASSERT(symbolTable != NULL);
19680
19681 // Print out the symbol table.
19682 symbolTable->print();
19683 }
19684 }
19685
19686 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
19687 if (namespaceDefinition != NULL)
19688 {
19689 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
19690 ROSE_ASSERT(namespaceDeclaration != NULL);
19691
19692 string namespaceName = namespaceDeclaration->get_name();
19693
19694 printf ("namespaceName = %s \n",namespaceName.c_str());
19695
19696 if (namespaceName == "B")
19697 {
19698 SgSymbolTable* symbolTable = namespaceDefinition->get_symbol_table();
19699 ROSE_ASSERT(symbolTable != NULL);
19700
19701 // Print out the symbol table.
19702 symbolTable->print();
19703 }
19704 }
19705 }
19706 }
19707 };
19708
19709 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19710 ScopeTraversal traversal;
19711 traversal.traverse(astNode, preorder);
19712 }
19713
19714//Jim Leek TODO (07/25/2023): After Dan merges his branch, please clean up all the #1f 0 stuff
19715void SageInterface::markNodeToBeUnparsed(SgNode* node, int physical_file_id)
19716 {
19717#if 0
19718 Sg_File_Info* fileInfo=node->get_file_info();
19719 if (fileInfo != NULL)
19720 {
19721 fileInfo->setTransformation();
19722 fileInfo->setOutputInCodeGeneration();
19723
19724 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19725 if (locatedNode != NULL)
19726 {
19727 // DQ (7/7/2015): Make the subtree as transformed.
19728 locatedNode->setTransformation();
19729 locatedNode->setOutputInCodeGeneration();
19730
19731 // DQ (7/8/2021): Added assertion.
19732 ROSE_ASSERT(locatedNode->get_file_info() != NULL);
19733#if 0
19734 printf ("In markNodeToBeUnparsed(): physical_file_id = %d \n",physical_file_id);
19735#endif
19736 // DQ (10/26/2020): Set the physical_file_id, required for ueader file unparsing (is it?).
19737 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19738#if 1
19739 printf ("Note: calling node markTransformationsForOutput(): node = %p = %s \n",node,node->class_name().c_str());
19740#endif
19741 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19742 // to call setTransformation() and setOutputInCodeGeneration().
19743 markTransformationsForOutput(node);
19744 }
19745 else
19746 {
19747#if 0
19748 printf ("Note: node is not a SgLocatedNode: node = %p = %s \n",node,node->class_name().c_str());
19749#endif
19750 }
19751 }
19752 else
19753 {
19754#if 0
19755 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19756#endif
19757 }
19758#else
19759 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19760 if (locatedNode != NULL)
19761 {
19762 locatedNode->setTransformation();
19763 locatedNode->setOutputInCodeGeneration();
19764
19765 // DQ (10/26/2020): Set the physical_file_id, required for header file unparsing (is it?).
19766 if (locatedNode->get_file_info() != NULL)
19767 {
19768#if 0
19769 printf ("In SageInterface::markNodeToBeUnparsed(): locatedNode = %p = %s calling set_physical_file_id(%d) \n",locatedNode,locatedNode->class_name().c_str(),physical_file_id);
19770#endif
19771 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19772 }
19773 else
19774 {
19775#if 1
19776 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19777#endif
19778 }
19779
19780 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19781 // to call setTransformation() and setOutputInCodeGeneration().
19782 // Jim Leek (07/25/2023) This doesn't seem to be redundant, it definately marks a bunch of the subtree as transformed
19783 // That otherwise isn't, but Reverse Type Dependence often fails to compile because too much gets unparsed.
19784 // markTransformationsForOutput(node);
19785 }
19786#endif
19787 }
19788
19789
19790
19791void SageInterface::markSubtreeToBeUnparsed(SgNode* root, int physical_file_id)
19792 {
19793 RoseAst ast(root);
19794 for (RoseAst::iterator i=ast.begin();i!=ast.end();++i)
19795 {
19796 markNodeToBeUnparsed(*i,physical_file_id);
19797 }
19798 }
19799
19800
19801
19803 {
19804 // DQ (7/13/2021): This function marks nodes in a subtree to be a transformation, but avoids marking subtrees of the SgCastExp.
19805 // This is important because currently the marking of an implicit cast will cause it to be unparsed, even though it is marked
19806 // as implicit. This detail of precedence of implicit flags over transformation flags needs to be fixed seperated.
19807 // This function has been implemented as part of debugging this issue.
19808
19809 class InheritedAttribute
19810 {
19811 public:
19812 int physical_file_id;
19813 bool isCastSubtree;
19814 InheritedAttribute(int file_id): physical_file_id(file_id), isCastSubtree(false) {}
19815 InheritedAttribute(const InheritedAttribute & X)
19816 {
19817 isCastSubtree = X.isCastSubtree;
19818 physical_file_id = X.physical_file_id;
19819 }
19820 };
19821
19822// DQ (7/21/21): This code construction does not work with the GNU 4.9.x compilers.
19823// #if !( ( (__GNUC__ == 4) && (__GNUC_MINOR__ <= 9) ) || (__GNUC__ < 4))
19824#if (__GNUC__ > 4)
19825
19826 class SubtreeTraversal : public SgTopDownProcessing<InheritedAttribute>
19827 {
19828 public:
19829 InheritedAttribute evaluateInheritedAttribute ( SgNode* node, InheritedAttribute inheritedAttribute)
19830 {
19831 InheritedAttribute returnAttribute(inheritedAttribute);
19832
19833 SgCastExp* castExpression = isSgCastExp(node);
19834 if (castExpression != NULL)
19835 {
19836 returnAttribute.isCastSubtree = true;
19837 }
19838
19839 if (returnAttribute.isCastSubtree == true)
19840 {
19841 // Nothing to do, unless we want to fixup the physical node id.
19842#if 0
19843 printf ("In markSubtreeToBeUnparsedTreeTraversal(): subtree of a SgCastExp: node = %p = %s physical_file_id = %d \n",
19844 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19845#endif
19846 }
19847 else
19848 {
19849#if 0
19850 printf ("In markSubtreeToBeUnparsedTreeTraversal(): Calling markNodeToBeUnparsed(): node = %p = %s physical_file_id = %d \n",
19851 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19852#endif
19853 // This logic will cause the SgCastExp node to NOT be marked as a transformation (not just its children).
19854 markNodeToBeUnparsed(node,inheritedAttribute.physical_file_id);
19855 }
19856
19857 return returnAttribute;
19858 }
19859 };
19860
19861 InheritedAttribute inheritedAttribute(physical_file_id);
19862
19863 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19864 SubtreeTraversal traversal;
19865
19866#if 0
19867 printf ("\nIn markSubtreeToBeUnparsedTreeTraversal(): calling traverse \n");
19868#endif
19869
19870 traversal.traverse(root, inheritedAttribute);
19871#else
19872 printf ("This function does not compile with GNU 4.9 or older compilers (part of ROSE used only with more modern compilers) \n");
19873#endif
19874
19875 }
19876
19877
19878
19879
19881vector<SgDeclarationStatement*>
19882generateCopiesOfDependentDeclarations (const vector<SgDeclarationStatement*>& dependentDeclarations, SgScopeStatement* targetScope)
19883//generateCopiesOfDependentDeclarations ( SgStatement* stmt, SgScopeStatement* targetScope )
19884 {
19885 // Liao suggests adding the target scope to the parameter list so that the constructed function
19886 // built using SageBuilder::buildNondefiningFunctionDeclaration() can be built to be in the
19887 // correct scope as soon as possible.
19888
19889 // This function uses the getDependentDeclarations() function to get the dependent declarations
19890 // and then returns a list of copies of each of them.
19891
19892#if 0
19893 printf ("\n\n********************************************************** \n");
19894 printf (" Inside of generateCopiesOfDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19895 printf ("********************************************************** \n");
19896#endif
19897
19898 vector<SgDeclarationStatement*> copiesOfDependentDeclarations;
19899 // avoiding call getDependentDeclarations() twice
19900// vector<SgDeclarationStatement*> dependentDeclarations = getDependentDeclarations(stmt);
19901
19902#if 0
19903 printf ("Output the dependentDeclarations: dependentDeclarations.size() = %" PRIuPTR " \n",dependentDeclarations.size());
19904 outputDeclarationList(dependentDeclarations);
19905#endif
19906#if 0
19907 printf ("************************************************ \n");
19908 printf ("*** Make all copies of dependentDeclarations *** \n");
19909 printf ("************************************************ \n");
19910#endif
19911
19912 // Should have a valid scope, so that symbol tables can be expected to be setup.
19913 ROSE_ASSERT(targetScope != NULL);
19914
19915 // DQ (2/25/2009): Initially this is always global scope so test this for now, at least.
19916 ROSE_ASSERT(isSgGlobal(targetScope) != NULL);
19917
19918 for (vector<SgDeclarationStatement*>::const_iterator i = dependentDeclarations.begin(); i != dependentDeclarations.end(); i++)
19919 {
19920#if 0
19921 printf ("Copying declaration = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
19922#endif
19923 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19924
19925 SgNode* copy_node = NULL;
19926 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
19927
19928 // For function declarations we don't want to do deep copies on defining declarations
19929 // since that would violate the One-time Definition Rule (ODR).
19930 if (functionDeclaration != NULL)
19931 {
19932 // the target scope may already have a declaration for this function.
19933 // This happens since SageInterface::appendStatementWithDependentDeclaration() is called in the end of outlining
19934 // and the original enclosing class of the outlined target has been changed already (replaced target with a call to OUT_xxx())
19935 // Also, getDependentDeclarations() recursively searches for declarations within the dependent class and hits OUT_xxx()
19936 // Liao, 5/8/2009
19937
19938 if ( SgProject::get_verbose() >= 1 )
19939 printf ("WARNING: In SageInterface -- generateCopiesOfDependentDeclarations(): I think this is the wrong lookup symbol function that is being used here! \n");
19940
19941 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
19942 // TV (2/4/2014): can be found in the project wide global scope...
19943 // So I removed it as we only build a nondef decl and it will only happen for function declared in global scope.`
19944#endif
19945#if 0
19946 printf ("In generateCopiesOfDependentDeclarations(): Copy mechanism appied to SgFunctionDeclaration functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19947
19948 printf ("functionDeclaration = %p \n",functionDeclaration);
19949 printf ("functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
19950 printf ("functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19951 printf ("functionDeclaration->get_scope() = %p \n",functionDeclaration->get_scope());
19952 printf ("targetScope = %p \n",targetScope);
19953#endif
19954 SgFunctionDeclaration* copy_functionDeclaration = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,targetScope);
19955 assert(copy_functionDeclaration != NULL);
19956
19957 copy_functionDeclaration->set_parent(targetScope);
19958
19959 assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != NULL);
19960
19961 // DQ (11/8/2020): This can not be asserted now that the buildSourceFile() has the
19962 // feature of clearing the symbol table used across multiple files.
19963 // assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != copy_functionDeclaration);
19964
19965 assert(copy_functionDeclaration->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table() != NULL);
19966
19967 assert(copy_functionDeclaration->get_scope() != NULL);
19968 assert(copy_functionDeclaration->get_scope() == targetScope);
19969 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19970 copy_functionDeclaration->get_type()) != NULL);
19971 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19972 copy_functionDeclaration->get_type())->get_symbol_basis() == copy_functionDeclaration->get_firstNondefiningDeclaration());
19973
19974 copy_node = copy_functionDeclaration;
19975#if 0
19976 printf ("In generateCopiesOfDependentDeclarations(): DONE: Copy mechanism appied to SgFunctionDeclaration \n");
19977 ROSE_ABORT();
19978#endif
19979 }
19980 else
19981 {
19982 // We only copy the non-defining declaration of a defining typedef declaration
19983 // since its defining body will be treated as a separate declaration and inserted to the new file.
19984 // This is also a workaround for an AST copy bug: losing defining body of a defining typedef declaration after copying.
19985 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(*i);
19986 if (tdecl)
19987 {
19988#if 0
19989 if (tdecl->get_definingDeclaration() == tdecl)
19990 cout<<"Copying a defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19991 else
19992 cout<<"Copying a non-defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19993#endif
19995 SgTypedefDeclaration* tdecl_copy = isSgTypedefDeclaration(copy_node);
19996 tdecl_copy->set_typedefBaseTypeContainsDefiningDeclaration (false); // explicit indicate this does not contain defining base type, Liao 12/14/2012
19997 }
19998 else
19999 copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
20000
20001 // 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).
20002 SgDeclarationStatement* copy_declaration = isSgDeclarationStatement(copy_node);
20003 ROSE_ASSERT(copy_declaration != NULL);
20004
20005 // DQ (3/2/2009): This will be done later, but it is set above, so set it in this branch to be consistant.
20006 if (copy_declaration->hasExplicitScope() == true)
20007 copy_declaration->set_scope(targetScope);
20008 }
20009
20010 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
20011 // Build a function prototype, but what scope should be used?
20012 // ROSE_ASSERT(functionDeclaration->get_scope() != NULL);
20013 // copy = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,functionDeclaration->get_scope());
20014
20015#if 0
20016 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());
20017#endif
20018
20019 ROSE_ASSERT(copy_node != NULL);
20020 ROSE_ASSERT(copy_node->get_file_info() != NULL);
20021
20022 // Note that the root of the does not have its file info set like its children.
20023 copy_node->get_file_info()->setTransformation();
20025 // copy_node->get_file_info()->display("CollectDependentDeclarationsTraversal::visit()");
20026
20027 SgDeclarationStatement* copy_definingDeclaration = isSgDeclarationStatement(copy_node);
20028 ROSE_ASSERT(copy_definingDeclaration != NULL);
20029
20030 ROSE_ASSERT( *i != NULL );
20031 ROSE_ASSERT(copy_definingDeclaration != NULL);
20032
20033 // DQ (2/26/2009): get_scope() will require a valid parent for some cases (see moreTest4.cpp).
20034 if (copy_definingDeclaration->get_parent() == NULL)
20035 {
20036 copy_definingDeclaration->set_parent(targetScope);
20037 }
20038 ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
20039
20040#if 0
20041 printf ("DONE: Copying declaration: original scope = %p copied to scope = %p \n",(*i)->get_scope(),copy_definingDeclaration->get_scope());
20042#endif
20043
20044 // DQ (2/22/2009): I think we need to set these explicitly (it will be reset later).
20045 copy_definingDeclaration->set_parent(NULL);
20046
20047 // Now that we pass in the scope explicitly we can set the scope (above), so don't reset to NULL!
20048 // copy_definingDeclaration->set_scope(NULL);
20049
20050 // DQ (2/20/2009): Added assertion.
20051 ROSE_ASSERT(copy_definingDeclaration->get_parent() == NULL);
20052
20053#if 0
20054 // DQ (2/20/2009): Added assertion.
20055 // ROSE_ASSERT(copy_definingDeclaration->get_definingDeclaration() != NULL);
20056 if (copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL)
20057 {
20058 printf ("copy_definingDeclaration = %p \n",copy_definingDeclaration);
20059 printf ("copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL \n");
20060 printf ("copy_definingDeclaration->get_definingDeclaration() = %p \n",copy_definingDeclaration->get_definingDeclaration());
20061 }
20062#endif
20063
20064 // DQ (2/21/2009): Commented out as a test.
20065 if ((*i)->get_firstNondefiningDeclaration() != NULL)
20066 {
20067 ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
20068 }
20069
20070 // DQ (2/20/2009): Added asertion.
20071 // ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
20072
20073 copiesOfDependentDeclarations.push_back(copy_definingDeclaration);
20074 }
20075
20076#if 0
20077 printf ("****************************************************** \n");
20078 printf ("*** DONE: Make all copies of dependentDeclarations *** \n");
20079 printf ("****************************************************** \n");
20080 printf ("copiesOfDependentDeclarations.size() = %" PRIuPTR " \n",copiesOfDependentDeclarations.size());
20081#endif
20082
20083 // The mapping of copies to original declarations should be 1-to-1.
20084 // Liao, not true anymore for getDependentDeclarations() using recursion: a depending class's body is searched for dependents also.
20085 // 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
20086 ROSE_ASSERT(copiesOfDependentDeclarations.size() <= dependentDeclarations.size());
20087
20088 return copiesOfDependentDeclarations;
20089 }
20090
20091
20092bool
20093declarationContainsDependentDeclarations( SgDeclarationStatement* decl, vector<SgDeclarationStatement*> & dependentDeclarationList )
20094 {
20095 // DQ (2/16/2009): This function finds the declarations in "decl" and checks if they match against those in dependentDeclarationList
20096 bool returnValue = false;
20097
20098#if 0
20099 printf ("\n\n********************************************************** \n");
20100 printf (" Inside of declarationContainsDependentDeclarations(decl = %p = %s) \n",decl,decl->class_name().c_str());
20101 printf ("********************************************************** \n");
20102#endif
20103
20104 vector<SgDeclarationStatement*> locallyDependentDeclarationList = SageInterface::getDependentDeclarations(decl);
20105
20106 // printf ("In declarationContainsDependentDeclarations(): locallyDependentDeclarationList: \n");
20107 // outputPreprocessingInfoList(locallyDependentDeclarationList);
20108
20109 for (size_t i = 0; i < locallyDependentDeclarationList.size(); i++)
20110 {
20111 SgDeclarationStatement* d = locallyDependentDeclarationList[i];
20112#if 0
20113 printf ("locallyDependentDeclarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20114#endif
20115 vector<SgDeclarationStatement*>::iterator j = find(dependentDeclarationList.begin(),dependentDeclarationList.end(),d);
20116 if (j != dependentDeclarationList.end())
20117 {
20118 // These identified declaration must be output as members of the class when it is output in the separate header file.
20119 // infact ODR may require that the whole class be output! Actually I think we don't have any chioce here!
20120#if 0
20121 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());
20122#endif
20123 returnValue = true;
20124 }
20125 }
20126
20127#if 0
20128 printf ("**************************************************************************** \n");
20129 printf (" LEAVING: Inside of declarationContainsDependentDeclarations(decl = %p = %s) returnValue = %s \n",decl,decl->class_name().c_str(),returnValue ? "true" : "false");
20130 printf ("**************************************************************************** \n");
20131#endif
20132
20133 return returnValue;
20134 }
20137{
20138 ROSE_ASSERT (new_exp != NULL);
20139 ROSE_ASSERT (anchor_exp != NULL);
20140 ROSE_ASSERT (new_exp != anchor_exp);
20141
20142 SgNode* parent = anchor_exp->get_parent();
20143 ROSE_ASSERT (parent != NULL);
20144
20145 //TODO use deep copy may be a better way, avoid reusing the original anchor_exp
20146 SgCommaOpExp * result = buildCommaOpExp(new_exp, NULL);
20147 ROSE_ASSERT (result != NULL);
20148 replaceExpression (anchor_exp, result, true);
20149
20150 result->set_rhs_operand(anchor_exp);
20151 anchor_exp->set_parent(result);
20152 return result ;
20153}
20154
20155
20157SgCommaOpExp * SageInterface::insertAfterUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp, SgStatement** temp_decl /* = NULL */, SgVarRefExp** temp_ref /* = NULL */)
20158{
20159 ROSE_ASSERT (new_exp != NULL);
20160 ROSE_ASSERT (anchor_exp != NULL);
20161 ROSE_ASSERT (new_exp != anchor_exp);
20162
20163 SgNode* parent = anchor_exp->get_parent();
20164 ROSE_ASSERT (parent != NULL);
20165
20166 // insert TYPE T1; right before the enclosing statement of anchor_exp
20167 SgType * t = anchor_exp ->get_type();
20168 ROSE_ASSERT (t != NULL);
20169 SgStatement * enclosing_stmt = getEnclosingStatement(anchor_exp);
20170 ROSE_ASSERT (enclosing_stmt != NULL);
20171
20172 gensym_counter ++;
20173 string temp_name = "_t_"+ StringUtility::numberToString(gensym_counter);
20174 SgVariableDeclaration* t_decl = buildVariableDeclaration(temp_name, t, NULL, enclosing_stmt->get_scope());
20175 insertStatementBefore (enclosing_stmt, t_decl);
20176 SgVariableSymbol * temp_sym = getFirstVarSym (t_decl);
20177 ROSE_ASSERT (temp_sym != NULL);
20178 if (temp_decl)
20179 *temp_decl = t_decl;
20180
20181 // build ((T1 = anchor_exp, new_exp),T1) )
20182 SgVarRefExp * first_ref = buildVarRefExp(temp_sym);
20183 if (temp_ref)
20184 * temp_ref = first_ref;
20185 SgCommaOpExp * result = buildCommaOpExp ( buildCommaOpExp (buildAssignOp ( first_ref, deepCopy(anchor_exp)), new_exp) , buildVarRefExp(temp_sym));
20186 replaceExpression (anchor_exp, result, false);
20187
20188 return result;
20189}
20190
20191void
20193 {
20194 // Put out a message in the separate file to lable the dependent CPP directives.
20195 // --- PreprocessingInfo(DirectiveType, const std::string & inputString, const std::string & filenameString, int line_no, int col_no, int nol, RelativePositionType relPos );
20196 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20197 string fileName = "separate-outlined-file";
20198 PreprocessingInfo* messageToUser = new PreprocessingInfo(PreprocessingInfo::C_StyleComment,message,fileName,0,0,1,PreprocessingInfo::before);
20199 // requiredDirectivesList.push_back(messageToUser);
20200 stmt->addToAttachedPreprocessingInfo(messageToUser,PreprocessingInfo::before);
20201
20202 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
20203 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
20204 // when multiple files are used on the command line.
20205 messageToUser->get_file_info()->setTransformation();
20206 }
20207
20208
20209// DQ (2/6/2009): Added function to support outlining into separate file.
20210// 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)
20211void
20213 {
20214 // New function to support outlining of functions into separate files (with their required declarations).
20215
20216#if 0
20217 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl = %p \n",decl);
20218 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_parent() = %p \n",decl->get_parent());
20219 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_scope() = %p \n",decl->get_scope());
20220 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): original_statement = %p \n",original_statement);
20221 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (decl) = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20222 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_firstNondefiningDeclaration() = %p \n",decl->get_firstNondefiningDeclaration());
20223 if (decl->get_firstNondefiningDeclaration() != NULL)
20224 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20225 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_definingDeclaration() = %p \n",decl->get_definingDeclaration());
20226 if (decl->get_definingDeclaration() != NULL)
20227 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_definingDeclaration())->getFileName().c_str());
20228#endif
20229
20230#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20231 // Make sure that the input declaration (decl" is consistent in it's representation across more
20232 // than one file (only a significant test when outlining to a separate file; which is what this
20233 // function supports).
20234 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20235 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20236 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20237
20238 // DQ (2/6/2009): I need to write this function to support the
20239 // insertion of the function into the specified scope. If the
20240 // file associated with the scope is marked as compiler generated
20241 // (or as a transformation) then the declarations referenced in the
20242 // function must be copied as well (those not in include files)
20243 // and the include files must be copies also. If the SgFile
20244 // is not compiler generated (or a transformation) then we just
20245 // append the function to the scope (trivial case).
20246
20247 // This code will be based on the work in:
20248 // developersScratchSpace/Dan/translator_tests/reverseTraversal.C
20249
20250 // To test this run: "rm moreTest2.o ; make moreTest2.o"
20251 // in directory: tests/nonsmoke/functional/roseTests/astOutliningTests
20252
20253 // ***** Also move different loop IR nodes into a common base class *****
20254
20255 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20256
20257 // DQ (3/2/2009): This now calls a newer function which returns a list of declarations and a list of symbols.
20258 // The declarations are sometimes outer declarations of nested references to dependent declaration in inner
20259 // scopes (see moreTest3.cpp). The Symbol list are the symbols in the old AST that will be mapped to newer
20260 // symbols generated in the copied AST.
20261 // Collect the declaration that the input declaration depends upon.
20262 vector<SgDeclarationStatement*> dependentDeclarationList_inOriginalFile;
20263
20264 dependentDeclarationList_inOriginalFile = getDependentDeclarations(decl);
20265
20266 // Generate the copies of all the dependent statements
20267// printf ("Fixme: this currently causes the getDependentDeclarations(decl) function to be called twice \n");
20268// vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(decl,scope);
20269 vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(dependentDeclarationList_inOriginalFile,scope);
20270 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20271
20272 // Make sure that the input declaration (decl" is consistent in it's representation across more
20273 // than one file (only a significant test when outlining to a separate file; which is what this
20274 // function supports).
20275 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20276 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20277 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20278
20279 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
20280 std::map<SgNode*, SgNode*> replacementMap;
20281
20282 // DQ (3/2/2009): Now use the collectDependentDeclarationsCopyType object to generate the mapping
20283 // from the symbols in the old AST to the new symbols in the new AST (generated as part of the AST
20284 // copy mechanism).
20285 SgCopyHelp::copiedNodeMapType copyNodeMap = collectDependentDeclarationsCopyType.get_copiedNodeMap();
20286 SgCopyHelp::copiedNodeMapType::iterator copyNodeMapItrator = copyNodeMap.begin();
20287 while (copyNodeMapItrator != copyNodeMap.end())
20288 {
20289 // Loop over all the nodes generated in the AST copy mechanism (accumulated result over multiple copies).
20290 // const SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20291 // SgNode* first = copyNodeMapItrator->first;
20292 SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20293 SgNode* second = copyNodeMapItrator->second;
20294#if 0
20295 printf ("copyNodeMapItrator.first = %p = %s second = %p = %s \n",first,first->class_name().c_str(),second,second->class_name().c_str());
20296#endif
20297 // Add the SgGlobal referenece to the replacementMap
20298 if (isSgSymbol(first) != NULL)
20299 {
20300#if 0
20301 printf ("Adding to replacementMap (first = %p = %s = %s , second = %p \n",first,first->class_name().c_str(),SageInterface::get_name(first).c_str(),second);
20302#endif
20303 replacementMap.insert(pair<SgNode*,SgNode*>(first,second));
20304 }
20305
20306 copyNodeMapItrator++;
20307 }
20308
20309#if 0
20310 printf ("Exiting after test of new functionality \n");
20311 ROSE_ABORT();
20312#endif
20313
20314 // DQ (2/22/2009): We need all the declarations! (moreTest3.cpp demonstrates this, since it drops
20315 // the "#define SIMPLE 1" which causes it to be treated a "0" (causing errors in the generated code).
20316 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(original_statement);
20317 vector<PreprocessingInfo*> requiredDirectivesList = collectCppDirectives(sourceFile);
20318
20319 SgFunctionDeclaration* outlinedFunctionDeclaration = isSgFunctionDeclaration(decl);
20320 ROSE_ASSERT(outlinedFunctionDeclaration != NULL);
20321 SgGlobal* originalFileGlobalScope = TransformationSupport::getGlobalScope(original_statement);
20322 ROSE_ASSERT(originalFileGlobalScope != NULL);
20323 if ( SgProject::get_verbose() >= 1 )
20324 printf ("WARNING: In SageInterface::appendStatementWithDependentDeclaration(): I think this is the wrong lookup symbol function that is being used here! \n");
20325
20326 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
20327 // SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name()));
20328 SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name(),NULL,NULL));
20329
20330 // SgSymbol* outlinedFunctionSymbolFromOutlinedFile = scope->lookup_symbol(outlinedFunctionDeclaration->get_name());
20331 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20332 SgFunctionSymbol* outlinedFunctionSymbolFromOutlinedFile = isSgFunctionSymbol(decl->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table());
20333#if 0
20334 printf ("outlinedFunctionSymbolFromOriginalFile = %p outlinedFunctionSymbolFromOutlinedFile = %p \n",outlinedFunctionSymbolFromOriginalFile,outlinedFunctionSymbolFromOutlinedFile);
20335
20336 printf ("TransformationSupport::getSourceFile(decl)->getFileName() = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20337 printf ("TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName() = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20338 printf ("TransformationSupport::getSourceFile(original_statement)->getFileName() = %s \n",TransformationSupport::getSourceFile(original_statement)->getFileName().c_str());
20339#endif
20340
20341 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile != NULL);
20342 ROSE_ASSERT(outlinedFunctionSymbolFromOutlinedFile != NULL);
20343
20344 // TV (07/24/2013): Symbol are unified across files through the project wide global scope
20345 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile == outlinedFunctionSymbolFromOutlinedFile);
20346
20347 // Add the SgGlobal referenece to the replacementMap
20348 replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
20349
20350 // Add the non-defining declarations of the outlined function to the replacementMap
20351 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOriginalFile = isSgFunctionDeclaration(outlinedFunctionSymbolFromOriginalFile->get_declaration());
20352 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOutlinedFile = isSgFunctionDeclaration(decl->get_firstNondefiningDeclaration());
20353 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOriginalFile != NULL);
20354 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOutlinedFile != NULL);
20355 replacementMap.insert(pair<SgNode*,SgNode*>(outlinedNondefiningFunctionDeclarationFromOriginalFile,outlinedNondefiningFunctionDeclarationFromOutlinedFile));
20356
20357
20358 // list<SgDeclarationStatement>::iterator i = declarationList.begin();
20359 // while (i != declarationList.end())
20360 // for (list<SgDeclarationStatement>::iterator i = declarationList.begin(); i != declarationList.end(); i++)
20361
20362// cout<<"\n*******************************************\n"<<endl;
20363// cout<<"Inserting dependent decls: count="<<dependentDeclarationList.size()<<endl;
20364 for (size_t i = 0; i < dependentDeclarationList.size(); i++)
20365 {
20366 SgDeclarationStatement* d = dependentDeclarationList[i]; // copies of dependent declarations
20367#if 0
20368 SgDeclarationStatement* originalDeclaration = dependentDeclarationList_inOriginalFile[i];
20369 printf ("declarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20370 printf ("originalDeclaration = %p \n",originalDeclaration);
20371
20372 d->get_file_info()->display("SageInterface::appendStatementWithDependentDeclaration()");
20373#endif
20374
20375 // DQ (2/20/2009): Added assertion.
20376 ROSE_ASSERT(d->get_parent() == NULL);
20377
20378 // scope->append_declaration(d);
20379 // scope->insert_statement (decl, d, /* bool inFront= */ true);
20380 ROSE_ASSERT(decl->get_scope() == scope);
20381 ROSE_ASSERT(find(scope->getDeclarationList().begin(),scope->getDeclarationList().end(),decl) != scope->getDeclarationList().end());
20382 scope->insert_statement (decl, d, /* bool inFront= */ true);
20383 d->set_parent (scope);
20384
20385#if 0
20386 printf ("Add the required symbol information to the symbol table: scope = %p = %s \n",scope,scope->class_name().c_str());
20387#endif
20388
20389 // For whatever type of declaration we add to the global scope in the new separate
20390 // file we have to add the required symbol information to the symbol table.
20391 switch(d->variantT())
20392 {
20393 case V_SgClassDeclaration:
20394 {
20395 if ( declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20396 printf ("Warning: This class contains dependent declarations (not implemented) \n");
20397 break;
20398 }
20399
20400 case V_SgMemberFunctionDeclaration:
20401 printf ("Sorry, support for dependent member function declarations not implemented! \n");
20402 ROSE_ABORT();
20403
20404 case V_SgTemplateInstantiationDecl:
20405 printf ("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration \n");
20406 d->get_file_info()->display("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration");
20407
20408 printf ("Case of SgTemplateInstantiationDecl not implemented. \n");
20409 ROSE_ABORT();
20410
20411 case V_SgNamespaceDeclarationStatement:
20412 if (declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20413 printf ("Warning: This namespace contains dependent declarations (not supported) \n");
20414 break;
20415
20416 case V_SgFunctionDeclaration:
20417 case V_SgTypedefDeclaration:
20418 case V_SgEnumDeclaration:
20419 break;
20420
20421 default:
20422 printf ("default case in SageInterface::appendStatementWithDependentDeclaration() (handling dependentDeclarationList) d = %p = %s \n",d,d->class_name().c_str());
20423 ROSE_ABORT();
20424 }
20425
20426
20427 // Collect include directives that are already attached to this dependent declaration.
20428 vector<PreprocessingInfo*> cppDirectivesAlreadyAttachedToDependentDeclarations = collectCppDirectives(d);
20429
20430#if 0
20431 printf ("directives BEFORE excluding those already present in dependent declarations \n");
20432 outputPreprocessingInfoList(requiredDirectivesList);
20433
20434 printf ("directives already attached to dependent declarations \n");
20435 outputPreprocessingInfoList(cppDirectivesAlreadyAttachedToDependentDeclarations);
20436#endif
20437
20438 // Remove these include directives from the requiredDirectivesList (to prevent redundant output in the generated file)
20439 vector<PreprocessingInfo*>::iterator j = cppDirectivesAlreadyAttachedToDependentDeclarations.begin();
20440 while ( j != cppDirectivesAlreadyAttachedToDependentDeclarations.end() )
20441 {
20442 // Remove this directive from the requiredDirectivesList (to avoid having them output redundently).
20443 vector<PreprocessingInfo*>::iterator entry = find(requiredDirectivesList.begin(),requiredDirectivesList.end(),*j);
20444 ROSE_ASSERT(entry != requiredDirectivesList.end());
20445
20446 requiredDirectivesList.erase(entry);
20447
20448 j++;
20449 }
20450
20451#if 0
20452 printf ("directives AFTER excluding those already present in dependent declarations \n");
20453 outputPreprocessingInfoList(requiredDirectivesList);
20454#endif
20455 }
20456
20457 // Add a message to the top of the outlined function that has been added
20458 addMessageStatement(decl,"/* OUTLINED FUNCTION */");
20459
20460 // Insert the dependent declarations ahead of the input "decl".
20461 SgStatement* firstStatmentInFile = NULL;
20462 if (dependentDeclarationList.empty() == true)
20463 {
20464 firstStatmentInFile = decl;
20465 }
20466 else
20467 {
20468 firstStatmentInFile = dependentDeclarationList[0];
20469 }
20470
20471 ROSE_ASSERT(firstStatmentInFile != NULL);
20472
20473 // Add a message to the top of the dependent declarations that have been added
20474 addMessageStatement(firstStatmentInFile,"/* REQUIRED DEPENDENT DECLARATIONS */");
20475
20476 // DQ (3/6/2009): Added support to permit exclusion of "#include<header.h>" files since they can make it
20477 // much more difficult for external tools. Later we will check if there are remaining unsatisfied dependent
20478 // declarations (which must be in the header file) so we can automate this step.
20479 if (excludeHeaderFiles == false)
20480 {
20481 // Include all the "#include<header.h>" cpp directives obtained from the original file.
20482 vector<PreprocessingInfo*>::reverse_iterator j = requiredDirectivesList.rbegin();
20483 while ( j != requiredDirectivesList.rend() )
20484 {
20485 firstStatmentInFile->addToAttachedPreprocessingInfo(*j,PreprocessingInfo::before);
20486 j++;
20487 }
20488 }
20489
20490 // Add a message to the top of the CPP directives that have been added
20491 addMessageStatement(firstStatmentInFile,"/* REQUIRED CPP DIRECTIVES */");
20492
20493 // ****************************************************************************
20494 // **************** Fixup AST to Reset References To IR nodes ***************
20495 // ****************************************************************************
20496 // This traversal of the replacement map modified the AST to reset pointers to subtrees that will be shared.
20497 // The whole AST is traversed (using the memory pool traversal) and the data member pointers to IR nodes that
20498 // are found in the replacement map are used to lookup the replacement values that are used to reset the
20499 // pointers in the AST. As the replacement is computed the pointer values that are marked in the replacement
20500 // list for update are added to the intermediateDeleteSet.
20501
20502 SgSourceFile* outlinedFile = TransformationSupport::getSourceFile(scope);
20503 ROSE_ASSERT(outlinedFile != NULL);
20504
20505 // This replacement will be done over the entire file (parts of it are redundant with what has already
20506 // been done by the AST copy (so this step need not do as much and may be reduced to just operating
20507 // on the outlined function, I think).
20508#if 0
20509 printf ("\n\n************************************************************\n");
20510 printf ("Calling Utils::edgePointerReplacement() \n");
20511#endif
20512
20513 Rose::AST::Utility::edgePointerReplacement(outlinedFile,replacementMap);
20514
20515#if 0
20516 printf ("Calling Utils::edgePointerReplacement(): DONE \n");
20517 printf ("************************************************************\n\n");
20518
20519 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
20520 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
20521#endif
20522
20523 // Repeated test from above
20524 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20525
20526// endif for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20527#endif
20528
20529#if 0
20530 // The replacementMap should include the symbols associated with the dependentDeclarationList
20531 // and the outlined function (so dependentDeclarationList.size() + 1).
20532 printf ("replacementMap.size() = %" PRIuPTR " dependentDeclarationList.size() = %" PRIuPTR " \n",replacementMap.size(),dependentDeclarationList.size());
20533 // ROSE_ASSERT(replacementMap.size() == dependentDeclarationList.size() + 1);
20534#endif
20535 }
20536
20537void
20539 {
20540//Tan, August/25/2010: //Re-implement DeleteAST function
20541
20542 //Use MemoryPoolTraversal to count the number of references to a certain symbol
20543 //This class defines the visitors for the MemoryPoolTraversal
20544
20545 class ClassicVisitor : public ROSE_VisitorPattern
20546 {
20547 private:
20548 int SgVariableSymbol_count;
20549 int SgFunctionSymbol_count;
20550 int SgClassDeclaration_count;
20551 int SgTypedefSymbol_count;
20552 int SgMemFuncSymbol_count;
20553 int SgTemplateSymbol_count;
20554 int SgEnumFieldSymbol_count;
20555
20556 SgVariableSymbol* SgVariableSymbolPtr;
20557 SgFunctionSymbol* SgFunctionSymbolPtr;
20558 SgClassSymbol * SgClassSymbolPtr;
20559 SgTypedefSymbol * SgTypedefPtr;
20560 SgEnumFieldSymbol * SgEnumFieldSymbolPtr;
20561 SgMemberFunctionSymbol * SgMemFuncSymbolPtr;
20562 SgTemplateSymbol * SgTemplateSymbolPtr;
20563 SgClassDeclaration * class_defining;
20564 SgTemplateDeclaration * template_defining;
20566 SgTypedefDeclaration * typedef_defining;
20567 SgFunctionDeclaration * function_decl;
20568 SgTemplateInstantiationDecl * templateInstantiate_defining;
20569
20570 public:
20571 ClassicVisitor(SgVariableSymbol* symbol){
20572 SgVariableSymbol_count = 0;
20573 SgVariableSymbolPtr = symbol;
20574 SgFunctionSymbolPtr =NULL;
20575 SgClassSymbolPtr =NULL;
20576 SgTypedefPtr = NULL;
20577 SgMemFuncSymbolPtr =NULL;
20578 class_defining = NULL;
20579 memFunc =NULL;
20580 typedef_defining =NULL;
20581 function_decl = NULL;
20582 SgTemplateSymbolPtr = NULL;
20583 template_defining = NULL;
20584 SgEnumFieldSymbolPtr = NULL;
20585 templateInstantiate_defining =NULL;
20586 }
20587
20588 ClassicVisitor(SgFunctionSymbol* symbol){
20589 SgFunctionSymbol_count = 0;
20590 SgFunctionSymbolPtr = symbol;
20591
20592 // DQ (5/2/2013): Added to fix test2013_141.C.
20593 SgMemFuncSymbol_count =0;
20594
20595 SgVariableSymbolPtr = NULL;
20596 SgClassSymbolPtr =NULL;
20597 SgTypedefPtr = NULL;
20598 SgMemFuncSymbolPtr =NULL;
20599 class_defining = NULL;
20600 memFunc =NULL;
20601 typedef_defining =NULL;
20602 function_decl = NULL;
20603 SgTemplateSymbolPtr = NULL;
20604 template_defining = NULL;
20605 SgEnumFieldSymbolPtr = NULL;
20606 templateInstantiate_defining =NULL;
20607 }
20608
20609 ClassicVisitor(SgClassSymbol* symbol){
20610 SgClassDeclaration_count = 0;
20611 SgClassSymbolPtr = symbol;
20612 SgFunctionSymbolPtr = NULL;
20613 SgVariableSymbolPtr = NULL;
20614 SgTypedefPtr = NULL;
20615 SgMemFuncSymbolPtr =NULL;
20616 class_defining = NULL;
20617 memFunc =NULL;
20618 typedef_defining =NULL;
20619 function_decl = NULL;
20620 SgTemplateSymbolPtr = NULL;
20621 template_defining = NULL;
20622 SgEnumFieldSymbolPtr = NULL;
20623 templateInstantiate_defining =NULL;
20624 }
20625
20626 ClassicVisitor(SgTypedefSymbol* symbol){
20627 SgTypedefSymbol_count =0;
20628 SgTypedefPtr = symbol;
20629 SgClassSymbolPtr = NULL;
20630 SgFunctionSymbolPtr = NULL;
20631 SgVariableSymbolPtr = NULL;
20632 SgMemFuncSymbolPtr =NULL;
20633 class_defining = NULL;
20634 memFunc =NULL;
20635 typedef_defining =NULL;
20636 function_decl = NULL;
20637 SgTemplateSymbolPtr = NULL;
20638 template_defining = NULL;
20639 SgEnumFieldSymbolPtr = NULL;
20640 templateInstantiate_defining =NULL;
20641 }
20642
20643 ClassicVisitor(SgMemberFunctionSymbol* symbol){
20644 SgMemFuncSymbolPtr = symbol;
20645 SgMemFuncSymbol_count =0;
20646 SgTypedefPtr = NULL;
20647 SgClassSymbolPtr = NULL;
20648 SgFunctionSymbolPtr = NULL;
20649 SgVariableSymbolPtr = NULL;
20650 class_defining = NULL;
20651 memFunc =NULL;
20652 typedef_defining =NULL;
20653 function_decl = NULL;
20654 SgTemplateSymbolPtr = NULL;
20655 template_defining = NULL;
20656 SgEnumFieldSymbolPtr = NULL;
20657 templateInstantiate_defining =NULL;
20658 }
20659
20660 ClassicVisitor(SgTemplateSymbol* symbol){
20661 SgTemplateSymbolPtr = symbol;
20662 SgTemplateSymbol_count =0;
20663 SgMemFuncSymbolPtr = NULL;
20664 SgTypedefPtr = NULL;
20665 SgClassSymbolPtr = NULL;
20666 SgFunctionSymbolPtr = NULL;
20667 SgVariableSymbolPtr = NULL;
20668 class_defining = NULL;
20669 memFunc =NULL;
20670 typedef_defining =NULL;
20671 function_decl = NULL;
20672 template_defining = NULL;
20673 SgEnumFieldSymbolPtr = NULL;
20674 templateInstantiate_defining =NULL;
20675 }
20676
20677 ClassicVisitor(SgEnumFieldSymbol* symbol){
20678 SgEnumFieldSymbolPtr = symbol;
20679 SgEnumFieldSymbol_count =0;
20680 SgTemplateSymbolPtr = NULL;
20681 SgMemFuncSymbolPtr = NULL;
20682 SgTypedefPtr = NULL;
20683 SgClassSymbolPtr = NULL;
20684 SgFunctionSymbolPtr = NULL;
20685 SgVariableSymbolPtr = NULL;
20686 class_defining = NULL;
20687 memFunc =NULL;
20688 typedef_defining =NULL;
20689 function_decl = NULL;
20690 template_defining = NULL;
20691 templateInstantiate_defining =NULL;
20692 }
20693
20694
20695 ClassicVisitor(SgClassDeclaration* node){
20696 class_defining = node;
20697 SgMemFuncSymbolPtr = NULL;
20698 SgTypedefPtr = NULL;
20699 SgClassSymbolPtr = NULL;
20700 SgFunctionSymbolPtr = NULL;
20701 SgVariableSymbolPtr = NULL;
20702 memFunc =NULL;
20703 typedef_defining =NULL;
20704 function_decl = NULL;
20705 SgTemplateSymbolPtr = NULL;
20706 template_defining = NULL;
20707 SgEnumFieldSymbolPtr = NULL;
20708 templateInstantiate_defining =NULL;
20709 }
20710
20711 ClassicVisitor(SgTemplateDeclaration* node){
20712 template_defining = node;
20713 class_defining = NULL;
20714 SgMemFuncSymbolPtr = NULL;
20715 SgTypedefPtr = NULL;
20716 SgClassSymbolPtr = NULL;
20717 SgFunctionSymbolPtr = NULL;
20718 SgVariableSymbolPtr = NULL;
20719 memFunc =NULL;
20720 typedef_defining =NULL;
20721 function_decl = NULL;
20722 SgTemplateSymbolPtr = NULL;
20723 SgEnumFieldSymbolPtr = NULL;
20724 templateInstantiate_defining =NULL;
20725 }
20726 ClassicVisitor(SgFunctionDeclaration* node){
20727 function_decl =node;
20728 class_defining = NULL;
20729 SgMemFuncSymbolPtr = NULL;
20730 SgTypedefPtr = NULL;
20731 SgClassSymbolPtr = NULL;
20732 SgFunctionSymbolPtr = NULL;
20733 SgVariableSymbolPtr = NULL;
20734 memFunc =NULL;
20735 typedef_defining =NULL;
20736 SgTemplateSymbolPtr = NULL;
20737 template_defining = NULL;
20738 SgEnumFieldSymbolPtr = NULL;
20739 templateInstantiate_defining =NULL;
20740 }
20741
20742 ClassicVisitor(SgMemberFunctionDeclaration* node){
20743 memFunc = node;
20744 function_decl =NULL;
20745 class_defining = NULL;
20746 SgMemFuncSymbolPtr = NULL;
20747 SgTypedefPtr = NULL;
20748 SgClassSymbolPtr = NULL;
20749 SgFunctionSymbolPtr = NULL;
20750 SgVariableSymbolPtr = NULL;
20751 typedef_defining =NULL;
20752 SgTemplateSymbolPtr = NULL;
20753 template_defining = NULL;
20754 SgEnumFieldSymbolPtr = NULL;
20755 templateInstantiate_defining =NULL;
20756 }
20757
20758 ClassicVisitor(SgTypedefDeclaration* node){
20759 typedef_defining = node;
20760 memFunc = NULL;
20761 function_decl =NULL;
20762 class_defining = NULL;
20763 SgMemFuncSymbolPtr = NULL;
20764 SgTypedefPtr = NULL;
20765 SgClassSymbolPtr = NULL;
20766 SgFunctionSymbolPtr = NULL;
20767 SgVariableSymbolPtr = NULL;
20768 SgTemplateSymbolPtr = NULL;
20769 template_defining = NULL;
20770 SgEnumFieldSymbolPtr = NULL;
20771 templateInstantiate_defining =NULL;
20772 }
20773
20774 ClassicVisitor(SgTemplateInstantiationDecl* node){
20775 templateInstantiate_defining =node;
20776 typedef_defining = NULL;
20777 memFunc = NULL;
20778 function_decl =NULL;
20779 class_defining = NULL;
20780 SgMemFuncSymbolPtr = NULL;
20781 SgTypedefPtr = NULL;
20782 SgClassSymbolPtr = NULL;
20783 SgFunctionSymbolPtr = NULL;
20784 SgVariableSymbolPtr = NULL;
20785 SgTemplateSymbolPtr = NULL;
20786 template_defining = NULL;
20787 SgEnumFieldSymbolPtr = NULL;
20788 }
20789
20790
20791 // SgVariableSymbol and SgEnumFieldSymbol
20792 void visit(SgInitializedName* node)
20793 {
20794 if(SgVariableSymbolPtr !=NULL)
20795 {
20796 if(node->get_scope()!=NULL)
20797 {
20798 // DQ (5/21/2013): We want to restrict access to the symbol table.
20799 if(node->get_scope()->get_symbol_table()!=NULL)
20800 {
20802 if (isSgVariableSymbol(s) == SgVariableSymbolPtr) SgVariableSymbol_count++;
20803 }
20804 }
20805 }
20806
20807 if(SgEnumFieldSymbolPtr !=NULL)
20808 {
20809 if(node->get_scope()!=NULL)
20810 {
20811 // DQ (5/21/2013): We want to restrict access to the symbol table.
20812 if(node->get_scope()->get_symbol_table()!=NULL)
20813 {
20815 if (isSgEnumFieldSymbol(s) == SgEnumFieldSymbolPtr) SgEnumFieldSymbol_count++;
20816 }
20817 }
20818 }
20819 }
20820
20821 void visit(SgVarRefExp* node)
20822 {
20823 if(SgVariableSymbolPtr !=NULL){
20824 SgVariableSymbol* s = node->get_symbol();
20825 if (s == SgVariableSymbolPtr) SgVariableSymbol_count++;
20826 }
20827 }
20828
20829 int get_num_variable_pointers(){return SgVariableSymbol_count;}
20830
20831 int get_num_EnumField_pointers(){return SgEnumFieldSymbol_count;}
20832
20833
20834 // SgFunctionSymbol
20835 void visit(SgFunctionDeclaration* node) {
20836 if(SgFunctionSymbolPtr !=NULL){
20837 if(node->get_scope()!=NULL){
20838 // DQ (5/21/2013): We want to restrict access to the symbol table.
20839 if(node->get_scope()->get_symbol_table()!=NULL)
20840 {
20842 if ((SgFunctionSymbol *)s == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20843 }
20844 }
20845 }
20846#if 0
20847 if(function_decl!=NULL){
20848 if(node->get_symbol_from_symbol_table() == NULL){
20851 if(node!=function_decl && (define==function_decl || first_nondefine==function_decl)) delete node;
20852 }
20853 }
20854#endif
20855 }
20856
20857 void visit(SgFunctionRefExp* node)
20858 {
20859#if 0
20860 printf ("In visit(SgFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20861#endif
20862 if (SgFunctionSymbolPtr !=NULL)
20863 {
20864 SgFunctionSymbol* s = node->get_symbol_i();
20865 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20866 {
20867 SgFunctionSymbol_count++;
20868#if 0
20869 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20870#endif
20871 }
20872 }
20873 }
20874
20875 // DQ (5/2/2013): Added support for SgMemberFunctionRefExp which is not derived from SgFunctionRefExp.
20876 void visit(SgMemberFunctionRefExp* node)
20877 {
20878#if 0
20879 printf ("In visit(SgMemberFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20880#endif
20881 if (SgFunctionSymbolPtr !=NULL)
20882 {
20883 SgFunctionSymbol* s = node->get_symbol_i();
20884 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20885 {
20886 SgFunctionSymbol_count++;
20887#if 0
20888 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20889#endif
20890 }
20891 }
20892 }
20893
20894 void visit(SgUserDefinedBinaryOp* node)
20895 {
20896 if (SgFunctionSymbolPtr !=NULL){
20897 SgFunctionSymbol* s = node->get_symbol();
20898 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20899 }
20900 }
20901
20902 int get_num_Function_pointers(){return SgFunctionSymbol_count;}
20903
20904 // SgClassSymbol
20905 void visit(SgClassDeclaration* node)
20906 {
20907 if(SgClassSymbolPtr !=NULL){
20908 if(node->get_scope()!=NULL){
20909 if(node->get_scope()->get_symbol_table()!=NULL)
20910 {
20912 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20913 }
20914 }
20915 }
20916
20917 if(class_defining!=NULL) {
20918 if(node->get_symbol_from_symbol_table() == NULL){
20921 if((class_decl==class_defining||class_decl1==class_defining) && node!=class_defining )
20922 delete node;
20923 }
20924 }
20925 }
20926
20927 void visit(SgTemplateInstantiationDecl* node)
20928 {
20929 if(SgClassSymbolPtr !=NULL){
20930 if(node->get_scope()!=NULL){
20931 if(node->get_scope()->get_symbol_table()!=NULL)
20932 {
20934 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20935 }
20936 }
20937 }
20938
20939 if(templateInstantiate_defining!=NULL) {
20940 if(node->get_scope()!=NULL){
20941 if(node->get_scope()->get_symbol_table()!=NULL)
20942 {
20943 if(node->get_symbol_from_symbol_table() == NULL){
20946 if((template_decl==templateInstantiate_defining||template_decl1==templateInstantiate_defining) && node!=templateInstantiate_defining){
20947 /*vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
20948 foreach (SgTemplateArgument* element, tempargs){
20949 SgTemplateArgument* temparg = isSgTemplateArgument(element);
20950 if(temparg){
20951 delete temparg;
20952 }
20953 printf("SgTemplateArg in Memory Pool traversal\n");
20954 }*/
20955 delete node;
20956 //printf("SgTemplateInstantiationDecl in Memory Pool traversal\n");
20957 }
20958 }
20959 }
20960 }
20961 }
20962 }
20963
20964 void visit(SgThisExp* node)
20965 {
20966 if (SgClassSymbolPtr !=NULL){
20967 SgSymbol* s = node->get_class_symbol();
20968 if (s == SgClassSymbolPtr) SgClassDeclaration_count++;
20969 }
20970 }
20971
20972 void visit(SgClassNameRefExp* node)
20973 {
20974 if (SgClassSymbolPtr !=NULL){
20975 SgSymbol* s = node->get_symbol();
20976 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20977 }
20978 }
20979
20980
20981 int get_num_Class_pointers(){return SgClassDeclaration_count;}
20982
20983
20984 // SgMemberFunctionSymbol
20985 void visit(SgCtorInitializerList* node)
20986 {
20987 if(memFunc !=NULL){
20989 if(func == memFunc){
20990 delete node;
20991 }
20992 }
20993 }
20994
20995
20996 void visit(SgMemberFunctionDeclaration* node)
20997 {
20998 if (SgMemFuncSymbolPtr !=NULL){
20999 if(node->get_scope()!=NULL){
21000 if(node->get_scope()->get_symbol_table()!=NULL)
21001 {
21002 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21003 if(symbol == SgMemFuncSymbolPtr){
21004 SgMemFuncSymbol_count++;
21005 }
21006 }
21007 }
21008 }
21009 }
21010
21012 {
21013 if (SgMemFuncSymbolPtr !=NULL){
21014 if(node->get_scope()!=NULL){
21015 if(node->get_scope()->get_symbol_table()!=NULL)
21016 {
21017 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
21018 if(symbol == SgMemFuncSymbolPtr){
21019 SgMemFuncSymbol_count++;
21020 }
21021 }
21022 }
21023 }
21024 }
21025
21026
21027
21028 int get_num_memFunc_pointers(){return SgMemFuncSymbol_count;}
21029
21030
21031 // SgTypedefSymbol
21032 void visit(SgTypedefDeclaration* node)
21033 {
21034 if(SgTypedefPtr!=NULL){
21035 if(node->get_scope()!=NULL){
21036 if(node->get_scope()->get_symbol_table()!=NULL)
21037 {
21039 if ((SgTypedefSymbol *)s == SgTypedefPtr) SgTypedefSymbol_count++;
21040 }
21041 }
21042 }
21043 if(typedef_defining!=NULL){
21045 if(typedef_define == typedef_defining && node != typedef_defining ) {
21046 delete node;
21047 }
21048 }
21049 }
21050
21051 int get_num_Typedef_pointers(){return SgTypedefSymbol_count;}
21052
21053
21054
21055 void visit(SgTemplateDeclaration* node)
21056 {
21057 if (SgTemplateSymbolPtr !=NULL){
21058 if(node->get_scope()!=NULL){
21059 if(node->get_scope()->get_symbol_table()!=NULL)
21060 {
21061 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
21062 if(symbol == SgTemplateSymbolPtr){
21063 SgTemplateSymbol_count++;
21064 }
21065 }
21066 }
21067 }
21068
21069 if(template_defining !=NULL) {
21070 if(node->get_scope()!=NULL){
21071 if(node->get_scope()->get_symbol_table()!=NULL)
21072 {
21073 if(node->get_symbol_from_symbol_table() == NULL){
21076 if((template_decl==template_defining||template_decl1==template_defining) && node!=template_defining) {
21077 delete node;
21078
21079 }
21080 }
21081 }
21082 }
21083 }
21084 }
21085
21086 int get_num_Template_pointers(){return SgTemplateSymbol_count;}
21087
21088 };
21089
21090
21091 //Tan August,25,2010 //Traverse AST in post order, delete nodes and their symbols if it's safe to do so
21092 class DeleteAST : public SgSimpleProcessing, ROSE_VisitTraversal
21093 {
21094 public:
21095
21096 void visit (SgNode* node)
21097 {
21098 //These nodes are manually deleted because they cannot be visited by the traversal
21100 //remove SgVariableDefinition, SgVariableSymbol and SgEnumFieldSymbol
21102#if 0
21103 printf ("In DeleteAST::visit(): node = %p = %s \n",node,node->class_name().c_str());
21104#endif
21105#if 0
21106 // DQ (3/2/2014): I think this might be a problem...
21107 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
21108 if (isSgScopeStatement(node) !=NULL)
21109 {
21110 SgScopeStatement* scope = isSgScopeStatement(node);
21111#if 1
21112 printf ("Deleting the scopes type table: scope->get_type_table() = %p \n",scope->get_type_table());
21113#endif
21114 delete scope->get_type_table();
21115 }
21116#endif
21117#if 0
21118 // DQ (3/2/2014): I think this might be a problem...
21119 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
21120 if (isSgTypeTable(node) !=NULL)
21121 {
21122 SgTypeTable* typeTable = isSgTypeTable(node);
21123#if 1
21124 printf ("Deleting the type table (SgSymbolTable): typeTable->get_type_table() = %p \n",typeTable->get_type_table());
21125#endif
21126 delete typeTable->get_type_table();
21127 }
21128#endif
21129 if(isSgInitializedName(node) !=NULL){
21130 //remove SgVariableDefinition
21131 SgDeclarationStatement* var_def;
21132 var_def = ((SgInitializedName *)node)->get_definition();
21133 if(isSgVariableDefinition(var_def) !=NULL){
21134 delete var_def;
21135 //printf("A SgVariableDefinition was deleted\n");
21136 }
21137
21138
21139 //remove SgVariableSymbol
21140 if(isSgInitializedName(node)->get_scope()!=NULL){
21141 if(isSgInitializedName(node)->get_scope()->get_symbol_table()!=NULL)
21142 {
21143 SgSymbol* symbol = ((SgInitializedName *)node)->get_symbol_from_symbol_table();
21144 if(isSgVariableSymbol(symbol) !=NULL){
21145 ClassicVisitor visitor((SgVariableSymbol*)symbol);
21146 traverseMemoryPoolVisitorPattern(visitor);
21147 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
21148 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
21149 delete symbol;
21150 //printf("A SgVariableSymbol was deleted\n");
21151 }
21152 }
21153
21154 if(isSgEnumFieldSymbol(symbol) !=NULL){
21155 ClassicVisitor visitor((SgEnumFieldSymbol*)symbol);
21156 traverseMemoryPoolVisitorPattern(visitor);
21157 if(visitor.get_num_EnumField_pointers()==1){
21158 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
21159 delete symbol;
21160 //printf("A SgEnumFieldSymbol was deleted\n");
21161 }
21162 }
21163
21164 }
21165 }
21166 }
21167
21168 if(isSgVarRefExp(node) !=NULL){
21169 SgVariableSymbol *symbol = ((SgVarRefExp*)node)->get_symbol();
21170 ClassicVisitor visitor(symbol);
21171 traverseMemoryPoolVisitorPattern(visitor);
21172 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
21173 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21174 delete symbol;
21175 //printf("A SgVariableSymbol was deleted\n");
21176 }
21177 }
21178
21179 /*////////////////////////////////////////////////
21180 /remove SgFunctionSymbol
21182
21183 {
21184 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(node);
21185 if (funcDecl != NULL){
21186 if (isSgMemberFunctionDeclaration(node) == NULL) {
21187 if (funcDecl->get_scope() != NULL) {
21188 if (funcDecl->get_scope()->get_symbol_table() != NULL) {
21189 SgSymbol* symbol = ((SgFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21190 ClassicVisitor visitor((SgFunctionSymbol *)symbol);
21191 traverseMemoryPoolVisitorPattern(visitor);
21192 if (visitor.get_num_Function_pointers()==1) { //only one reference to this FunctionSymbol => safe to delete
21193 ((SgFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21194 delete symbol;
21195 //printf("A SgFunctionSymbol was deleted\n");
21196 }
21197 ClassicVisitor visitor1((SgFunctionDeclaration *)node);
21198 traverseMemoryPoolVisitorPattern(visitor1);
21199 }
21200 }
21201 }
21202 }
21203 }
21204
21205 if(isSgFunctionRefExp(node) !=NULL)
21206 {
21207#if 0
21208 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(node);
21209 ROSE_ASSERT(functionRefExp->get_symbol_i() != NULL);
21210 printf ("In DeleteAST::visit(): functionRefExp->get_symbol_i() = %p = %s \n",functionRefExp->get_symbol_i(),functionRefExp->get_symbol_i()->class_name().c_str());
21211#endif
21212 SgFunctionSymbol *symbol = ((SgFunctionRefExp*)node)->get_symbol_i();
21213 ClassicVisitor visitor(symbol);
21214 traverseMemoryPoolVisitorPattern(visitor);
21215 if(visitor.get_num_Function_pointers()==1)
21216 {
21217 // only one reference to this FunctionSymbol => safe to delete
21218 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21219 delete symbol;
21220 //printf("A SgFunctionSymbol was deleted\n");
21221 }
21222
21223 }
21224
21225 if(isSgUserDefinedBinaryOp(node) !=NULL){
21226 SgFunctionSymbol *symbol = ((SgUserDefinedBinaryOp*)node)->get_symbol();
21227 ClassicVisitor visitor(symbol);
21228 traverseMemoryPoolVisitorPattern(visitor);
21229 if(visitor.get_num_Function_pointers()==1){ //only one reference to this FunctionSymbol => safe to delete
21230 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21231 delete symbol;
21232 //printf("A SgFunctionSymbol was deleted\n");
21233 }
21234 }
21235
21236 /*/
21237 /remove SgTypedefSymbol
21239
21240 if(isSgTypedefDeclaration(node) !=NULL){
21241 if(((SgTypedefDeclaration*)node)->get_scope()!=NULL){
21242 if(((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21243 {
21244 SgSymbol* symbol = ((SgTypedefDeclaration*)node)->get_symbol_from_symbol_table();
21245 if(isSgTypedefSymbol(symbol)){
21246 ClassicVisitor visitor((SgTypedefSymbol*) symbol);
21247 traverseMemoryPoolVisitorPattern(visitor);
21248 if(visitor.get_num_Typedef_pointers()==1){ //only one reference to this SgTypedefSymbol => safe to delete
21249 ((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21250 delete symbol;
21251 //printf("A SgTypedefSymbol was deleted\n");
21252 }
21253 }
21254 }
21255 }
21256
21257 if(node == isSgTypedefDeclaration(node)->get_definingDeclaration()){
21258 ClassicVisitor visitor1((SgTypedefDeclaration*) node);
21259 traverseMemoryPoolVisitorPattern(visitor1);
21260 }
21261 }
21262
21263 /*////////////////////////////////////////////////
21264 /remove SgNamespaceDeclarationSymbol
21266
21267 if(isSgNamespaceDeclarationStatement(node) !=NULL){
21268 if(((SgNamespaceDeclarationStatement*)node)->get_scope()!=NULL){
21269 if(((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21270 {
21271 SgSymbol* symbol = ((SgNamespaceDeclarationStatement*)node)->get_symbol_from_symbol_table();
21272 if(isSgNamespaceSymbol(symbol)){
21273 ((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21274 delete symbol;
21275 //printf("A SgNamespaceSymbol was deleted\n");
21276 }
21277 }
21278 }
21279 }
21280
21281
21282 if(isSgNamespaceAliasDeclarationStatement(node) !=NULL){
21283 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()!=NULL){
21284 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21285 {
21286 SgSymbol* symbol = ((SgNamespaceAliasDeclarationStatement*)node)->get_symbol_from_symbol_table();
21287 if(isSgNamespaceSymbol(symbol)){
21288 ((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21289 delete symbol;
21290 //printf("A SgNamespaceSymbol was deleted\n");
21291 }
21292 }
21293 }
21294 }
21295
21296
21297 /*/
21298 /remove SgLabelSymbol
21300
21301 if(isSgLabelStatement(node) !=NULL){
21302 if(((SgLabelStatement*)node)->get_scope()!=NULL){
21303 if(((SgLabelStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21304 {
21305 SgSymbol* symbol = ((SgLabelStatement*)node)->get_symbol_from_symbol_table();
21306 if(isSgLabelSymbol(symbol)){
21307 ((SgLabelStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21308 delete symbol;
21309 //printf("A SgLabelSymbol was deleted\n");
21310 }
21311 }
21312 }
21313 }
21314
21315 if(isSgLabelRefExp(node) !=NULL){
21316 SgLabelSymbol* symbol = ((SgLabelRefExp*)node)->get_symbol();
21317 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21318 delete symbol;
21319 //printf("A SgLabelSymbol was deleted\n");
21320 }
21321
21322
21323 /*////////////////////////////////////////////////
21324 /remove SgEnumSymbol
21326
21327 if(isSgEnumDeclaration(node) !=NULL){
21328 if(((SgEnumDeclaration*)node)->get_scope()!=NULL){
21329 if(((SgEnumDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21330 {
21331 SgSymbol* symbol = ((SgEnumDeclaration*)node)->get_symbol_from_symbol_table();
21332 if(isSgEnumSymbol(symbol) !=NULL){
21333 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21334 delete symbol;
21335 //printf("A SgEnumSymbol was deleted\n");
21336 }
21337 }
21338 }
21339 SgEnumType* type= ((SgEnumDeclaration*)node)->get_type();
21340 if(type !=NULL){
21341 delete type;
21342 //printf("A SgEnumType was deleted\n");
21343 }
21344 }
21345
21346
21347 /*/
21348 /remove SgClassSymbol
21350
21351 if(isSgClassDeclaration(node) !=NULL && isSgTemplateInstantiationDecl(node) ==NULL){
21352 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21353 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21354 {
21355 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21356 if(isSgClassSymbol(symbol) !=NULL){
21357 ClassicVisitor visitor((SgClassSymbol*)symbol);
21358 traverseMemoryPoolVisitorPattern(visitor);
21359 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21360 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21361 delete symbol;
21362 //printf("A SgClassSymbol was deleted\n");
21363 }
21364 }
21365 }
21366 }
21367
21368 ClassicVisitor visitor((SgClassDeclaration*) node );
21369 traverseMemoryPoolVisitorPattern(visitor);
21370
21371 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21372 if(type !=NULL){
21373 delete type;
21374 //printf("A SgClassType was deleted\n");
21375 }
21376 }
21377
21378 if(isSgThisExp(node) !=NULL){
21379 SgSymbol* symbol = ((SgThisExp*)node)->get_class_symbol();
21380 ClassicVisitor visitor((SgClassSymbol*)symbol);
21381 traverseMemoryPoolVisitorPattern(visitor);
21382 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21383 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21384 delete symbol;
21385 //printf("A SgClassSymbol was deleted\n");
21386 }
21387
21388 }
21389
21390 if(isSgClassNameRefExp(node) !=NULL){
21391 SgSymbol* symbol = ((SgClassNameRefExp*)node)->get_symbol();
21392 if(isSgClassSymbol(symbol) !=NULL)
21393 {
21394 ClassicVisitor visitor((SgClassSymbol*)symbol);
21395 traverseMemoryPoolVisitorPattern(visitor);
21396 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21397 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21398 delete symbol;
21399 //printf("A SgClassSymbol was deleted\n");
21400 }
21401 }
21402 }
21403
21404 /*////////////////////////////////////////////////
21405 /remove SgMemberFunctionSymbol
21407
21408
21409 if(isSgMemberFunctionDeclaration(node) !=NULL){
21410 if(((SgMemberFunctionDeclaration*)node)->get_scope()!=NULL){
21411 if(((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21412 {
21413 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21414 if(isSgMemberFunctionSymbol(symbol)){
21415 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21416 traverseMemoryPoolVisitorPattern(visitor);
21417 if(visitor.get_num_memFunc_pointers()==1){
21418 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21419 delete symbol;
21420 //printf("A SgMemberFunctionSymbol was deleted\n");
21421 }
21422 }
21423 }
21424 }
21425 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21426 traverseMemoryPoolVisitorPattern(visitor);
21427
21428 }
21429//Tan: I have no idea why the codes below cannot work. Perhaps it conflicts with some prior works
21430#if 0
21431 if(isSgMemberFunctionRefExp(node) !=NULL){
21432 SgMemberFunctionSymbol* symbol = ((SgMemberFunctionRefExp*)node)->get_symbol_i();
21433 ClassicVisitor visitor(symbol);
21434 traverseMemoryPoolVisitorPattern(visitor);
21435 if(visitor.get_num_memFunc_pointers()==1){ //only one reference to this symbol => safe to delete
21436 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21437 delete symbol;
21438 //printf("A SgClassSymbol was deleted\n");
21439 }
21440
21441 }
21442
21443 if(isSgFunctionType(node) !=NULL){
21444 SgSymbol* symbol = ((SgFunctionType*)node)->get_symbol_from_symbol_table();
21445 if(isSgFunctionTypeSymbol(symbol)){
21446 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21447 delete symbol;
21448 //printf("A SgFunctionTypeSymbol was deleted\n");
21449 }
21450 }
21451#endif
21452
21453 /*/
21456
21457 if(isSgInterfaceStatement(node) !=NULL){
21458 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21459 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21460 {
21461 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21462 if(isSgInterfaceSymbol(symbol)){
21463 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21464 delete symbol;
21465 //printf("A SgInterfaceSymbol was deleted\n");
21466 }
21467 }
21468 }
21469
21470 }
21471
21472
21473 if(isSgModuleStatement(node) !=NULL){
21474 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21475 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21476 {
21477 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21478 if(isSgModuleSymbol(symbol)){
21479 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21480 delete symbol;
21481 //printf("A SgModuleSymbol was deleted\n");
21482 }
21483 }
21484 }
21485
21486 }
21487
21488
21489//Tan: I got stuck in deleting the SgTemplateArgument
21490#if 0
21491 if(isSgTemplateInstantiationMemberFunctionDecl(node) !=NULL){
21492 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()!=NULL){
21493 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21494 {
21495 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
21496 if(isSgMemberFunctionSymbol(symbol)){
21497 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21498 traverseMemoryPoolVisitorPattern(visitor);
21499 if(visitor.get_num_memFunc_pointers()==1){
21500 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21501 delete symbol;
21502 //printf("A SgMemberFunctionSymbol was deleted\n");
21503 }
21504 }
21505 }
21506 }
21507 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21508 traverseMemoryPoolVisitorPattern(visitor);
21509 }
21510
21511 if(isSgTemplateDeclaration(node) !=NULL){
21512 if(((SgTemplateDeclaration*)node)->get_scope()!=NULL){
21513 if(((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21514 {
21515 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
21516 ClassicVisitor visitor((SgTemplateSymbol*)symbol);
21517 traverseMemoryPoolVisitorPattern(visitor);
21518 if(visitor.get_num_Template_pointers()==1){
21519 ((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21520 delete symbol;
21521 printf("A SgTemplateSymbol was deleted\n");
21522 }
21523 }
21524 }
21525 //if(isSgTemplateDeclaration(node) == ((SgTemplateDeclaration*)node)->get_firstNondefiningDeclaration()){
21526 ClassicVisitor visitor1((SgTemplateDeclaration*) node );
21527 traverseMemoryPoolVisitorPattern(visitor1);
21528 //}
21529
21530 }
21531
21532 if(isSgInterfaceStatement(node) !=NULL){
21533 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21534 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21535 {
21536 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21537 if(isSgInterfaceSymbol(symbol)){
21538 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21539 delete symbol;
21540 //printf("A SgInterfaceSymbol was deleted\n");
21541 }
21542 }
21543 }
21544
21545 }
21546
21547
21548 if(isSgModuleStatement(node) !=NULL){
21549 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21550 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21551 {
21552 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21553 if(isSgModuleSymbol(symbol)){
21554 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21555 delete symbol;
21556 //printf("A SgModuleSymbol was deleted\n");
21557 }
21558 }
21559 }
21560
21561 }
21562
21563 if(isSgTemplateInstantiationDecl(node) !=NULL){
21564 if(((SgTemplateInstantiationDecl*)node)->get_scope()!=NULL){
21565 if(((SgTemplateInstantiationDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21566 {
21567 SgSymbol* symbol = ((SgTemplateInstantiationDecl*)node)->get_symbol_from_symbol_table();
21568 if(isSgClassSymbol(symbol)){
21569 ClassicVisitor visitor((SgClassSymbol*)symbol);
21570 traverseMemoryPoolVisitorPattern(visitor);
21571 if(visitor.get_num_Class_pointers()==1){
21572 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21573 delete symbol;
21574 }
21575 }
21576 }
21577 }
21578 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21579 if(type !=NULL){
21580 delete type;
21581 //printf("A SgClassType was deleted\n");
21582 }
21583
21584 vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
21585 foreach (SgTemplateArgument* element, tempargs){
21586 SgTemplateArgument* temparg = isSgTemplateArgument(element);
21587 if(temparg){
21588 delete temparg;
21589 }
21590 printf("SgTemplateArg in normal traversal\n");
21591 }
21592 printf("SgTemplateInstantiationDecl in normal traversal\n");
21593
21594 ClassicVisitor visitor((SgTemplateInstantiationDecl*) node);
21595 traverseMemoryPoolVisitorPattern(visitor);
21596 }
21597
21598#endif
21599#if 0
21600 printf ("Deleting node = %p = %s = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
21601#endif
21602 // Normal nodes will be removed in a post-order way
21603 delete node;
21604#if 0
21605 printf ("After delete node: node = %p = %s \n",node,node->class_name().c_str());
21606#endif
21607 }
21608 };
21609
21610
21611 DeleteAST deleteTree;
21612
21613 // Deletion must happen in post-order to avoid traversal of (visiting) deleted IR nodes
21614 deleteTree.traverse(n,postorder);
21615
21616#if 0
21617 printf ("Leaving SageInterface::deleteAST(): n = %p = %s \n",n,n->class_name().c_str());
21618#endif
21619 }
21620
21621
21622
21623
21624#ifndef USE_ROSE
21625// DQ (9/25/2011): The deleteAST() function will not remove original expression trees behind constant folded expressions.
21626// These exist in the AST within the internal construction of the AST until they are simplified in the AST post-processing.
21627// In the post-processing either:
21628// 1) the constant folded values are kept and the original expression trees deleted (optional, controled by default parameter to function "frontend()", OR
21629// 2) the constant folded values are replaced by the original expression trees, and the constant folded values are deleted (default).
21630// Either way, after the AST post-processing the AST is simplified. Until then the expression trees can contain constant
21631// folded values and the values will have a pointer to the original expression tree. Before (9/16/2011) the original
21632// tree would also sometimes (not uniformally) be traversed as part of the AST. This was confusing (to people and
21633// to numerous forms of analysis), so this is being fixed to be uniform (using either of the methods defined above).
21634// However, the fact that until post-processing the AST has this complexity, and that the AST traversal does not
21635// traverse the original expression trees (now uniform); means that we need a special delete function for subtrees
21636// that are not use post-processed. This is the special purpose function that we need.
21637//
21638// NOTE: This function is called from the SgArrayType::createType() member function and in the constant folding AST post-processing.
21639//
21641 {
21642 struct Visitor: public AstSimpleProcessing
21643 {
21644 virtual void visit(SgNode* n)
21645 {
21646 SgExpression* expression = isSgExpression(n);
21647 if (expression != NULL)
21648 {
21649 Visitor().traverse(expression->get_originalExpressionTree(), postorder);
21650 }
21651
21652 delete (n);
21653 }
21654 };
21655
21656 Visitor().traverse(root, postorder);
21657 }
21658#endif
21659 // move symbol table from one scope to another
21660static void moveSymbolTableBetweenBlocks(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, std::vector <SgInitializedName*>& initname_vec)
21661{
21662 // Move the symbol table
21663 SgSymbolTable* s_table = sourceBlock->get_symbol_table();
21664 ASSERT_not_null(sourceBlock->get_symbol_table());
21665 // Liao, 11/26/2019 make sure the symbol table has symbols for init names before and after the move
21666 for (SgInitializedName* iname : initname_vec)
21667 {
21668 SgSymbol* symbol = s_table->find(iname);
21669 ASSERT_not_null(symbol);
21670 }
21671 // entirely move source block's symbol table to target block
21672 targetBlock->set_symbol_table(sourceBlock->get_symbol_table());
21673
21674 ASSERT_not_null(sourceBlock);
21675 ASSERT_not_null(targetBlock);
21676 ASSERT_not_null(targetBlock->get_symbol_table());
21677 ASSERT_not_null(sourceBlock->get_symbol_table());
21678 targetBlock->get_symbol_table()->set_parent(targetBlock);
21679
21680 ASSERT_not_null(sourceBlock->get_symbol_table());
21681 sourceBlock->set_symbol_table(nullptr);
21682
21683 // Reset with a valid symbol table
21684 sourceBlock->set_symbol_table(new SgSymbolTable());
21685 sourceBlock->get_symbol_table()->set_parent(sourceBlock);
21686
21687 ASSERT_require(targetBlock->get_symbol_table() == s_table);
21688 for (SgInitializedName* iname : initname_vec)
21689 {
21690 SgSymbol* symbol = s_table->find(iname);
21691 ASSERT_not_null(symbol);
21692 }
21693
21694 // Liao, 11/26/2019 make sure init names have symbols after the move.
21695 for (SgInitializedName* iname : initname_vec)
21696 {
21697 SgSymbol* symbol = iname->get_symbol_from_symbol_table();
21698 ASSERT_not_null(symbol);
21699 }
21700}
21701
21702// helper function to move a single statement or declaration from a block to another
21703static void moveOneStatement(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, SgStatement* stmt, std::vector <SgInitializedName*>& initname_vec)
21704{
21705 // append statement to the target block
21706 targetBlock->append_statement(stmt);
21707
21708 // Make sure that the parents are set.
21709 ASSERT_require(stmt->get_parent() == targetBlock);
21710 if (stmt->hasExplicitScope())
21711 {
21712 if (stmt->get_scope() != targetBlock)
21713 {
21714 if (SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt))
21715 {
21716 // why only move if it is a first nondefining declaration?
21717 // We have a case to move both defining and nondefining function declarations of Ada package body to namespace definition.
21718 // comment out the if condition for now. 1/20/2021
21719 //
21720 // A call to a undeclared function will introduce a hidden func prototype declaration in the enclosing scope .
21721 // The func declaration should be moved along with the call site.
21722 // The scope should be set to the new block also
21723 // Liao 1/14/2011
21724 func->set_scope(targetBlock);
21725 // This is needed to move functions in Ada package body into C++ namespace
21726 // We may have compiler generated first nondefining declaration. We need to move its scope also
21727 SgFunctionDeclaration* nondef_decl= isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
21728 if (func != nondef_decl)
21729 {
21730 ASSERT_not_null(nondef_decl);
21731 ASSERT_not_null(nondef_decl->get_file_info());
21732 if (nondef_decl->get_file_info()->isCompilerGenerated()) {
21733 nondef_decl->set_scope(targetBlock);
21734 }
21735 }
21736 }
21737 else if (auto labelStmt = isSgLabelStatement(stmt))
21738 {
21739 if (labelStmt->get_scope() == sourceBlock) {
21740 labelStmt->set_scope(targetBlock);
21741 // Make sure the labelStmt is in the enclosing function scope of targetBlock
21742 SageInterface::fixLabelStatement(labelStmt, targetBlock);
21743 }
21744 }
21745 else if (isSgJovialTableStatement(stmt) || isSgTypedefDeclaration(stmt) || isSgEnumDeclaration(stmt))
21746 {
21747 // Rasmussen 9/21/2020,10/27/2020,11/4/2020: Uncovered by issues RC-135 and RC-227.
21748 // The issues are fixed in the switch statement below but this test is needed
21749 // so that the warning message immediately below is not triggered.
21750 }
21751 else
21752 {
21753 mlog[Rose::Diagnostics::WARN] << "test failing stmt->get_scope() == targetBlock in SageInterface::moveStatementsBetweenBlocks(): class: "
21754 << stmt->class_name() << "\n";
21755 }
21756 }
21757 }
21758
21759 SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
21760 if (declaration != nullptr)
21761 {
21762 // Need to reset the scope from sourceBlock to targetBlock.
21763 switch(declaration->variantT())
21764 {
21765 // There will be other cases to handle, but likely not all declaration will be possible to support.
21766
21767 case V_SgVariableDeclaration:
21768 {
21769 // Reset the scopes on any SgInitializedName objects.
21770 SgVariableDeclaration* varDecl = isSgVariableDeclaration(declaration);
21771 SgInitializedNamePtrList & l = varDecl->get_variables();
21772 for (SgInitializedNamePtrList::iterator ii = l.begin(); ii != l.end(); ii++)
21773 {
21774 // reset the scope, but make sure it was set to sourceBlock to make sure.
21775 // This might be an issue for extern variable declaration that have a scope
21776 // in a separate namespace of a static class member defined external to
21777 // its class, etc. I don't want to worry about those cases right now.
21778
21779 SgInitializedName * init_name = (*ii);
21780
21781 // Rasmussen (3/16/2021): Use the base type in case type is modified (i.e., const)
21782 SgType* var_type = init_name->get_type();
21783 if (SgModifierType* mod_type = isSgModifierType(var_type))
21784 {
21785 var_type = mod_type->get_base_type();
21786 }
21787
21788 // Rasmussen (6/29/2020) and (10/19/2020): Variable declarations related to anonymous types are not
21789 // moved. This is fixed below. Note that SgJovialTableType derives from SgClassType, it may
21790 // be that class types are not moved correctly either.
21791 //
21792 if (isSgEnumType(var_type))
21793 {
21794 SgEnumType* enum_type = isSgEnumType(var_type);
21795 SgEnumDeclaration* decl = isSgEnumDeclaration(enum_type->get_declaration());
21796 SgEnumDeclaration* def_decl = isSgEnumDeclaration(decl->get_definingDeclaration());
21797 SgEnumDeclaration* nondef_decl = isSgEnumDeclaration(decl->get_firstNondefiningDeclaration());
21798
21799 if (decl->get_scope() == sourceBlock)
21800 {
21801 // Needs to be moved
21802 def_decl->set_scope(targetBlock);
21803 nondef_decl->set_scope(targetBlock);
21804 nondef_decl->set_parent(targetBlock);
21805
21806 // Move the scope of the enumerators to the new block as well
21807 for (SgInitializedName* enumerator : def_decl->get_enumerators())
21808 {
21809 enumerator->set_scope(targetBlock);
21810 }
21811 }
21812 }
21813 else if (isSgJovialTableType(var_type))
21814 {
21815 SgJovialTableType* table_type = isSgJovialTableType(var_type);
21816 SgDeclarationStatement* decl = table_type->get_declaration();
21817 if (decl->get_scope() == sourceBlock)
21818 {
21819 // Needs to be moved
21822 def_decl->set_scope(targetBlock);
21823 nondef_decl->set_scope(targetBlock);
21824 nondef_decl->set_parent(targetBlock);
21825 }
21826 }
21827
21828 // Must also move the symbol into the source block, Liao 2019/8/14
21829 SgVariableSymbol* var_sym = isSgVariableSymbol(init_name -> search_for_symbol_from_symbol_table ()) ;
21830 ASSERT_not_null(var_sym);
21831 SgScopeStatement * old_scope = var_sym -> get_scope();
21832#if 1 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21833 if (old_scope != sourceBlock)
21834 {
21835 old_scope->remove_symbol (var_sym);
21836 sourceBlock ->insert_symbol(init_name->get_name(), var_sym);
21837 }
21838#endif
21839 init_name->set_scope(targetBlock);
21840 initname_vec.push_back(init_name);
21841 }
21842 break;
21843 }
21844 case V_SgFunctionDeclaration: // Liao 1/15/2009, I don't think there is any extra things to do here
21845 {
21846 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(declaration);
21847 ASSERT_not_null(funcDecl);
21848#if 0 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21849 // move function symbols also: search_for_symbol_from_symbol_table()
21851 if (func_sym)
21852 {
21853 SgScopeStatement * old_scope = func_sym -> get_scope();
21854 if (old_scope != sourceBlock)
21855 {
21856 old_scope->remove_symbol (func_sym);
21857 sourceBlock ->insert_symbol(func_sym->get_name(), func_sym);
21858 }
21859 }
21860#endif
21861 break;
21862 }
21863 // needed to move Ada record into definition of C++ namespace
21864 case V_SgProgramHeaderStatement:
21865 case V_SgProcedureHeaderStatement:
21866 case V_SgClassDeclaration:
21867 case V_SgEnumDeclaration:
21868 {
21869 SgDeclarationStatement* nondef_decl = declaration->get_firstNondefiningDeclaration();
21870 ASSERT_not_null(nondef_decl);
21871
21872 nondef_decl->set_parent(targetBlock);
21873 nondef_decl->set_scope(targetBlock);
21874
21875 SgDeclarationStatement* def_decl = declaration->get_definingDeclaration();
21876 if (def_decl)
21877 {
21878 def_decl->set_parent(targetBlock);
21879 def_decl->set_scope(targetBlock);
21880 }
21881 else
21882 {
21883 // Set the scope of the function arguments
21884 if (auto proc = isSgProcedureHeaderStatement(nondef_decl)) {
21885 for (auto arg : proc->get_parameterList()->get_args()) {
21886 if (arg->get_scope() != proc->get_scope()) {
21887 // Note: arg (is an SgInitializedName) from the parameter list does not have
21888 // a symbol in the scope of the procedure declaration (proc). Should add
21889 // arg to initname_vec, which will check for missing symbols [GL-387, Rasmussen 7/22/2024].
21890 arg->set_scope(proc->get_scope());
21891 }
21892 }
21893 }
21894 }
21895
21896 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(stmt);
21897 if (enum_decl)
21898 {
21899 // Set the scope of the enumerators [Rasmussen 12/23/2020]
21900 for (SgInitializedName* name : enum_decl->get_enumerators())
21901 {
21902 name->set_scope(targetBlock);
21903 }
21904 }
21905 break;
21906 }
21907 case V_SgJovialTableStatement:
21908 {
21909 // [RC-135, Rasmussen 9/21/2020]
21910 SgJovialTableStatement* table = isSgJovialTableStatement(declaration);
21911 ROSE_ASSERT (table);
21912
21915 nondef_decl->set_parent(targetBlock);
21916 nondef_decl->set_scope(targetBlock);
21917 def_decl->set_scope(targetBlock);
21918 break;
21919 }
21920 case V_SgTypedefDeclaration:
21921 {
21922 // [RC-227, Rasmussen 10/19/2020]
21923 SgTypedefDeclaration* typedef_decl = isSgTypedefDeclaration(declaration);
21924 ASSERT_not_null(typedef_decl);
21925 typedef_decl->set_parent(targetBlock);
21926 typedef_decl->set_scope(targetBlock);
21927 break;
21928 }
21929 case V_SgAttributeSpecificationStatement:
21930 case V_SgEmptyDeclaration:
21931 case V_SgFortranIncludeLine:
21932 case V_SgImplicitStatement: // Rasmussen 5/13/2021: TODO: implicit statement with letter-list
21933 case V_SgJovialDefineDeclaration:
21934 case V_SgJovialDirectiveStatement:
21935 case V_SgJovialLabelDeclaration:
21936 case V_SgJovialOverlayDeclaration:
21937 case V_SgPragmaDeclaration:
21938 case V_SgAdaAttributeClause:
21939 break;
21940 default:
21941 {
21942 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());
21943 declaration->get_file_info()->display("file info");
21944 ROSE_ABORT();
21945 }
21946 }
21947 } // end if
21948}
21949
21950// different handling for scopes with declarations only
21951template <class T1, class T2>
21952void moveDeclarationsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21953{
21954 // This function moves statements from one block to another (used by the outliner).
21955 // printf ("***** Moving statements from sourceBlock %p to targetBlock %p ***** \n",sourceBlock,targetBlock);
21956 ROSE_ASSERT (sourceBlock && targetBlock);
21957 ROSE_ASSERT (sourceBlock->containsOnlyDeclarations() && targetBlock->containsOnlyDeclarations());
21958 if ((void*)sourceBlock == (void*)targetBlock)
21959 {
21960 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21961 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21962 return;
21963 }
21964
21965 SgDeclarationStatementPtrList& srcStmts = sourceBlock->get_declarations ();
21966 std::vector <SgInitializedName*> initname_vec;
21967
21968 for (auto stmt : srcStmts)
21969 {
21970 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21971 }
21972
21973 // Remove the statements in the sourceBlock
21974 srcStmts.clear();
21975 ROSE_ASSERT(srcStmts.empty() == true);
21976 ROSE_ASSERT(sourceBlock->get_declarations().empty() == true);
21977
21978 // move symbol table from one scope to another
21979 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21980
21981 // Liao 2/4/2009
21982 // Finally , move preprocessing information attached inside the source block to the target block
21983 // Outliner uses this function to move a code block to the outlined function.
21984 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21985 // to the target block to match #if (which is attached
21986 // before some statement moved to the target block)
21987 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21988}
21989
21990
21991// source and destination class, both are derived classes of scope statement but with support of get_statements()
21992template <class T1, class T2>
21993void moveStatementsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21994{
21995 // This function moves statements from one block to another (used by the outliner).
21996 ROSE_ASSERT (sourceBlock && targetBlock);
21997 if ((void*)sourceBlock == (void*)targetBlock)
21998 {
21999 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
22000 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
22001 return;
22002 }
22003
22004 SgStatementPtrList & srcStmts = sourceBlock->get_statements();
22005 std::vector <SgInitializedName*> initname_vec;
22006
22007 for (SgStatement* stmt : srcStmts)
22008 {
22009 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
22010 }
22011
22012 // Remove the statements in the sourceBlock
22013 srcStmts.clear();
22014 ROSE_ASSERT(srcStmts.empty() == true);
22015 ROSE_ASSERT(sourceBlock->get_statements().empty() == true);
22016
22017 // move symbol table from one scope to another
22018 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
22019
22020 // Liao 2/4/2009
22021 // Finally , move preprocessing information attached inside the source block to the target block
22022 // Outliner uses this function to move a code block to the outlined function.
22023 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
22024 // to the target block to match #if (which is attached
22025 // before some statement moved to the target block)
22026 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
22027
22028}
22029
22030static void createAliasSymbols (SgNamespaceDeclarationStatement* decl)
22031{
22032 ASSERT_not_null(decl);
22034 SgNamespaceDefinitionStatement* global_def = local_def->get_global_definition();
22035
22036 ASSERT_require(local_def && global_def && (local_def!=global_def));
22037
22038 for (auto symbol : local_def->get_symbol_table()->get_symbols())
22039 {
22040 SgSymbol *orig_sym = isSgSymbol(symbol);
22041 ASSERT_not_null(orig_sym);
22042 SgAliasSymbol* asym = new SgAliasSymbol (orig_sym);
22043 global_def->get_symbol_table()->insert (asym->get_name(), asym);
22044 }
22045}
22046
22047//TODO: now with more types, we need to use template functions
22049{
22050 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
22051 //create alias symbols in its global definition
22052 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
22053}
22054
22056{
22057 moveStatementsBetweenScopes(sourceBlock, targetBlock);
22058 //create alias symbols in its global definition
22059 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
22060}
22061
22063{
22064 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
22065}
22066
22067void
22069{
22070 moveStatementsBetweenScopes (sourceBlock, targetBlock);
22071}
22072
22074// TODO, expose to SageInterface namespace
22076{
22077 bool rt = false;
22078 ROSE_ASSERT (func != NULL);
22079 SgNode* p = func->get_parent();
22080 ROSE_ASSERT (p != NULL);
22081 SgLambdaExp* le = isSgLambdaExp (p);
22082 if (le && le->get_lambda_function() == func)
22083 rt = true;
22084 return rt;
22085}
22086
22087// check if a variable reference is this->a[i] inside of a lambda function
22088// SgArrowExp <SgThisExp, SgVarRefExp>, both are compiler generated nodes
22089// class symbol of ThisExp 's declaration is AutonomousDeclaration SgClassDeclaration
22090// its parent is SgLambdaExp, and lambda_closure_class points back to this class declaration
22092{
22093 bool rt = false;
22094#ifdef _MSC_VER
22095 #pragma message ("WARNING: MSVC does not handle isLambdaCapturedVariable() properly.")
22096#else
22097 ROSE_ASSERT (varRef!= NULL);
22098 SgNode* parent = varRef->get_parent();
22099 if (SgArrowExp *p = isSgArrowExp(parent))
22100 {
22101 SgThisExp* te = isSgThisExp(p->get_lhs_operand_i());
22102 if (te != NULL)
22103 {
22104 SgClassSymbol* csym = te->get_class_symbol();
22105 ROSE_ASSERT (csym!= NULL);
22106 SgClassDeclaration* xdecl = isSgClassDeclaration(csym->get_declaration());
22107 // each this exp should have a class decl
22108 ROSE_ASSERT (xdecl != NULL);
22109 SgLambdaExp* le = isSgLambdaExp(xdecl->get_parent());
22110 if (le != NULL)
22111 {
22112 if (le->get_lambda_closure_class() == xdecl ) // the class is a lambda closure class
22113 rt = true;
22114 }
22115 }
22116 }
22117#endif
22118 return rt;
22119}
22120
22123//TODO consult AstInterface::IsVarRef() for more cases
22125{
22126 SgInitializedName* name = NULL;
22127 SgExpression* nameExp = NULL;
22128 ROSE_ASSERT(current != NULL);
22129
22130 if (isSgInitializedName(current))
22131 {
22132 name = isSgInitializedName(current);
22133 }
22134 else if (isSgPntrArrRefExp(current) != NULL)
22135 {
22136 bool suc=false;
22137 SgExpression* exp = isSgExpression(current);
22138 ROSE_ASSERT(exp != NULL);
22139 suc = SageInterface::isArrayReference(exp,&nameExp);
22140 ROSE_ASSERT(suc == true);
22141 // has to resolve this recursively
22142 return convertRefToInitializedName(nameExp, coarseGrain);
22143 }
22144 else if (isSgVarRefExp(current) != NULL)
22145 {
22146 if (coarseGrain)
22147 {
22148 // Outliner needs coarse grain mem objects to work. Always returning fine grain objects will cause problems.
22149 SgNode* parent = current->get_parent();
22150 if (isSgDotExp(parent))
22151 {
22152 if (isSgDotExp(parent)->get_rhs_operand() == current)
22153 return convertRefToInitializedName(parent, coarseGrain);
22154 }
22155 // avoid backtracking to parent if this is part of lambda function
22156 else if(isSgArrowExp(parent) && ! isLambdaCapturedVariable ( isSgVarRefExp(current) ) )
22157 {
22158 if (isSgArrowExp(parent)->get_rhs_operand() == current)
22159 return convertRefToInitializedName(parent, coarseGrain);
22160 }
22161 }
22162 name = isSgVarRefExp(current)->get_symbol()->get_declaration();
22163 }
22164 else if (isSgFunctionRefExp(current) != NULL ||
22165 isSgTemplateFunctionRefExp(current) != NULL ||
22166 isSgMemberFunctionRefExp(current) != NULL ||
22167 isSgTemplateMemberFunctionRefExp(current) != NULL)
22168 {
22169 //If a function is here it's probably related to a function pointer, it can't be converted to an SgInitailizedName
22170 return NULL;
22171 }
22172 else if (isSgNonrealRefExp(current) != NULL)
22173 {
22174 //SgNonrealRefExp is not a reasonable thing to convert to an SgInitializedName (I think) -Jim Leek
22175 return NULL;
22176 }
22177 else if (isSgDotExp(current))
22178 {
22179 SgExpression* child = NULL;
22180 if (coarseGrain)
22181 child= isSgDotExp(current)->get_lhs_operand();
22182 else
22183 child= isSgDotExp(current)->get_rhs_operand();
22184 ROSE_ASSERT(child);
22185 // has to resolve this recursively
22186 return convertRefToInitializedName(child, coarseGrain);
22187 }
22188 else if (isSgArrowExp(current))
22189 {
22190 SgExpression* child = NULL;
22191 if (coarseGrain)
22192 {
22193 SgExpression* lhs = isSgArrowExp(current)->get_lhs_operand();
22194 ROSE_ASSERT(lhs);
22195 // Liao 9/12/2016, special handling for variables inside of C++11 lambda functions
22196 // They capture variables outside of the lambda function.
22197 // They are represented as a class variable of an anonymous class, this->a[i]
22198 // So, we have to recognize this pattern, and pass the rhs variable to obtain initialized name.
22199 // has to resolve this recursively
22201
22202 if (isLambdaFunction (efunc) )
22203 child= isSgArrowExp(current)->get_rhs_operand();
22204 else
22205 child = lhs;
22206 }
22207 else
22208 child = isSgArrowExp(current)->get_rhs_operand();
22209 ROSE_ASSERT(child);
22210 // has to resolve this recursively
22211
22212 return convertRefToInitializedName(child, coarseGrain);
22213 } // The following expression types are usually introduced by left hand operands of DotExp, ArrowExp
22214 else if (isSgThisExp(current))
22215 {
22216 //SgThisExp* texp = isSgThisExp(current);
22217 name = NULL; // inside a class, there is no initialized name at all!! what to do??
22218 }
22219 else if (isSgPointerDerefExp(current))
22220 {
22221 return convertRefToInitializedName(isSgPointerDerefExp(current)->get_operand(), coarseGrain);
22222 }
22223 else if(isSgUnaryOp(current)) { //Written for SgAddressOfOp, but seems generally aplicable to all Unary Ops (replace above?) -JL
22224 return convertRefToInitializedName(isSgUnaryOp(current)->get_operand(), coarseGrain);
22225 }
22226 else if (isSgCastExp(current))
22227 {
22228 return convertRefToInitializedName(isSgCastExp(current)->get_operand(), coarseGrain);
22229 }
22230 // Scientific applications often use *(address + offset) to access array elements
22231 // If a pointer dereferencing is applied to AddOp, we assume the left operand is the variable of our interests
22232 else if (isSgAddOp(current))
22233 {
22234 SgExpression* lhs = isSgAddOp(current)->get_lhs_operand();
22235 return convertRefToInitializedName(lhs, coarseGrain);
22236 }
22237 else if (isSgSubtractOp(current))
22238 {
22239 SgExpression* lhs = isSgSubtractOp(current)->get_lhs_operand();
22240 return convertRefToInitializedName(lhs, coarseGrain);
22241 }
22242 // operator->() may be called upon a class object.
22243 // e.g. we need to get the function: it a SgDotExp node, (lhs is the class object, rhs is its member function)
22244 else if (SgFunctionCallExp * func_call = isSgFunctionCallExp(current))
22245 {
22246 return convertRefToInitializedName(func_call->get_function(), coarseGrain);
22247 }
22248 else if (isSgIntVal(current))
22249 {
22250 //It is very rare, but sometimes a constant is treated as a
22251 //variable. In which case we don't need an SgInitializdName
22252 return NULL;
22253 }
22254
22255 else
22256 {
22257 // side effect analysis will return rhs of Class A a = A(); as a read ref exp. SgConstructorInitializer
22258 if (!isSgConstructorInitializer(current))
22259 {
22260 mlog[Sawyer::Message::Common::WARN] <<
22261 "convertRefToInitializedName: " <<
22262 current->get_file_info()->get_filename() << ":" <<
22263 current->get_file_info()->get_line() << "-" << current->get_file_info()->get_col()<<endl;
22264 cerr<<"In SageInterface::convertRefToInitializedName(): unhandled reference type:"<<current->class_name()<<endl;
22265 ROSE_ABORT();
22266 }
22267 }
22268 //ROSE_ASSERT(name != NULL);
22269 return name;
22270}
22271
22274{
22275#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22276 printf ("AbstractHandle support is disabled for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT \n");
22277 ROSE_ABORT();
22278#else
22280
22281 // trim off the possible leading handle for project: "Project<numbering,1>::"
22282 size_t pos = input_string.find("SourceFile<");
22283 ROSE_ASSERT (pos != string::npos);
22284 string trimed_string = input_string.substr(pos);
22285 AbstractHandle::abstract_handle * handle = new AbstractHandle::abstract_handle(project_handle, trimed_string);
22286 if (handle)
22287 {
22288 if (handle->getNode()!=NULL)
22289 {
22290#ifdef _MSC_VER
22291 // DQ (11/28/2009): This is related to the use of covariant return types (I think).
22292 SgNode* result = NULL; // (SgNode*)(handle->getNode()->getNode());
22293#pragma message ("WARNING: covariant return type for get_node() not supported in MSVC.")
22294 printf ("ERROR: covariant return type for get_node() not supported in MSVC. \n");
22295 ROSE_ABORT();
22296#else
22297 SgNode* result = (SgNode*)(handle->getNode()->getNode());
22298#endif
22299 // deallocate memory, should not do this!!
22300 // May corrupt the internal std maps used in abstract handle namespace
22301 //delete handle->getNode();
22302 //delete handle;
22303 return result;
22304 }
22305 }
22306#endif
22307
22308 return NULL;
22309}
22310
22311
22313// unparseToString() is too strict for debugging purpose
22314// we provide this instead.
22315void SageInterface::dumpInfo(SgNode* node, std::string desc/*=""*/)
22316{
22317 ROSE_ASSERT(node != NULL);
22318 cout<<desc<<endl;
22319 // base information for all SgNode:
22320 cout<<"///////////// begin of SageInterface::dumpInfo() ///////////////"<<endl;
22321 cout<<"--------------base info. for SgNode---------------"<<endl;
22322 cout<<node<<" "<<node->class_name()<<endl;
22323 SgLocatedNode* snode = isSgLocatedNode(node);
22324 if (snode)
22325 {
22326 // source file info. dump
22327 cout<<"--------------source location info. for SgNode---------------"<<endl;
22328 cout<<snode->get_file_info()->get_filename()
22329 << ":"<<snode->get_file_info()->get_line()<<"-"
22330 << snode->get_file_info()->get_col()<<endl;
22331 // preprocessing info dump
22332 AttachedPreprocessingInfoType *comments = snode->getAttachedPreprocessingInfo ();
22333 if (comments)
22334 {
22335 cout<<"--------------preprocessing info. for SgNode---------------"<<endl;
22336 AttachedPreprocessingInfoType::iterator i;
22337 cout<<"Total attached preprocessingInfo count="<<comments->size()<<endl;
22338 for (i = comments->begin (); i != comments->end (); i++)
22339 {
22340 PreprocessingInfo * pinfo = *i;
22341 pinfo->display("");
22342 }
22343 }
22344 cout<<"--------------name info. for SgNode---------------"<<endl;
22345 // print out namea for named nodes
22346 SgFunctionDeclaration * decl = isSgFunctionDeclaration(snode);
22347 if (decl)
22348 cout<<"\tqualified name="<<decl->get_qualified_name().getString()<<endl;
22349 SgVarRefExp * varRef = isSgVarRefExp(snode);
22350 if (varRef)
22351 cout<<"\treferenced variable name= "<<varRef->get_symbol()->get_name().getString()<<endl;
22352 }
22353 SgInitializedName * iname = isSgInitializedName(snode);
22354 if (iname)
22355 cout<<"\tvariable name= "<<iname->get_qualified_name().getString()<<endl;
22356
22357 cout<<endl;
22358 cout<<"///////////// end of SageInterface::dumpInfo() ///////////////"<<endl;
22359}
22360
22366bool
22367SageInterface::collectReadWriteRefs(SgStatement* stmt, std::vector<SgNode*>& readRefs, std::vector<SgNode*>& writeRefs, bool useCachedDefUse)
22368{ // The type cannot be SgExpression since variable declarations have SgInitializedName as the reference, not SgVarRefExp.
22369 bool retVal = true;
22370
22371 ROSE_ASSERT(stmt !=NULL);
22372
22373#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22374 // We should allow accumulate the effects for multiple statements
22375 // ROSE_ASSERT(readRefs.size() == 0);
22376 // ROSE_ASSERT(writeRefs.size() == 0);
22377
22378 // convert a request for a defining function declaration to its function body
22379 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(stmt);
22380 if (funcDecl != NULL)
22381 {
22382 funcDecl= isSgFunctionDeclaration(funcDecl->get_definingDeclaration ());
22383 if (funcDecl == NULL)
22384 {
22385 cerr<<"In collectReadWriteRefs(): cannot proceed without a function body!"<<endl;
22386 }
22387 else
22388 stmt = funcDecl->get_definition()->get_body();
22389 }
22390
22391 // get function level information
22392 SgFunctionDefinition* funcDef = isSgFunctionDefinition(stmt);
22393 if (!funcDef)
22395
22396 ROSE_ASSERT(funcDef != NULL);
22397 SgBasicBlock* funcBody = funcDef->get_body();
22398 ROSE_ASSERT(funcBody!= NULL);
22399
22400 // prepare Loop transformation environment
22401 AstInterfaceImpl faImpl(funcBody);
22402 AstInterface fa(&faImpl);
22403 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
22404 if( useCachedDefUse ){
22405 ArrayInterface* array_interface = ArrayInterface::get_inst(*annot, fa, funcDef, AstNodePtrImpl(funcDef));
22406 LoopTransformInterface::set_arrayInfo(array_interface);
22407 } else {
22408 ArrayInterface array_interface(*annot);
22409 // Alias analysis and value propagation are called in initialize(). Turn both off for now.
22410// array_interface.initialize(fa, AstNodePtrImpl(funcDef));
22411 array_interface.observe(fa);
22412 LoopTransformInterface::set_arrayInfo(&array_interface);
22413 }
22414 LoopTransformInterface::set_astInterface(fa);
22415 // Liao, 3/27/2015. connect to annotations for function side effect
22416 LoopTransformInterface::set_sideEffectInfo(annot);
22417
22418 // variables to store results
22419 DoublyLinkedListWrap<AstNodePtr> rRef1, wRef1;
22420 CollectDoublyLinkedList<AstNodePtr> crRef1(rRef1),cwRef1(wRef1);
22421 AstNodePtr s1 = AstNodePtrImpl(stmt);
22422
22423 // Actual side effect analysis
22424 if (!AnalyzeStmtRefs(fa, s1, cwRef1, crRef1))
22425 {
22426 //False returned here just means that the function called a
22427 //function that was not annotated with Qing's RWset annotation
22428 //method. This doesn't matter for my tool. -Jim Leek 03/21/2023
22429 mlog[Sawyer::Message::Common::DEBUG] << "Function: " << funcDef->get_declaration()->get_qualified_name() << " calls at least one function that has not been annotated." << endl;
22430 retVal = false;
22431 }
22432
22433 // transfer results into STL containers.
22434 for (DoublyLinkedEntryWrap<AstNodePtr>* p = rRef1.First(); p != 0; )
22435 {
22436 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22437 p = rRef1.Next(p);
22438 AstNodePtr cur = p1->GetEntry();
22439 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22440 ROSE_ASSERT(sgRef != NULL);
22441 readRefs.push_back(sgRef);
22442 //cout<<"read reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22443 // " sage type:"<< sgRef->class_name()<< endl;
22444 }
22445
22446 for (DoublyLinkedEntryWrap<AstNodePtr>* p = wRef1.First(); p != 0; )
22447 {
22448 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22449 p = wRef1.Next(p);
22450 AstNodePtr cur = p1->GetEntry();
22451 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22452 ROSE_ASSERT(sgRef != NULL);
22453 writeRefs.push_back(sgRef);
22454 // cout<<"write reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22455 // " sage type:"<< sgRef->class_name()<< endl;
22456 }
22457
22458#endif
22459
22460 return retVal;
22461}
22462#if 0
22463// The side effect analysis will report three references for a statement like this->x = ...
22464// 1.SgThisExp 2. SgArrowExp 3. SgVarRefExp
22465// We only need to keep SgVarRefExp and skip the other two.
22466static bool skipSomeRefs(SgNode* n)
22467{
22468 ROSE_ASSERT (n);
22469 return (isSgThisExp(n)||isSgArrowExp(n)||isSgDotExp(n));
22470}
22471#endif
22473bool SageInterface::collectReadWriteVariables(SgStatement* stmt, set<SgInitializedName*>& readVars, set<SgInitializedName*>& writeVars, bool coarseGrain/*=true*/)
22474{
22475 ROSE_ASSERT(stmt != NULL);
22476 vector <SgNode* > readRefs, writeRefs;
22477
22478 bool retVal = collectReadWriteRefs(stmt, readRefs, writeRefs);
22479 // process read references
22480 vector<SgNode*>::iterator iter = readRefs.begin();
22481 for (; iter!=readRefs.end();iter++)
22482 {
22483 SgNode* current = *iter;
22484 //if (skipSomeRefs(current)) continue;
22485
22486 ROSE_ASSERT (current != NULL);
22487 SgInitializedName* name= convertRefToInitializedName(current, coarseGrain);
22488 //ROSE_ASSERT (name); // this pointer will return NULL
22489 if (!name) continue;
22490 // Only insert unique ones
22491 // We use std::set to ensure uniqueness now
22492 readVars.insert(name);
22493 }
22494 // process write references
22495 vector<SgNode*>::iterator iterw = writeRefs.begin();
22496 for (; iterw!=writeRefs.end();iterw++)
22497 {
22498 SgNode* current = *iterw;
22499 ROSE_ASSERT (current != NULL);
22500 SgInitializedName* name = convertRefToInitializedName(current, coarseGrain);
22501 if (!name) continue;
22502 //ROSE_ASSERT (name); // this pointer will return NULL
22503 // Only insert unique ones
22504 // We use std::set to ensure uniqueness now
22505 writeVars.insert(name);
22506 }
22507 return retVal;
22508}
22509
22511void SageInterface::collectReadOnlyVariables(SgStatement* stmt, std::set<SgInitializedName*>& readOnlyVars, bool coarseGrain/*=true*/)
22512{
22513 ROSE_ASSERT(stmt != NULL);
22514 set<SgInitializedName*> readVars, writeVars;
22515 // Only collect read only variables if collectReadWriteVariables() succeeded.
22516 if (collectReadWriteVariables(stmt, readVars, writeVars, coarseGrain))
22517 {
22518 // read only = read - write
22519 set_difference(readVars.begin(), readVars.end(),
22520 writeVars.begin(), writeVars.end(),
22521 std::inserter(readOnlyVars, readOnlyVars.begin()));
22522 }
22523 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
22524 {
22525 RoseAst ast(stmt);
22526
22527 for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
22528 if (SgVarRefExp* v_ref = isSgVarRefExp(*i))
22529 {
22530 if (isConstType(v_ref->get_type()))
22531 readOnlyVars.insert (v_ref->get_symbol()->get_declaration());
22532 }
22533 } // end for
22534 } // end else
22535}
22536
22537
22539void SageInterface::collectReadOnlySymbols(SgStatement* stmt, std::set<SgVariableSymbol*>& readOnlySymbols, bool coarseGrain/*=true*/)
22540{
22541 set<SgInitializedName*> temp;
22542 collectReadOnlyVariables(stmt, temp, coarseGrain);
22543
22544 for (set<SgInitializedName*>::const_iterator iter = temp.begin();
22545 iter!=temp.end(); iter++)
22546 {
22547 SgSymbol* symbol = (*iter)->get_symbol_from_symbol_table () ;
22548 ROSE_ASSERT(symbol != NULL );
22549 ROSE_ASSERT(isSgVariableSymbol(symbol));
22550 readOnlySymbols.insert(isSgVariableSymbol(symbol));
22551 }
22552
22553}
22554
22557{
22558 bool result = false;
22559 ROSE_ASSERT(ref != NULL);
22560 ROSE_ASSERT(ref->get_parent() != NULL);
22561 // case 1: ref is used as an operator for & (SgAddressofOp)
22562 // TODO tolerate possible type casting operations in between ?
22563 if (isSgAddressOfOp(ref->get_parent()))
22564 {
22565 result = true;
22566 }
22567 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22568 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22569 {
22570 SgNode* grandparent = ref->get_parent()->get_parent();
22571 ROSE_ASSERT(grandparent);
22572 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22573 {
22574 // find which parameter ref is in SgExpressionPtrList
22575
22576 // DQ (8/12/2020): This is a compiler warning where it is used below in comparision between signed and unsigned types.
22577 // int param_index = 0;
22578 size_t param_index = 0;
22579
22580 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22581 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22582 for (; iter!=expList.end(); iter++)
22583 {
22584 if (*iter == ref)
22585 break;
22586 else
22587 param_index++;
22588 }
22589 // find the parameter type of the corresponding function declaration
22590 SgExpression* func_exp = isSgFunctionCallExp(grandparent)->get_function();
22591 ROSE_ASSERT (func_exp);
22592 SgFunctionRefExp * funcRef = isSgFunctionRefExp(func_exp);
22593 if (funcRef) // regular functions
22594 {
22595 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22596 SgInitializedNamePtrList nameList = funcDecl->get_args();
22597 //TODO tolerate typedef chains
22598 // printf() has only two arguments to express variable arguments.
22599 // The third argument index ==2 will be out of bounds for nameList[index]
22600 // So we must check the bound first.
22601 if (param_index >= nameList.size() ||isSgTypeEllipse(nameList[param_index]->get_type()) )
22602 {
22603 if (isSgReferenceType(ref))
22604 result = true;
22605 }
22606 else // now within the bound: two situations,
22607 if (isSgReferenceType(nameList[param_index]->get_type()))
22608 {
22609 result = true;
22610 }
22611 } //It also could be a dot or arrow expression where its right hand operand is a SgMemberFunctionRefExp
22612 else if (isSgDotExp (func_exp) || isSgArrowExp(func_exp)) // ArrowExp TODO
22613 {
22614 SgBinaryOp* binOp = isSgBinaryOp(func_exp);
22615 ROSE_ASSERT (binOp);
22616 SgMemberFunctionRefExp* mfuncRef = isSgMemberFunctionRefExp(binOp->get_rhs_operand_i());
22617 ROSE_ASSERT (mfuncRef);
22618 SgMemberFunctionDeclaration * mfuncDecl = isSgMemberFunctionSymbol (mfuncRef->get_symbol())->get_declaration();
22619 ROSE_ASSERT (mfuncDecl);
22620 SgInitializedNamePtrList nameList = mfuncDecl->get_args();
22621 //TODO tolerate typedef chains
22622 if (isSgReferenceType(nameList[param_index]->get_type()))
22623 {
22624 result = true;
22625 }
22626 }
22627
22628 }
22629 }
22630 return result;
22631}
22632
22633
22635void SageInterface::collectUseByAddressVariableRefs (const SgStatement* s, std::set<SgVarRefExp* >& varSetB)
22636{
22637 Rose_STL_Container <SgNode*> var_refs = NodeQuery::querySubTree (const_cast<SgStatement *> (s), V_SgVarRefExp);
22638
22639 Rose_STL_Container<SgNode*>::iterator iter = var_refs.begin();
22640 for (; iter!=var_refs.end(); iter++)
22641 {
22642 SgVarRefExp* ref = isSgVarRefExp(*iter);
22643 ROSE_ASSERT(ref != NULL);
22644 ROSE_ASSERT(ref->get_parent() != NULL);
22645#if 0
22646 // case 1: ref is used as an operator for & (SgAddressofOp)
22647 // TODO tolerate possible type casting operations in between ?
22648 if (isSgAddressOfOp(ref->get_parent()))
22649 {
22650 varSetB.insert(ref);
22651 }
22652 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22653 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22654 {
22655 SgNode* grandparent = ref->get_parent()->get_parent();
22656 ROSE_ASSERT(grandparent);
22657 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22658 {
22659 // find which parameter ref is in SgExpressionPtrList
22660 int param_index =0;
22661 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22662 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22663 for (; iter!=expList.end(); iter++)
22664 {
22665 if (*iter == ref)
22666 break;
22667 else
22668 param_index++;
22669 }
22670 // find the parameter type of the corresponding function declaration
22671 SgFunctionRefExp * funcRef = isSgFunctionRefExp(isSgFunctionCallExp(grandparent)->get_function());
22672 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22673 SgInitializedNamePtrList nameList = funcDecl->get_args();
22674 //TODO tolerate typedef chains
22675 if (isSgReferenceType(nameList[param_index]->get_type()))
22676 {
22677 varSetB.insert(ref);
22678 }
22679 }
22680 }
22681#endif
22683 varSetB.insert(ref);
22684 }
22685}
22686
22687#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22689LivenessAnalysis * SageInterface::call_liveness_analysis(SgProject* project, bool debug/*=false*/)
22690{
22691 // We expect this function to be called multiple times but always return the result generated from the first execution.
22692 static LivenessAnalysis* liv = NULL; // one instance
22693 if (liv!=NULL)
22694 return liv;
22695
22696 static DFAnalysis * defuse = NULL; // only one instance
22697 // Prepare def-use analysis
22698 if (defuse==NULL)
22699 {
22700 ROSE_ASSERT(project != NULL);
22701 defuse = new DefUseAnalysis(project);
22702 }
22703
22704 ROSE_ASSERT(defuse != NULL);
22705 defuse->run(debug);
22706
22707 if (debug)
22708 defuse->dfaToDOT();
22709
22710 //Prepare variable liveness analysis
22711 liv = new LivenessAnalysis(debug,(DefUseAnalysis*)defuse);
22712 ROSE_ASSERT(liv != NULL);
22713
22714 std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions;
22715 NodeQuerySynthesizedAttributeType vars =
22716 NodeQuery::querySubTree(project, V_SgFunctionDefinition);
22717 NodeQuerySynthesizedAttributeType::const_iterator i;
22718 bool abortme=false;
22719 // run liveness analysis on each function body
22720 for (i= vars.begin(); i!=vars.end();++i)
22721 {
22722 SgFunctionDefinition* func = isSgFunctionDefinition(*i);
22723 ROSE_ASSERT(func != NULL);
22724 if (debug)
22725 {
22726 std::string name = func->class_name();
22727 string funcName = func->get_declaration()->get_qualified_name().str();
22728 cout<< " .. running liveness analysis for function: " << funcName << endl;
22729 }
22730 FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
22731 // propagate results to statement level
22732 liv->fixupStatementsINOUT(func);
22733 if (rem_source.getNode()!=NULL)
22734 dfaFunctions.push_back(rem_source);
22735 if (abortme)
22736 break;
22737 } // end for ()
22738 if(debug)
22739 {
22740 cout << "Writing out liveness analysis results into var.dot... " << endl;
22741 std::ofstream f2("var.dot");
22742 dfaToDot(f2, string("var"), dfaFunctions, (DefUseAnalysis*)defuse, liv);
22743 f2.close();
22744 }
22745 if (abortme) {
22746 cerr<<"Error: Liveness analysis is ABORTING ." << endl;
22747 ROSE_ABORT();
22748 }
22749 return liv;
22750 //return !abortme;
22751}
22752#endif
22753
22754#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22756void SageInterface::getLiveVariables(LivenessAnalysis * liv, SgForStatement* loop, std::set<SgInitializedName*>& liveIns, std::set<SgInitializedName*> & liveOuts)
22757{
22758 ROSE_ASSERT(liv != NULL);
22759 ROSE_ASSERT(loop != NULL);
22760 SgForStatement *forstmt = loop;
22761 std::vector<SgInitializedName*> liveIns0, liveOuts0; // store the original one
22762
22763 // Jeremiah's hidden constructor parameter value '2' to grab the node for forStmt's
22764 // Several CFG nodes are used for the same SgForStatement, only one of the is needed.
22765 // We have to check the full control flow graph to find all SgForStatement's nodes,
22766 // check the index numbers from 0 , find the one with two out edges (true, false)
22767 // The CFG node should have a caption like" <SgForStatement> @ 8: 1",
22768 // which means this is a CFG node for a for statement at source line 8, with an index 1.
22769 // For SgForStatement, there are 5 cfg nodes, 0 and 4 are for begin and end CFG nodes
22770 // 1: after init statement, 2: after test expression (the remaining one after filtering), 3: before increment
22771 CFGNode cfgnode(forstmt,2);
22772 FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (cfgnode);
22773 // This one does not return the one we want even its getNode returns the
22774 // right for statement
22775 //FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (forstmt->cfgForBeginning());
22776 ROSE_ASSERT(filternode.getNode()==forstmt);
22777
22778 // Check out edges
22779 vector<FilteredCFGEdge < IsDFAFilter > > out_edges = filternode.outEdges();
22780 ROSE_ASSERT(out_edges.size()==2);
22781 vector<FilteredCFGEdge < IsDFAFilter > >::iterator iter= out_edges.begin();
22782
22783 for (; iter!=out_edges.end();iter++)
22784 {
22785 FilteredCFGEdge < IsDFAFilter > edge= *iter;
22786 //SgForStatement should have two outgoing edges based on the loop condition
22787 // one true(going into the loop body) and one false (going out the loop)
22788 //x. Live-in (loop) = live-in (first-stmt-in-loop)
22789 if (edge.condition()==eckTrue)
22790 {
22791 SgNode* firstnode= edge.target().getNode();
22792 liveIns0 = liv->getIn(firstnode);
22793 // cout<<"Live-in variables for loop:"<<endl;
22794 for (std::vector<SgInitializedName*>::iterator iter = liveIns0.begin();
22795 iter!=liveIns0.end(); iter++)
22796 {
22797 // SgInitializedName* name = *iter;
22798 liveIns.insert(*iter);
22799 // cout<< name->get_qualified_name().getString()<<endl;
22800 }
22801 }
22802 //x. live-out(loop) = live-in (first-stmt-after-loop)
22803 else if (edge.condition()==eckFalse)
22804 {
22805 SgNode* firstnode= edge.target().getNode();
22806 liveOuts0 = liv->getIn(firstnode);
22807 // cout<<"Live-out variables for loop:"<<endl;
22808 for (std::vector<SgInitializedName*>::iterator iter = liveOuts0.begin();
22809 iter!=liveOuts0.end(); iter++)
22810 {
22811 // SgInitializedName* name = *iter;
22812 // cout<< name->get_qualified_name().getString()<<endl;
22813 liveOuts.insert(*iter);
22814 }
22815 }
22816 else
22817 {
22818 cerr<<"Unexpected CFG out edge type for SgForStmt!"<<endl;
22819 ROSE_ABORT();
22820 }
22821 } // end for (edges)
22822
22823}
22824#endif
22825
22826//Check if two references form an idiom like: x= x op expr, x = expr op x (except for subtraction)
22827static bool isAssignReduction (SgVarRefExp* ref_exp1, SgVarRefExp* ref_exp2, OmpSupport::omp_construct_enum& optype)
22828{
22829 bool isReduction = false;
22830 // Sanity check
22831 ROSE_ASSERT (ref_exp1!= NULL);
22832 ROSE_ASSERT (ref_exp2!= NULL);
22833 ROSE_ASSERT (ref_exp1-> get_symbol() == ref_exp2-> get_symbol());
22834 // must be scalar type
22835 ROSE_ASSERT (SageInterface::isScalarType(ref_exp1-> get_symbol()->get_type() ) );
22836
22839 if (stmt != stmt2) return false; // early return false;
22840
22841 // must be assignment statement using
22842 // x= x op expr, x = expr op x (except for subtraction)
22843 // one reference on left hand, the other on the right hand of assignment expression
22844 // the right hand uses associative operators +, *, -, &, ^ ,|, &&, ||
22845 SgExprStatement* exp_stmt = isSgExprStatement(stmt);
22846 if (exp_stmt && isSgAssignOp(exp_stmt->get_expression()))
22847 {
22848 SgExpression* assign_lhs=NULL, * assign_rhs =NULL;
22849 assign_lhs = isSgAssignOp(exp_stmt->get_expression())->get_lhs_operand();
22850 assign_rhs = isSgAssignOp(exp_stmt->get_expression())->get_rhs_operand();
22851 ROSE_ASSERT(assign_lhs && assign_rhs);
22852 // x must show up in both lhs and rhs in any order:
22853 // e.g.: ref1 = ref2 op exp or ref2 = ref1 op exp
22854 if (((assign_lhs==ref_exp1)&&SageInterface::isAncestor(assign_rhs,ref_exp2))
22855 ||((assign_lhs==ref_exp2)&&SageInterface::isAncestor(assign_rhs,ref_exp1)))
22856 {
22857 // assignment's rhs must match the associative binary operations
22858 // +, *, -, &, ^ ,|, &&, ||
22859 SgBinaryOp * binop = isSgBinaryOp(assign_rhs);
22860 if (binop!=NULL){
22861 SgExpression* op_lhs = binop->get_lhs_operand();
22862 SgExpression* op_rhs = binop->get_rhs_operand();
22863
22864 // double check that the binary expression has either ref1 or ref2 as one operand
22865 if( !((op_lhs==ref_exp1)||(op_lhs==ref_exp2))
22866 && !((op_rhs==ref_exp1)||(op_rhs==ref_exp2)))
22867 return false; // early return false;
22868
22869 bool isOnLeft = false; // true if it has form (refx op exp), instead (exp or refx)
22870 if ((op_lhs==ref_exp1)|| // TODO might have in between !!
22871 (op_lhs==ref_exp2))
22872 isOnLeft = true;
22873 switch (binop->variantT())
22874 {
22875 case V_SgAddOp:
22876 {
22877 optype = OmpSupport::e_reduction_plus;
22878 isReduction = true;
22879 break;
22880 }
22881 case V_SgMultiplyOp:
22882 {
22883 optype = OmpSupport::e_reduction_mul;
22884 isReduction = true;
22885 break;
22886 }
22887 case V_SgSubtractOp: // special handle here!!
22888 {
22889 optype = OmpSupport::e_reduction_minus;
22890 if (isOnLeft) // cannot allow (exp - x)a
22891 {
22892 isReduction = true;
22893 }
22894 break;
22895 }
22896 case V_SgBitAndOp:
22897 {
22898 optype = OmpSupport::e_reduction_bitand ;
22899 isReduction = true;
22900 break;
22901 }
22902 case V_SgBitXorOp:
22903 {
22904 optype = OmpSupport::e_reduction_bitxor;
22905 isReduction = true;
22906 break;
22907 }
22908 case V_SgBitOrOp:
22909 {
22910 optype = OmpSupport::e_reduction_bitor;
22911 isReduction = true;
22912 break;
22913 }
22914 case V_SgAndOp:
22915 {
22916 optype = OmpSupport::e_reduction_logand;
22917 isReduction = true;
22918 break;
22919 }
22920 case V_SgOrOp:
22921 {
22922 optype = OmpSupport::e_reduction_logor;
22923 isReduction = true;
22924 break;
22925 }
22926 default:
22927 break;
22928 }
22929 } // end matching associative operations
22930 }
22931 } // end if assignop
22932 return isReduction;
22933}
22934// A helper function for reduction recognition
22935// check if two references to the same variable form a reduction idiom using if-statement
22936// example 1: if (array[i]> maxV) maxV = array[i]
22937// example 2: if (array[i]< minV) minV = array[i]
22938// If it matches, return true and the reduction operator type
22939static bool isIfReduction(SgVarRefExp* ref1, SgVarRefExp* ref2, OmpSupport::omp_construct_enum& optype)
22940{
22941 bool matchStmt1 = false;
22942 bool matchStmt2 = false;
22943
22944 //TODO: ensure ref1, ref2 are ordered as pre-order manner in AST
22945 // SgExpression* reduction_var_ref = NULL;
22946 // SgExpression* source_var_ref = NULL; //array[i] is the source var ref
22947
22948 // Sanity check
22949 ROSE_ASSERT (ref1 != NULL);
22950 ROSE_ASSERT (ref2 != NULL);
22951 ROSE_ASSERT (ref1-> get_symbol() == ref2-> get_symbol());
22952 // must be scalar type
22953 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22954
22957
22958 //early return if the same stmt
22959 if (stmt1 == stmt2) return false;
22960
22961 // check stmt2 first. It is easier.
22962 // stmt2 should be an assignment stmt like:
22963 // reduction_variable = else;
22964 // minV = array[i];
22965 SgExpression* lhs2 = NULL;
22966 SgExpression* rhs2 = NULL;
22967 if (SageInterface::isAssignmentStatement (stmt2, &lhs2, &rhs2 ))
22968 {
22969 // lhs2 must be ref2
22970 if (lhs2 == ref2 )
22971 {
22972 matchStmt2 = true;
22973 // reduction_var_ref = lhs2;
22974 // source_var_ref= rhs2;
22975 }
22976 } // end assignment stmt
22977
22978 // stmt1 should be a if-stmt's conditional expression stmt
22979 // and its body should be stmt2
22980 if (SgExprStatement* if_cond_stmt = isSgExprStatement(stmt1))
22981 {
22982 bool matchBody = false;
22983 bool matchCondition= false;
22984 if (SgIfStmt * if_stmt = isSgIfStmt (if_cond_stmt->get_parent()) )
22985 {
22986 if (SgStatement* body = if_stmt->get_true_body())
22987 {
22988 if (SgBasicBlock* block = isSgBasicBlock (body))
22989 {
22990 // stmt2 must be the only child of the if true body
22991 ROSE_ASSERT(stmt2 != NULL);
22992 if ( ((block->get_statements()).size() == 1) && stmt2->get_scope() == block )
22993 matchBody = true;
22994 }
22995 else
22996 {
22997 if (body == stmt2)
22998 matchBody = true;
22999 }
23000 } // body match test
23001
23002 // match condition SgExprStatement ref1 SgLessThanOp source_var
23003 if (SgExprStatement* cond_exp_stmt = isSgExprStatement (if_stmt->get_conditional()) )
23004 {
23005 SgExpression* cond_exp = cond_exp_stmt->get_expression();
23006 if (SgBinaryOp * binop = isSgBinaryOp (cond_exp))
23007 {
23008 if (ref1 == binop->get_lhs_operand_i())
23009 {
23010 // minV > array[i] ;
23011 if (isSgLessThanOp (binop))
23012 {
23013 optype = OmpSupport::e_reduction_max;
23014 matchCondition= true;
23015 }
23016 else if (isSgGreaterThanOp(binop))
23017 {
23018 optype = OmpSupport::e_reduction_min;
23019 matchCondition= true;
23020 }
23021 }
23022 else if ( ref1 == binop->get_rhs_operand_i() )
23023 {
23024 // array[i] < minV
23025 if (isSgLessThanOp (binop))
23026 {
23027 optype = OmpSupport::e_reduction_min;
23028 matchCondition= true;
23029 }
23030 else if (isSgGreaterThanOp(binop))
23031 {
23032 optype = OmpSupport::e_reduction_max;
23033 matchCondition= true;
23034 }
23035 }
23036 } // end if binary op
23037 // TODO the source_var should match the source_var from stmt2
23038 }
23039 }
23040 matchStmt1 = matchBody && matchCondition;
23041 } // end if-stmt
23042
23043
23044 return (matchStmt2 && matchStmt1);
23045}
23046
23047// check if a var ref is a form of
23048// --x, x--, ++x, x++
23049// x+= .., x-= ..., etc.
23050// The reduction variable appears only once in the reduction idiom.
23051static bool isSingleAppearanceReduction(SgVarRefExp* ref1, OmpSupport::omp_construct_enum& optype )
23052{
23053 bool isReduction = false;
23054
23055 ROSE_ASSERT (ref1 != NULL);
23056 // must be scalar type
23057 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
23058
23060
23061 if (isSgExprStatement(stmt))
23062 {
23063 SgExpression* exp = isSgExprStatement(stmt)->get_expression();
23064 SgExpression* binop = isSgBinaryOp(exp);
23065 if (isSgPlusPlusOp(exp)) // x++ or ++x
23066 { // Could have multiple reduction clause with different operators!!
23067 // So the variable list is associated with each kind of operator
23068 optype = OmpSupport::e_reduction_plus;
23069 isReduction = true;
23070 }
23071 else if (isSgMinusMinusOp(exp)) // x-- or --x
23072 {
23073 optype = OmpSupport::e_reduction_minus;
23074 isReduction = true;
23075 }
23076 else
23077 // x binop= expr where binop is one of + * - & ^ |
23078 // x must be on the left hand side
23079 if (binop!=NULL) {
23080 SgExpression* lhs= isSgBinaryOp(exp)->get_lhs_operand ();
23081 if (lhs==ref1)
23082 {
23083 switch (exp->variantT())
23084 {
23085 case V_SgPlusAssignOp:
23086 {
23087 optype = OmpSupport::e_reduction_plus;
23088 isReduction = true;
23089 break;
23090 }
23091 case V_SgMultAssignOp:
23092 {
23093 optype = OmpSupport::e_reduction_mul;
23094 isReduction = true;
23095 break;
23096 }
23097 case V_SgMinusAssignOp:
23098 {
23099 optype = OmpSupport::e_reduction_minus;
23100 isReduction = true;
23101 break;
23102 }
23103 case V_SgAndAssignOp:
23104 {
23105 optype = OmpSupport::e_reduction_bitand;
23106 isReduction = true;
23107 break;
23108 }
23109 case V_SgXorAssignOp:
23110 {
23111 optype = OmpSupport::e_reduction_bitxor;
23112 isReduction = true;
23113 break;
23114 }
23115 case V_SgIorAssignOp:
23116 {
23117 optype = OmpSupport::e_reduction_bitor;
23118 isReduction = true;
23119 break;
23120 }
23121 default:
23122 break;
23123 } // end
23124 }// end if on left side
23125 }
23126 }
23127 return isReduction;
23128}
23129
23131/* This code is refactored from project/autoParallelization/autoParSupport.C
23132 std::vector<SgInitializedName*>
23133 RecognizeReduction(SgNode *loop, OmpSupport::OmpAttribute* attribute, std::vector<SgInitializedName*>& candidateVars/)
23134 * Algorithms:
23135 * for each scalar candidate which are both live-in and live-out for the loop body
23136 * (We don't use liveness analysis here for simplicity)
23137 * and which is not the loop invariant variable (loop index).
23138 * Consider those with only 1 or 2 references
23139 * 1 reference
23140 * the operation is one of x++, ++x, x--, --x, x binop= expr
23141 * 2 references belonging to the same operation
23142 * operations: one of x= x op expr, x = expr op x (except for subtraction)
23143 * The reduction description from the OpenMP 3.0 specification.
23144 * x is not referenced in exp
23145 * expr has scalar type (no array, objects etc)
23146 * x: scalar only, aggregate types (including arrays), pointer types and reference types may not appear in a reduction clause.
23147 * op is not an overloaded operator, but +, *, -, &, ^ ,|, &&, ||
23148 * binop is not an overloaded operator, but: +, *, -, &, ^ ,|
23149 */
23150void SageInterface::ReductionRecognition(SgForStatement* loop, std::set< std::pair <SgInitializedName*, OmpSupport::omp_construct_enum > > & results)
23151{
23152 //x. Collect variable references of scalar types as candidates, excluding loop index
23153 SgInitializedName* loopindex;
23154 if (!(isCanonicalForLoop(loop, &loopindex)))
23155 {
23156// cerr<<"Skip reduction recognition for non-canonical for loop"<<endl;
23157 return;
23158 }
23159 std::set<SgInitializedName*> candidateVars; // scalar variables used within the loop
23160 //Store the references for each scalar variable
23161 std::map <SgInitializedName*, vector<SgVarRefExp* > > var_references;
23162
23163 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(loop, V_SgVarRefExp);
23164 SgStatement* lbody= loop->get_loop_body();
23165 ROSE_ASSERT(lbody != NULL);
23166 Rose_STL_Container<SgNode*>::iterator iter = reflist.begin();
23167 for (; iter!=reflist.end(); iter++)
23168 {
23169 SgVarRefExp* ref_exp = isSgVarRefExp(*iter);
23170 SgInitializedName* initname= ref_exp->get_symbol()->get_declaration();
23171 // candidates are of scalar types and are not the loop index variable
23172 // And also should be live-in:
23173 // not declared locally (var_scope equal or lower than loop body )
23174 // or redefined (captured by ref count)
23175 SgScopeStatement* var_scope = initname->get_scope();
23176 ROSE_ASSERT(var_scope != NULL);
23177 if ((isScalarType(initname->get_type())) &&(initname !=loopindex)
23178 && !(SageInterface::isAncestor(lbody, var_scope)||(lbody==var_scope)))
23179 {
23180 candidateVars.insert(initname);
23181 var_references[initname].push_back(ref_exp);
23182 }
23183 }
23184
23185 //Consider variables referenced at most twice
23186 std::set<SgInitializedName*>::iterator niter=candidateVars.begin();
23187 for (; niter!=candidateVars.end(); niter++)
23188 {
23189 SgInitializedName* initname = *niter;
23190 bool isReduction = false;
23191 OmpSupport::omp_construct_enum optype;
23192 // referenced once only
23193 if (var_references[initname].size()==1)
23194 {
23195 mlog[Sawyer::Message::Common::DEBUG] << "Debug: SageInterface::ReductionRecognition() A candidate used once:"<<initname->get_name().getString()<<endl;
23196 SgVarRefExp* ref_exp = *(var_references[initname].begin());
23197 if (isSingleAppearanceReduction (ref_exp, optype))
23198 isReduction = true;
23199 }
23200 // referenced twice within a same statement
23201 else if (var_references[initname].size()==2)
23202 {
23203 mlog[Sawyer::Message::Common::DEBUG] << "Debug: A candidate used twice:"<<initname->get_name().getString()<<endl;
23204 SgVarRefExp* ref_exp1 = *(var_references[initname].begin());
23205 SgVarRefExp* ref_exp2 = *(++var_references[initname].begin());
23206 // TODO: recognize maxV = array[i]>maxV? array[i]:maxV // this can be normalized to if () stmt
23207 // TODO: recognize maxV = max (maxV, array[i])
23208 if (isAssignReduction (ref_exp1, ref_exp2, optype) || isIfReduction (ref_exp1, ref_exp2, optype) )
23209 {
23210 isReduction = true;
23211 }
23212
23213 }// end referenced twice
23214
23215 if (isReduction)
23216 results.insert(make_pair(initname,optype));
23217 }// end for ()
23218}
23219
23222{
23223 ROSE_ASSERT(r!=NULL);
23224#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23225 ConstantFolding::constantFoldingOptimization(r,false);
23226#endif
23227}
23228
23231{
23233 {
23234 public:
23235 virtual void visit (SgNode * n)
23236 {
23237 SgExpression* exp = isSgExpression(n);
23238 if (exp)
23239 {
23240 string u_name = generateUniqueName(exp,false)+"-"+exp->class_name();
23241 AstAttribute * name_attribute = new UniqueNameAttribute(u_name);
23242 ROSE_ASSERT (name_attribute != NULL);
23243 exp->addNewAttribute("UniqueNameAttribute",name_attribute);
23244 }
23245 }
23246 };
23247 visitorTraversal exampleTraversal;
23248 //Sriram FIX: should traverse using the traverse function
23249 // exampleTraversal.traverseInputFiles(project,preorder);
23250 exampleTraversal.traverse(project, preorder);
23251}
23252
23253
23254 //
23255 // wrap free-standing function body in another function
23256
23258 {
23259 ROSE_ASSERT(vardecl.get_variables().size());
23260
23261 return *vardecl.get_variables().front();
23262 }
23263
23264#if 0
23265 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23266 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23267
23275 static
23277 cloneParameterList(const SgFunctionParameterList& params, SgFunctionDefinition* fundef = NULL)
23278 {
23279 namespace SB = SageBuilder;
23280
23281 SgFunctionParameterList& copy = *SB::buildFunctionParameterList();
23282 const SgInitializedNamePtrList& orig_decls = params.get_args();
23283
23284 std::transform( orig_decls.begin(), orig_decls.end(), sg::sage_inserter(copy), sg::InitNameCloner(copy, fundef) );
23285
23286 return copy;
23287 }
23288#endif
23289
23290#if 0
23291 // DQ (2/16/2017): This is a static function that is defined but not used in this file (compiler waring).
23292
23294 static
23295 void swapDefiningElements(SgFunctionDeclaration& ll, SgFunctionDeclaration& rr)
23296 {
23297 // swap definitions
23298 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_definition, &SgFunctionDeclaration::set_definition);
23299 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_parameterList, &SgFunctionDeclaration::set_parameterList);
23300
23301 // \todo do we need to swap also exception spec, decorator_list, etc. ?
23302 }
23303#endif
23304
23305#if 0
23306 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23307 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23308
23309 std::pair<SgStatement*, SgInitializedName*>
23310 SageInterface::wrapFunction(SgFunctionDeclaration& definingDeclaration, SgName newName)
23311 {
23312 namespace SB = SageBuilder;
23313
23314 // handles freestanding functions only
23315 ROSE_ASSERT(typeid(SgFunctionDeclaration) == typeid(definingDeclaration));
23316 ROSE_ASSERT(definingDeclaration.get_definingDeclaration() == &definingDeclaration);
23317
23318 // clone function parameter list
23319 SgFunctionParameterList& param_list = cloneParameterList(*definingDeclaration.get_parameterList());
23320
23321 // create new function definition/declaration in the same scope
23322 SgScopeStatement* containing_scope = definingDeclaration.get_scope();
23323 SgType* result_type = definingDeclaration.get_type()->get_return_type();
23324 SgExprListExp* decorators = deepCopy( definingDeclaration.get_decoratorList() );
23325
23326 // DQ (4/9/2015): Suggested fix for this function.
23327 // SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope, decorators);
23328 SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope);
23329
23330 SgFunctionDefinition* wrapperdef = wrapperfn->get_definition();
23331 ROSE_ASSERT(wrapperdef);
23332
23333 // copy the exception specification
23334 wrapperfn->set_exceptionSpecification(definingDeclaration.get_exceptionSpecification());
23335
23336 // swap the original's function definition w/ the clone's function def
23337 // and the original's func parameter list w/ the clone's parameters
23338 swapDefiningElements(definingDeclaration, *wrapperfn);
23339
23340 // call original function from within the defining decl's body
23341 SgBasicBlock* body = wrapperdef->get_body();
23342 SgExprListExp* args = SB::buildExprListExp();
23343 SgInitializedNamePtrList& param_decls = param_list.get_args();
23344
23345 std::transform( param_decls.begin(), param_decls.end(), sg::sage_inserter(*args), sg::VarRefBuilder(*wrapperdef) );
23346
23347 SgFunctionCallExp* callWrapped = SB::buildFunctionCallExp( newName, result_type, args, body );
23348 SgInitializedName* resultName = NULL;
23349 SgStatement* callStatement = NULL;
23350
23351 // \todo skip legal qualifiers that could be on top of void
23352 if (!isSgTypeVoid(result_type))
23353 {
23354 // add call to original function and assign result to variable
23355 SgVariableDeclaration* res = SB::buildVariableDeclaration( "res", result_type, SB::buildAssignInitializer(callWrapped), body );
23356 SgVarRefExp* resref = SB::buildVarRefExp( res );
23357
23358 appendStatement(res, body);
23359
23360 // add return statement, returning result
23361 resultName = &getFirstVariable(*res);
23362 callStatement = res;
23363
23364 appendStatement(SB::buildReturnStmt(resref), body);
23365 }
23366 else
23367 {
23368 // add function call statement to original function
23369 callStatement = SB::buildExprStatement(callWrapped);
23370 appendStatement(callStatement, body);
23371 }
23372
23373 ROSE_ASSERT(callStatement);
23374
23375 // create non defining declaration
23376 SgExprListExp* decorator_proto = deepCopy( decorators );
23377 SgFunctionDeclaration* wrapperfn_proto = SB::buildNondefiningFunctionDeclaration(wrapperfn, containing_scope, decorator_proto);
23378
23379 // add the new functions at the proper location of the surrounding scope
23380 insertStatementBefore(&definingDeclaration, wrapperfn_proto);
23381 insertStatementAfter (&definingDeclaration, wrapperfn);
23382
23383 return std::make_pair(callStatement, resultName);
23384 }
23385#endif
23386
23387 //
23388 // flatten C/C++ array dimensions
23389 namespace
23390 {
23391 struct VarrefBuilder
23392 {
23393 virtual SgVarRefExp* get() const = 0;
23394
23395 static
23396 SgVarRefExp* build(const SgVarRefExp& n)
23397 {
23398 return SageInterface::deepCopy(&n);
23399 }
23400
23401 static
23403 {
23404 SgScopeStatement* scope = sg::ancestor<SgStatement>(n).get_scope();
23405
23406 return SageBuilder::buildVarRefExp(&n, scope);
23407 }
23408 };
23409
23410 template <class AstNode>
23411 struct VarrefCreator : VarrefBuilder
23412 {
23413 AstNode& origin;
23414
23415 explicit
23416 VarrefCreator(AstNode& orig)
23417 : origin(orig)
23418 {}
23419
23420 SgVarRefExp* get() const { return VarrefBuilder::build(origin); }
23421 };
23422
23423 template <class AstNode>
23424 VarrefCreator<AstNode>
23425 varrefCreator(AstNode& n)
23426 {
23427 return VarrefCreator<AstNode>(n);
23428 }
23429
23430 SgExpression* create_mulop(SgExpression* lhs, const SgExpression* rhs)
23431 {
23432 namespace SB = SageBuilder;
23433 namespace SI = SageInterface;
23434
23435 // we own the lhs (intermediate result),
23436 // but we do not own the rhs (another top-level expression)
23437 return SB::buildMultiplyOp(lhs, SI::deepCopy(rhs));
23438 }
23439
23440 std::pair<std::vector<SgExpression*>, SgType*>
23441 get_C_array_dimensions_aux(const SgArrayType& arr_type)
23442 {
23443 namespace SB = SageBuilder;
23444 namespace SI = SageInterface;
23445
23446 const SgArrayType* arrtype = &arr_type;
23447 std::vector<SgExpression*> indices;
23448 SgType* undertype = NULL;
23449
23450 // \todo when get_index() does not return a nullptr anymore
23451 // the condition can be removed
23452 if (arrtype->get_index() == NULL)
23453 {
23454 indices.push_back(SB::buildNullExpression());
23455 undertype = arrtype->get_base_type();
23456 arrtype = isSgArrayType(undertype);
23457 }
23458
23459 while (arrtype)
23460 {
23461 SgExpression* indexexpr = arrtype->get_index();
23462 ROSE_ASSERT(indexexpr);
23463
23464 indices.push_back(SI::deepCopy(indexexpr));
23465 undertype = arrtype->get_base_type();
23466 arrtype = isSgArrayType(undertype);
23467 }
23468
23469 ROSE_ASSERT((!indices.empty()) && undertype);
23470 return std::make_pair(indices, undertype);
23471 }
23472
23474 std::vector<SgExpression*>
23475 get_C_array_dimensions_aux(const SgArrayType& arrtype, const VarrefBuilder& varrefBuilder)
23476 {
23477 namespace SB = SageBuilder;
23478
23479 std::pair<std::vector<SgExpression*>, SgType*> res = get_C_array_dimensions_aux(arrtype);
23480 const std::vector<SgExpression*>::iterator first = res.first.begin();
23481
23482 // if the first dimension was open, create the expression for it
23483 if (isSgNullExpression(*first))
23484 {
23485 // handle implicit first dimension for array initializers
23486 // for something like
23487 // int p[][2][3] = {{{ 1, 2, 3 }, { 4, 5, 6 }}}
23488 // we can calculate the first dimension as
23489 // sizeof( p ) / ( sizeof( int ) * 2 * 3 )
23490
23491 const std::vector<SgExpression*>::iterator aa = first+1;
23492 const std::vector<SgExpression*>::iterator zz = res.first.end();
23493
23494 SgExpression* sz_undertype = SB::buildSizeOfOp(res.second);
23495 SgExpression* denominator = std::accumulate(aa, zz, sz_undertype, create_mulop);
23496 SgSizeOfOp* sz_var = SB::buildSizeOfOp(varrefBuilder.get());
23497 SgExpression* sz = SB::buildDivideOp(sz_var, denominator);
23498
23499 std::swap(*first, sz);
23500 delete sz;
23501 }
23502
23503 return res.first;
23504 }
23505 }
23506
23507 std::vector<SgExpression*>
23509 {
23510 return get_C_array_dimensions_aux(arrtype).first;
23511 }
23512
23513 std::vector<SgExpression*>
23515 {
23516 return get_C_array_dimensions_aux(arrtype, varrefCreator(varref));
23517 }
23518
23519 std::vector<SgExpression*>
23521 {
23522 return get_C_array_dimensions_aux(arrtype, varrefCreator(initname));
23523 }
23524
23525// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23527 {
23528 public:
23529 set<unsigned int> sourceSequenceSet;
23530
23531 void visit ( SgNode* astNode );
23532 };
23533
23534// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23535void
23537 {
23538 Sg_File_Info* fileInfo = astNode->get_file_info();
23539 if (fileInfo != NULL)
23540 {
23541 unsigned int source_sequence_number = fileInfo->get_source_sequence_number();
23542#if 0
23543 printf ("In CollectSourceSequenceNumbers::visit(): source_sequence_number = %" PRIuPTR " \n",source_sequence_number);
23544#endif
23545 sourceSequenceSet.insert(source_sequence_number);
23546 }
23547 }
23548
23549// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23550set<unsigned int>
23552 {
23554
23555 traversal.traverse(astNode,preorder);
23556
23557 return traversal.sourceSequenceSet;
23558
23559 }
23560
23561/*Winnie, loop collapse, collapse nested for loops into one large for loop
23562 * return a SgExprListExp *, which will contain a list of SgVarRefExp * to variables newly created, inserted outside of the
23563 * loop scope, and used inside the loop scope.
23564 * If the target_loop comes with omp target directive, these variables should be added in map in clause in
23565 * transOmpCollpase(..) function in omp_lowering.cpp.
23566 *
23567 * The input loop pointer is changed to the generated collapsed loop after the transformation.
23568 *
23569 *
23570 * Loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
23571 *
23572 * to collapse two level of loops:
23573 * iteration_count_one= (ub1-lb1+1)%step1 ==0?(ub1-lb1+1)/step1: (ub1-lb1+1)/step1+1
23574 * iteration_count_two= (ub2-lb2+1)%step2 ==0?(ub2-lb2+1)/step2: (ub2-lb2+1)/step2+1
23575 * total_iteration_count = iteration_count_one * iteration_count_two
23576 *
23577 * Decide incremental/decremental loop by checking operator of test statement(ub), <=/>=, this is done in isCanonicalForLoop()
23578 *
23579 * Example 1:
23580 * for (int i=lb2;i<ub2;i+=inc2) //incremental
23581 * {
23582 * for (int j=lb1;j>ub1;i+=inc1) //decremental
23583 * {
23584 * for (int l=lb2;l<ub2;l+=inc2) //incremental
23585 * {
23586 * a[i][j][l]=i+j+l;
23587 * }
23588 * }
23589 * }
23590 *
23591 *==> translated output code ==>
23592 * int i_nom_1_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23593 * 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;
23594 * int l_nom_3_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23595 * int final_total_iters = 1 * i_nom_1_total_iters* j_nom_2_total_iters* l_nom_3_total_iters;
23596 * int i_nom_1_interval = j_nom_2_total_iters * (l_nom_3_total_iters* 1);
23597 * int j_nom_2_interval = l_nom_3_total_iters * 1;
23598 * int l_nom_3_interval = 1;
23599 *
23600 * for (int new_index = 0; new_index <= final_total_iters- 1; new_index += 1) {
23601 * i_nom_1 = new_index / i_nom_1_interval* inc2 + lb2;
23602 * int i_nom_1_remainder = new_index % i_nom_1_interval;
23603 * j_nom_2 = -(i_nom_1_remainder / j_nom_2_interval* (inc1 * -1)) + lb1;
23604 * l_nom_3 = i_nom_1_remainder % j_nom_2_interval* inc2 + lb2;
23605 * a[i_nom_1][j_nom_2][l_nom_3] = i_nom_1 + j_nom_2 + l_nom_3;
23606 * }
23607 *
23608 * Example 2 with concrete numbers:
23609 *
23610 * // collapse the following two level of for loops:
23611 * for (i=1; i<=9; i+=1) //incremental for loop
23612 * {
23613 * for(j=10; j>=1; j+=-2) //decremental for loop
23614 * {
23615 * a[i][j]=i+j;
23616 * }
23617 * }
23618 * // it becomes
23619 * // total iteration count = ((9 - 1 + 1)/1) * ((10 - 1 + 1)/2) = 45
23620 * // ub = 45
23621 * // lb = 0
23622 *
23623 * int i_nom_1_total_iters = 9;
23624 * int j_nom_1_total_iters = 5; // 10 % (-2 * -1) == 0 ? 10 / (-2 * -1) : 10 /(-2 * -1) + 1;
23625 * int final_total_iters = 45; // i_nom_1_total_iters * j_nom_2_total_iters;
23626 *
23627 * int i_nom_1_interval = 5;
23628 *
23629 * for (z=0; z<=44; z+=1)
23630 * {
23631 * i_nom_1 = z / 5 + 1;
23632 * j_nom_2 = -(z % 5 * 2) + 10;
23633 * a[i_nom_1][j_nom_2]=i_nom_1 + j_nom_2;
23634 * }
23635 * // for the generated loop, a few compiler generated variables are introduced
23636 * final_total_iters for the collapsed loop
23637 * i_interval for each of the n-1 loops
23638 **
23639*/
23640
23641#ifndef USE_ROSE
23643{
23644#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23645 //Handle 0 and 1, which means no collapsing at all
23646 if (collapsing_factor <= 1)
23647 return NULL;
23648
23649 SgExprListExp * new_var_list = buildExprListExp(); //expression list contains all the SgVarRefExp * to variables that need to be added in the mapin clause
23650
23651 /*
23652 *step 1: grab the target loops' header information
23653 */
23654 SgForStatement *& target_loop = loop;
23655
23656 // we use global scope to help generate unique variable name later
23657 // local scope-based unique names may cause conflicts if the declarations are moved around (in OpenMP target data promotion)
23658 SgGlobal* global_scope = getGlobalScope (loop);
23659 ROSE_ASSERT (global_scope != NULL);
23660 SgInitializedName** ivar = new SgInitializedName*[collapsing_factor];
23661 SgExpression** lb = new SgExpression*[collapsing_factor];
23662 SgExpression** ub = new SgExpression*[collapsing_factor];
23663 SgExpression** step = new SgExpression*[collapsing_factor];
23664 SgStatement** orig_body = new SgStatement*[collapsing_factor];
23665
23666 SgExpression** total_iters = new SgExpression*[collapsing_factor]; //Winnie, the real iteration counter in each loop level
23667 SgExpression** interval = new SgExpression*[collapsing_factor]; //Winnie, this will be used to calculate i_nom_1_remainder
23668 bool *isPlus = new bool[collapsing_factor]; //Winnie, a flag indicates incremental or decremental for loop
23669
23670
23671 //Winnie, get loops info first
23672 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(target_loop,V_SgForStatement);
23673 ROSE_ASSERT(loops.size()>=collapsing_factor);
23674
23675 SgForStatement* temp_target_loop = NULL;
23676 SgExpression* temp_range_exp = NULL; //Raw iteration range
23677 SgExpression* temp_range_d_step_exp = NULL; //temp_range_exp / step[i]
23678 SgExpression* temp_condition_1 = NULL; //Check whether temp_range_exp % step[i] == 0
23679 SgExpression* temp_total_iter = NULL;
23680 SgExpression* ub_exp = buildIntVal(1); //Winnie, upbound
23681
23682 /*
23683 * get lb, ub, step information for each level of the loops
23684 * ub_exp is the final iterantion range(starting from 0) after loop collapsing
23685 * total_iters[i], = (ub[i] - lb[i] + 1)/step[i] is the total iter num in each level of loop before loop collapsing
23686 */
23687
23688 SgStatement* parent = isSgStatement(getScope(target_loop)->get_parent()); //Winnie, the scope that include target_loop
23689 ROSE_ASSERT(getScope(target_loop)->get_parent()!= NULL);
23690
23691 SgScopeStatement* scope = isSgScopeStatement(parent); //Winnie, the scope that include target_loop
23692
23693 while(scope == NULL)
23694 {
23695 parent = isSgStatement(parent->get_parent());
23696 scope = isSgScopeStatement(parent);
23697 }
23698
23699 SgStatement* insert_target = findLastDeclarationStatement(scope);
23700 if (insert_target != NULL)
23701 insert_target = getNextStatement(insert_target);
23702 else
23703 insert_target = getFirstStatement(scope);
23704
23705 ROSE_ASSERT(scope != NULL);
23706
23707
23708 for(size_t i = 0; i < collapsing_factor; i ++)
23709 {
23710 temp_target_loop = loops[i];
23711
23712 // normalize the target loop first // adjust to numbering starting from 0
23713 forLoopNormalization(temp_target_loop);
23714
23715 if (!isCanonicalForLoop(temp_target_loop, &ivar[i], &lb[i], &ub[i], &step[i], &orig_body[i], &isPlus[i]))
23716 {
23717 cerr<<"Error in SageInterface::loopCollapsing(): target loop is not canonical."<<endl;
23718 dumpInfo(target_loop);
23719
23720 // release memory
23721 delete[] ivar;
23722 delete[] lb;
23723 delete[] ub;
23724 delete[] step;
23725 delete[] orig_body;
23726 delete[] total_iters;
23727 delete[] interval;
23728 delete[] isPlus;
23729
23730 return NULL;
23731 }
23732
23733 ROSE_ASSERT(ivar[i]&& lb[i] && ub[i] && step[i]);
23734
23735
23736//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]
23737 if(isPlus[i] == true)
23738 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(ub[i]), copyExpression(lb[i])), buildIntVal(1));
23739 else{
23740 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(lb[i]), copyExpression(ub[i])), buildIntVal(1));
23741 step[i] = buildMultiplyOp(step[i], buildIntVal(-1));
23742 }
23743 temp_range_d_step_exp = buildDivideOp(temp_range_exp,copyExpression(step[i]));//(ub[i]-lb[i]+1)/step[i]
23744
23745 temp_condition_1 = buildEqualityOp(buildModOp(copyExpression(temp_range_exp),copyExpression(step[i])),buildIntVal(0)); //(ub[i]-lb[i]+1)%step[i] ==0
23746
23747 temp_total_iter = buildConditionalExp(temp_condition_1,temp_range_d_step_exp, buildAddOp(copyExpression(temp_range_d_step_exp),buildIntVal(1)));
23748
23749 //build variables to store iteration numbers in each loop, simplify the calculation of "final_total_iters"
23750 //insert the new variable (store real iteration number of each level of the loop) before the target loop
23751 string iter_var_name= "_total_iters";
23752 //iter_var_name = ivar[i]->get_name().getString() + iter_var_name + generateUniqueName(temp_total_iter, false);
23753 iter_var_name = "__"+ivar[i]->get_name().getString() + iter_var_name+ generateUniqueVariableName (global_scope,"");
23754 SgVariableDeclaration* total_iter = buildVariableDeclaration(iter_var_name, buildIntType(), buildAssignInitializer(temp_total_iter, buildIntType()), scope);
23755 insertStatementBefore(insert_target, total_iter);
23756 constantFolding (total_iter);
23757 total_iters[i] = buildVarRefExp(iter_var_name, scope);
23758 ub_exp = buildMultiplyOp(ub_exp, total_iters[i]); //Winnie, build up the final iteration range
23759 }
23760
23761
23762 /*
23763 * step 2: build new variables (new_index, final_total_iters, remainders...) for the new loop
23764 */
23765
23766 /*Winnie, build another variable to store final total iteration counter of the loop after collapsing*/
23767 //string final_iter_counter_name = "final_total_iters" + generateUniqueName(ub_exp, false);
23768 string final_iter_counter_name = "__final_total_iters" + generateUniqueVariableName(global_scope,"");
23769 SgVariableDeclaration * final_total_iter = buildVariableDeclaration(final_iter_counter_name, buildIntType(), buildAssignInitializer(copyExpression(ub_exp), buildIntType()), scope);
23770 insertStatementBefore(insert_target, final_total_iter);
23771 ub_exp = buildVarRefExp(final_iter_counter_name, scope);
23772 new_var_list->append_expression(isSgVarRefExp(ub_exp));
23773
23774 /*Winnie, interval[i] will make the calculation of remainders simpler*/
23775 for(unsigned int i = 0; i < collapsing_factor; i++)
23776 {
23777 interval[i] = buildIntVal(1);
23778 for(unsigned int j = collapsing_factor - 1; j > i; j--)
23779 {
23780 interval[i] = buildMultiplyOp(total_iters[j], interval[i]);
23781 }
23782 //string interval_name = ivar[i]->get_name().getString() + "_interval" + generateUniqueName(interval[i], false);
23783 string interval_name = "__"+ ivar[i]->get_name().getString() + "_interval" + generateUniqueVariableName (global_scope,"");
23784 SgVariableDeclaration* temp_interval = buildVariableDeclaration(interval_name, buildIntType(), buildAssignInitializer(copyExpression(interval[i]), buildIntType()), scope);
23785 insertStatementBefore(insert_target, temp_interval);
23786 interval[i] = buildVarRefExp(interval_name, scope);
23787 new_var_list->append_expression(isSgVarRefExp(interval[i]));
23788 }
23789
23790
23791 //Winnie, starting from here, we are dealing with variables inside loop, update scope
23792 scope = getScope(target_loop);
23793
23794 //Winnie, init statement of the loop header, copy the lower bound, we are dealing with a range, the lower bound should always be "0"
23795 //Winnie, declare a brand new var as the new index
23796 string ivar_name = "__collapsed_index"+ generateUniqueVariableName (global_scope,"");
23797 ROSE_ASSERT(insert_target != NULL);
23798 SgVariableDeclaration* new_index_decl = buildVariableDeclaration(ivar_name, buildIntType(), NULL, insert_target->get_scope());
23799 SgVariableSymbol * collapsed_index_symbol = getFirstVarSym (new_index_decl);
23800 insertStatementBefore(insert_target, new_index_decl);
23801 SgVarRefExp * clps_index_ref = buildVarRefExp(collapsed_index_symbol);
23802 new_var_list->append_expression(clps_index_ref);
23803
23804// SgVariableDeclaration* init_stmt = buildVariableDeclaration(ivar_name, buildIntType(), buildAssignInitializer(buildIntVal(0), buildIntType()), scope);
23805
23806
23807 SgBasicBlock* body = isSgBasicBlock(deepCopy(temp_target_loop->get_loop_body())); // normalized loop has a BB body
23808 ROSE_ASSERT(body != NULL);
23809 SgExpression* new_exp = NULL;
23810 SgExpression* remain_exp_temp = buildVarRefExp(ivar_name, scope);
23811 std::vector<SgStatement*> new_stmt_list;
23812
23813 SgExprStatement* assign_stmt = NULL;
23814
23815 /* Winnie
23816 * express old iterator variables (i_norm, j_norm ...) with new_index,
23817 * new_exp, create new expression for each of the iterators
23818 * i_nom_1 = (_new_index / interval[0])*step[0] + lb[0]
23819 * i_nom_1_remain_value = (_new_index % interval[0])*step[0] + lb[0], create a new var to store remain value
23820 * create a new var to store total_iters[i]
23821 */
23822 for(unsigned int i = 0; i < collapsing_factor - 1; i ++)
23823 {
23824 if(isPlus[i] == true)
23825 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]
23826 else
23827 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
23828
23829 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[i], scope), copyExpression(new_exp));
23830 new_stmt_list.push_back(assign_stmt);
23831 remain_exp_temp = buildModOp((remain_exp_temp), copyExpression(interval[i]));
23832
23833 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
23834 string remain_var_name= "_remainder";
23835 remain_var_name = "__"+ ivar[i]->get_name().getString() + remain_var_name;
23836 SgVariableDeclaration* loop_index_decl = buildVariableDeclaration(remain_var_name, buildIntType(), buildAssignInitializer(remain_exp_temp, buildIntType()), scope);
23837 remain_exp_temp = buildVarRefExp(remain_var_name, scope);
23838 new_stmt_list.push_back(loop_index_decl);
23839 }
23840 new_exp = NULL;
23841 }
23842
23843//Winnie, the inner most loop, iter
23844 if(isPlus[collapsing_factor - 1] == true)
23845 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1]), lb[collapsing_factor - 1]));
23846 else
23847 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMinusOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1])), lb[collapsing_factor - 1]));
23848 new_stmt_list.push_back(assign_stmt);
23849 prependStatementList(new_stmt_list, body);
23850
23851 /*
23852 * step 3: build the new loop, new step is always 1, disregard value of step[i]
23853 */
23854 SgExpression* incr_exp = buildPlusAssignOp(buildVarRefExp(ivar_name, scope), buildIntVal(1));
23855
23856 //Winnie, build the new conditional expression/ub
23857 SgExprStatement* cond_stmt = NULL;
23858 ub_exp = buildSubtractOp(ub_exp, buildIntVal(1));
23859 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar_name,scope),copyExpression(ub_exp)));
23860 ROSE_ASSERT(cond_stmt != NULL);
23861
23862 SgForStatement* new_loop = buildForStatement(buildAssignStatement(clps_index_ref, buildIntVal(0)), cond_stmt,incr_exp, body); //Winnie, add in the new block!
23863 new_loop->set_parent(scope); //TODO: what's the correct parent?
23864
23865 replaceStatement(target_loop, new_loop);
23866
23867 target_loop = new_loop; //Winnie, so that transOmpLoop() can work on the collapsed loop
23868 // constant folding for the transformed AST
23869 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
23870
23871 delete [] ivar;
23872 delete [] lb;
23873 delete [] ub;
23874 delete [] step;
23875 delete [] orig_body;
23876 delete [] total_iters;
23877 delete [] interval;
23878 delete [] isPlus;
23879
23880 #endif
23881
23882 return new_var_list;
23883}
23884
23885
23886
23887bool
23889 {
23890 // DQ (3/4/2014): Added support for testing two trees for equivalents using the AST iterators.
23891
23892#ifndef USE_CMAKEx
23893 // DQ (3/8/2014): Make this conditionally compiled based on when CMake is not used because the libraries are not configured yet.
23894
23895 // This is AST container for the ROSE AST that will provide an iterator.
23896 // We want two iterators (one for the copy of the snippet and one for the
23897 // original snippet so that we can query the original snippet's AST
23898 // as we process each IR node of the AST for the copy of the snippet.
23899 // Only the copy of the snippet is inserted into the target AST.
23900 RoseAst ast_of_copy(tree1);
23901 RoseAst ast_of_original(tree2);
23902
23903 // printf ("ast_of_copy.size() = %" PRIuPTR " \n",ast_of_copy.size());
23904
23905 // Build the iterators so that we can increment thorugh both ASTs one IR node at a time.
23906 RoseAst::iterator i_copy = ast_of_copy.begin();
23907 RoseAst::iterator i_original = ast_of_original.begin();
23908
23909 // Iterate of the copy of the snippet's AST.
23910 while (i_copy != ast_of_copy.end())
23911 {
23912#if 0
23913 printf ("*i_copy = %p = %s \n",*i_copy,(*i_copy)->class_name().c_str());
23914 printf ("*i_original = %p = %s \n",*i_original,(*i_original)->class_name().c_str());
23915#endif
23916 // DQ (2/28/2014): This is a problem for some of the test codes (TEST store/load heap string [test7a] and [test7a])
23917 // ROSE_ASSERT((*i_copy)->variantT() == (*i_original)->variantT());
23918 if ((*i_copy)->variantT() != (*i_original)->variantT())
23919 {
23920#if 0
23921 printf ("ERROR: return from SageInterface::isStructurallyEquivalentAST(): (*i_copy)->variantT() != (*i_original)->variantT() \n");
23922#endif
23923#if 0
23924 printf ("Making this an error! \n");
23925 ROSE_ABORT();
23926#endif
23927 return false;
23928 }
23929
23930 i_copy++;
23931
23932 // Verify that we have not reached the end of the ast for the original (both the
23933 // copy and the original are the same structurally, and thus the same size).
23934 ROSE_ASSERT(i_original != ast_of_original.end());
23935 i_original++;
23936 }
23937
23938 // We have reached the end of both ASTs.
23939 ROSE_ASSERT(i_copy == ast_of_copy.end() && i_original == ast_of_original.end());
23940#endif
23941
23942 return true;
23943 }
23944
23945
23946#endif
23947
23949 SgForStatement * for_loop,
23950 SgVariableSymbol * & iterator,
23951 SgExpression * & lower_bound,
23952 SgExpression * & upper_bound,
23953 SgExpression * & stride
23954) {
23957
23958 iterator = NULL;
23959 lower_bound = NULL;
23960 upper_bound = NULL;
23961 stride = NULL;
23962
23963 SgForInitStatement * for_init_stmt = for_loop->get_for_init_stmt();
23964 const std::vector<SgStatement *> & init_stmts = for_init_stmt->get_init_stmt();
23965 assert(init_stmts.size() == 1);
23966 SgExprStatement * init_stmt = isSgExprStatement(init_stmts[0]);
23967 assert(init_stmt != NULL);
23968 SgExpression * init = init_stmt->get_expression();
23969
23970 SgAssignOp * assign_init = isSgAssignOp(init);
23971 assert(assign_init != NULL);
23972 SgVarRefExp * iterator_init_ref = isSgVarRefExp(assign_init->get_lhs_operand_i());
23973 assert(iterator_init_ref != NULL);
23974 iterator = iterator_init_ref->get_symbol();
23975 assert(iterator != NULL);
23976 lower_bound = assign_init->get_rhs_operand_i();
23977
23978 SgExprStatement * test_stmt = isSgExprStatement(for_loop->get_test());
23979 assert(test_stmt != NULL);
23980 SgExpression * test = test_stmt->get_expression();
23981 SgBinaryOp * bin_test = isSgBinaryOp(test);
23982 assert(bin_test);
23983
23984 SgExpression * lhs_exp = bin_test->get_lhs_operand_i();
23985 while (isSgCastExp(lhs_exp)) lhs_exp = ((SgCastExp *)lhs_exp)->get_operand_i();
23986 SgVarRefExp * lhs_var_ref = isSgVarRefExp(lhs_exp);
23987 bool lhs_it = (lhs_var_ref != NULL) && (lhs_var_ref->get_symbol() == iterator);
23988
23989 SgExpression * rhs_exp = bin_test->get_rhs_operand_i();
23990 while (isSgCastExp(rhs_exp)) rhs_exp = ((SgCastExp *)rhs_exp)->get_operand_i();
23991 SgVarRefExp * rhs_var_ref = isSgVarRefExp(rhs_exp);
23992#ifndef NDEBUG
23993 bool rhs_it = (rhs_var_ref != NULL) && (rhs_var_ref->get_symbol() == iterator);
23994
23995// DQ (4/21/2016): Replacing use of bitwise xor with something more approriate for logical types.
23996// Note that the xor logica operator does not exist in C/C++ and that this is a case of using the
23997// bitwise xor operator on boolean values (not a great idea). Note that logical "a xor b" is
23998// equivalent to "!a != !b" the use of "!" only make sure that the "!=" is applied to a boolean
23999// value. Since these are boolean typed values we can use "a != b", directly.
24000// assert(lhs_it xor rhs_it);
24001 assert(lhs_it != rhs_it);
24002#endif
24003
24004 upper_bound = lhs_it ? bin_test->get_rhs_operand_i() : bin_test->get_lhs_operand_i();
24005
24006 bool inclusive;
24007 bool reversed;
24008
24009 switch (test->variantT()) {
24010 case V_SgGreaterOrEqualOp:
24011 inclusive = lhs_it;
24012 reversed = lhs_it;
24013 break;
24014 case V_SgGreaterThanOp:
24015 inclusive = !lhs_it;
24016 reversed = lhs_it;
24017 break;
24018 case V_SgLessOrEqualOp:
24019 inclusive = lhs_it;
24020 reversed = !lhs_it;
24021 break;
24022 case V_SgLessThanOp:
24023 inclusive = !lhs_it;
24024 reversed = !lhs_it;
24025 break;
24026 case V_SgEqualityOp:
24027 case V_SgNotEqualOp:
24028 default:
24029 ROSE_ABORT();
24030 }
24031
24032 SgExpression * increment = for_loop->get_increment();
24033 switch (increment->variantT()) {
24034 case V_SgPlusPlusOp:
24035 assert(!reversed);
24036 stride = SageBuilder::buildIntVal(1);
24037 break;
24038 case V_SgMinusMinusOp:
24039 assert(reversed);
24040 stride = SageBuilder::buildIntVal(-1);
24041 break;
24042 case V_SgPlusAssignOp:
24043 {
24044 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
24045#ifndef NDEBUG
24046 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
24047 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
24048#endif
24049 stride = bin_op->get_rhs_operand_i();
24050 break;
24051 }
24052 case V_SgMinusAssignOp:
24053 {
24054 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
24055#ifndef NDEBUG
24056 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
24057 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
24058#endif
24059 stride = bin_op->get_rhs_operand_i();
24060 break;
24061 }
24062 case V_SgAssignOp:
24063 {
24064 SgAssignOp * assign_op = (SgAssignOp *)increment;
24065#ifndef NDEBUG
24066 SgVarRefExp * inc_assign_lhs = isSgVarRefExp(assign_op->get_lhs_operand_i());
24067 assert(inc_assign_lhs != NULL && inc_assign_lhs->get_symbol() == iterator);
24068#endif
24069 SgBinaryOp * inc_assign_rhs = isSgBinaryOp(assign_op->get_rhs_operand_i());
24070 assert(inc_assign_rhs != NULL);
24071 SgVarRefExp * inc_assign_rhs_lhs = isSgVarRefExp(inc_assign_rhs->get_lhs_operand_i());
24072 if (inc_assign_rhs_lhs != NULL && inc_assign_rhs_lhs->get_symbol() == iterator)
24073 stride = inc_assign_rhs->get_rhs_operand_i();
24074 SgVarRefExp * inc_assign_rhs_rhs = isSgVarRefExp(inc_assign_rhs->get_rhs_operand_i());
24075 if (inc_assign_rhs_rhs != NULL && inc_assign_rhs_rhs->get_symbol() == iterator)
24076 stride = inc_assign_rhs->get_lhs_operand_i();
24077 break;
24078 }
24079 default:
24080 ROSE_ABORT();
24081 }
24082
24083 // DQ (7/19/2015): Added braces to avoid compiler warning about ambigious "else" case.
24084 if (!inclusive)
24085 {
24086 if (reversed)
24087 upper_bound = SageBuilder::buildAddOp(upper_bound, SageBuilder::buildIntVal(1));
24088 else
24089 upper_bound = SageBuilder::buildSubtractOp(upper_bound, SageBuilder::buildIntVal(1));
24090 }
24091
24092 return true;
24093}
24094
24095//------------------------------------------------------------------------------
24096#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
24097//------------------------------------------------------------------------------
24098
24103 jstring temp_directory = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(::currentJavaTraversalClass, Rose::Frontend::Java::Ecj::getTempDirectoryMethod);
24104
24105 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_directory, NULL);
24106 ROSE_ASSERT(utf8);
24107 string directory_name = utf8;
24108 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_directory, utf8);
24109
24110 list<string> sourcepath = project -> get_Java_sourcepath();
24111 sourcepath.push_back(directory_name); // push it in the back because it should have lower priority
24112 project -> set_Java_sourcepath(sourcepath);
24113
24114 return directory_name;
24115}
24116
24117
24121void SageInterface::destroyTempDirectory(string directory_name) {
24122 string command = string("rm -fr ") + directory_name;
24123 int status = system(command.c_str());
24124 ROSE_ASSERT(status == 0);
24125}
24126
24127
24131SgFile* SageInterface::processFile(SgProject *project, string filename, bool unparse /* = false */) {
24132 //
24133 // Set up the new source file for processing "a la Rose".
24134 //
24135 project -> get_sourceFileNameList().push_back(filename);
24136 Rose_STL_Container<std::string> arg_list = project -> get_originalCommandLineArgumentList();
24137 arg_list.push_back(filename);
24138 Rose_STL_Container<string> fileList = CommandlineProcessing::generateSourceFilenames(arg_list, false);
24139 CommandlineProcessing::removeAllFileNamesExcept(arg_list, fileList, filename);
24140 int error_code = 0; // need this because determineFileType takes a reference "error_code" argument.
24141 SgFile *file = determineFileType(arg_list, error_code, project);
24142 SgSourceFile *sourcefile = isSgSourceFile(file);
24143 ROSE_ASSERT(sourcefile);
24144 sourcefile -> set_parent(project);
24145
24146 //
24147 // Insert the file into the list of files in the project.
24148 //
24149 project -> get_fileList_ptr() -> get_listOfFiles().push_back(sourcefile);
24150 ROSE_ASSERT(sourcefile == isSgSourceFile((*project)[filename]));
24151
24152 sourcefile -> build_Java_AST(arg_list, project -> get_originalCommandLineArgumentList());
24153
24154 if (! unparse) { // if we are not supposed to unparse this file,
24155 project -> get_fileList_ptr() -> get_listOfFiles().pop_back(); // remove it from the list of files in the project
24156 ROSE_ASSERT(sourcefile != isSgSourceFile((*project)[filename]));
24157 }
24158
24159 // DQ (7/2/2020): Added assertion (fails for snippet tests).
24160 ROSE_ASSERT(file->get_preprocessorDirectivesAndCommentsList() != NULL);
24161
24162 return file;
24163}
24164
24165
24170string SageInterface::preprocessPackage(SgProject *project, string package_name) {
24171 string command = "package " + package_name + ";";
24172
24173 //
24174 // Call the Java side to create an input file with the relevant package statement; translate the file and return the file name.
24175 //
24176 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24177 Rose::Frontend::Java::Ecj::createTempFileMethod,
24178 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
24179
24180 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
24181 ROSE_ASSERT(utf8);
24182 string filename = (string) utf8;
24183 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
24184
24185 processFile(project, filename); // translate the file
24186
24187 return package_name;
24188}
24189
24190
24195string SageInterface::preprocessImport(SgProject *project, string import_string) {
24196 string command = "import " + import_string + ";";
24197
24198 //
24199 // Call the Java side to create an input file with the relevant import statement.
24200 //
24201 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24202 Rose::Frontend::Java::Ecj::createTempFileMethod,
24203 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
24204
24205 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
24206 ROSE_ASSERT(utf8);
24207 string filename = (string) utf8;
24208 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
24209
24210 processFile(project, filename); // translate the file
24211
24212 return import_string;
24213}
24214
24215
24220SgFile* SageInterface::preprocessCompilationUnit(SgProject *project, string file_name, string file_content, bool unparse /* true */) {
24221 //
24222 // Call the Java side to create an input file with the relevant import statement.
24223 //
24224 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24225 Rose::Frontend::Java::Ecj::createTempNamedFileMethod,
24226 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_name.c_str()),
24227 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_content.c_str()));
24228
24229 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
24230 ROSE_ASSERT(utf8);
24231 string filename = (string) utf8;
24232 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
24233
24234 return processFile(project, filename, unparse); // translate the file and unparse it, if requested (unparse=true is the default).
24235}
24236
24237
24242 ROSE_ASSERT(scope);
24243 SgClassDefinition *package_definition = NULL;
24244 for (int index = 0, length = package_name.size(); index < length; index++) {
24245 int n;
24246 for (n = index; n < length; n++) {
24247 if (package_name[n] == '.') {
24248 break;
24249 }
24250 }
24251 string name = package_name.substr(index, n - index);
24252
24253 SgClassSymbol *package_symbol = scope -> lookup_class_symbol(name);
24254 if (package_symbol == NULL) { // package not found?
24255 return NULL;
24256 }
24257
24258 SgJavaPackageDeclaration *package_declaration = isSgJavaPackageDeclaration(package_symbol -> get_declaration() -> get_definingDeclaration());
24259 ROSE_ASSERT(package_declaration);
24260 package_definition = package_declaration -> get_definition();
24261 ROSE_ASSERT(package_definition);
24262 scope = package_definition;
24263
24264 index = n;
24265 }
24266
24267 return package_definition;
24268}
24269
24270
24274SgClassDefinition *SageInterface::findOrInsertJavaPackage(SgProject *project, string package_name, bool create_directory /* = false */) {
24275 SgGlobal *global_scope = project -> get_globalScopeAcrossFiles();
24276 SgClassDefinition *package_definition = findJavaPackage(global_scope, package_name);
24277 if (package_definition == NULL) { // try again after loading the package
24278 preprocessPackage(project, package_name);
24279
24280 //
24281 // If requested, Create the directory associated with this package_name.
24282 //
24283 if (create_directory) {
24284 Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24285 Rose::Frontend::Java::Ecj::createTempNamedDirectoryMethod,
24286 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(package_name.c_str()));
24287 }
24288
24289 package_definition = findJavaPackage(global_scope, package_name);
24290 }
24291
24292 return package_definition;
24293}
24294
24299 ROSE_ASSERT(package_definition);
24300 SgClassSymbol *class_symbol = package_definition -> lookup_class_symbol(class_name);
24301 SgClassDeclaration *class_declaration = (class_symbol == NULL
24302 ? NULL
24303 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24304 if ((! class_declaration) || (! class_declaration -> attributeExists("complete"))) { // class not available in the scope
24305 string qualified_name = package_definition -> get_qualified_name().getString() + "." + class_name;
24306 preprocessImport(project, qualified_name);
24307 class_symbol = package_definition -> lookup_class_symbol(class_name);
24308 }
24309
24310 class_declaration = (class_symbol == NULL
24311 ? NULL
24312 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24313
24314 return class_declaration;
24315}
24316
24317
24321SgClassDeclaration *SageInterface::findOrImportJavaClass(SgProject *project, string package_name, string class_name) {
24322 return findOrImportJavaClass(project, findOrInsertJavaPackage(project, package_name, false), class_name);
24323}
24324
24325
24330 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24331 ROSE_ASSERT(class_declaration);
24332 SgClassDefinition *scope = isSgClassDefinition(class_declaration -> get_scope());
24333 while (scope && (! isSgJavaPackageDeclaration(scope -> get_parent()))) {
24334 class_declaration = isSgClassDeclaration(scope -> get_parent());
24335 ROSE_ASSERT(class_declaration);
24336 scope = isSgClassDefinition(class_declaration -> get_scope());
24337 }
24338
24339 if (! scope) { // a local type !!!
24340 return NULL;
24341 }
24342
24343 string class_name = class_declaration -> get_name().getString();
24344 return findOrImportJavaClass(project, scope, class_name);
24345}
24346
24347
24352 ROSE_ASSERT(class_definition);
24354 ROSE_ASSERT(type_list);
24355 SgArrayType *string_array_type = getUniqueJavaArrayType(Rose::Frontend::Java::StringClassType, 1);
24356 ROSE_ASSERT(string_array_type);
24357 type_list -> append_argument(string_array_type);
24358
24359 // DQ (1/11/2020): Fixing support for C++11 l-value and r-value reference modifiers for member functions.
24360 // SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, 0);
24361 SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, /* mfunc_specifier */ 0);
24362
24363 SgFunctionSymbol *method_symbol = class_definition -> lookup_function_symbol("main", member_function_type);
24364 delete type_list;
24365 return (method_symbol == NULL ? NULL : isSgMemberFunctionDeclaration(method_symbol -> get_declaration()));
24366}
24367
24368
24373 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24374 ROSE_ASSERT(class_declaration);
24375 SgClassDefinition *class_definition = class_declaration -> get_definition();
24376 return findJavaMain(class_definition);
24377}
24378
24379//------------------------------------------------------------------------------
24380#endif // ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
24381//------------------------------------------------------------------------------
24382
24384// Essentially replace variable a with b.
24386{
24387 ROSE_ASSERT (old_sym != NULL);
24388 ROSE_ASSERT (new_sym != NULL);
24389 ROSE_ASSERT (old_sym != new_sym);
24390 ROSE_ASSERT (scope != NULL);
24391
24392 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVarRefExp);
24393 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
24394 {
24395 SgVarRefExp *vRef = isSgVarRefExp(*i);
24396 if (vRef->get_symbol() == old_sym)
24397 vRef->set_symbol(new_sym);
24398 }
24399}
24400
24401
24402// 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.
24407bool
24409 {
24410 bool result = true;
24411
24412 bool includingSelf = false;
24413 SgSourceFile* sourceFile = getEnclosingSourceFile(stmt,includingSelf);
24414
24415 if (sourceFile == NULL)
24416 {
24417 printf ("In SageInterface::statementCanBeTransformed(): sourceFile not found \n");
24418 }
24419
24420 // I think we can assert this!
24421 ROSE_ASSERT(sourceFile != NULL);
24422
24423 if (sourceFile != NULL && sourceFile->get_unparse_tokens() == true && sourceFile->get_unparseHeaderFiles() == true)
24424 {
24425 // Need to look up the source file name, find the SgIncludeFile, and check if statements from this file can be transformed.
24426 // 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.
24427 string source_filename = stmt->getFilenameString();
24428#if 0
24429 printf ("In SageInterface::statementCanBeTransformed(): source_filename = %s \n",source_filename.c_str());
24430 printf (" --- Rose::includeFileMapForUnparsing.size() = %zu \n",Rose::includeFileMapForUnparsing.size());
24431#endif
24432
24433 // DQ (11/5/2019): Using the edg_include_file_map instead (constructed in EDG/ROSE translation).
24434 if (EDG_ROSE_Translation::edg_include_file_map.find(source_filename) != EDG_ROSE_Translation::edg_include_file_map.end())
24435 {
24436 SgIncludeFile* include_file = EDG_ROSE_Translation::edg_include_file_map[source_filename];
24437 ROSE_ASSERT(include_file != NULL);
24438#if 0
24439 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");
24440#endif
24441 if (include_file->get_can_be_supported_using_token_based_unparsing() == false)
24442 {
24443#if 0
24444 printf ("NOTE: Transformations of this statement cannot be supported using the header file unparsing with token unparsing options! \n");
24445#endif
24446 result = false;
24447 }
24448 }
24449 else
24450 {
24451 // DQ (5/13/2021): I think that the default (returing true) will work well.
24452 // This is likely just the original input source file (not a header file).
24453#if 0
24454 printf ("Not found in Rose::includeFileMapForUnparsing: source_filename = %s \n",source_filename.c_str());
24455#endif
24456#if 0
24457 printf ("Exiting as a test! \n");
24458 ROSE_ABORT();
24459#endif
24460 }
24461
24462#if 0
24463 printf ("Error: In statementCanBeTransformed(): this might be an issue! \n");
24464 ROSE_ABORT();
24465#endif
24466 }
24467
24468 return result;
24469 }
24470
24471
24472//Note: this function is no longer used by decl move tool: we use copy and insert instead to support moving to multiple scopes
24475{
24476 ROSE_ASSERT (decl!= NULL);
24477 ROSE_ASSERT (target_scope != NULL);
24478 ROSE_ASSERT (target_scope != decl->get_scope());
24479
24480#if 0 // at this stage, we focus on legal move only, any scope adjustment should be done earlier!
24481 // Special handling for If-Stmt, may need to climb up one level of scope when:
24482 // two bodies of if uses the same variable, but cannot be pushed down into each body.
24483 // If-stmt will be the innermost common scope for the variable.
24484 // But we should not move the declaration to if-stmt. We can only move it to the parent scope of if-stmt.
24485 if (isSgIfStmt (target_scope))
24486 {
24487 target_scope = SageInterface::getEnclosingScope (target_scope, false);
24488 if (target_scope == )
24489 }
24490# endif
24491
24492 // Move the declaration
24493 //TODO: consider another way: copy the declaration, insert the copy, replace varRefExp, and remove (delete) the original declaration
24495
24496 switch (target_scope->variantT())
24497 {
24498 case V_SgBasicBlock:
24499 {
24500 SageInterface::prependStatement (decl, target_scope);
24501 break;
24502 }
24503#if 0 // this check should be done earlier before any side effects can happen
24504 case V_SgIfStmt:
24505 {
24506 // adjust to parent scope of if-stmt
24507 break;
24508 }
24509#endif
24510 case V_SgForStatement:
24511 {
24512 // we move int i; to be for (int i=0; ...);
24513 SgForStatement* stmt = isSgForStatement (target_scope);
24514 ROSE_ASSERT(stmt != NULL);
24515 SgStatementPtrList& stmt_list = stmt->get_init_stmt();
24516 // Try to match a pattern like for (i=0; ...) here
24517 // assuming there is only one assignment like i=0
24518 // We don't yet handle more complex cases
24519 if (stmt_list.size() !=1)
24520 {
24521 cerr<<"Error in moveVariableDeclaration(): only single init statement is handled for SgForStatement now."<<endl;
24522 ROSE_ASSERT (stmt_list.size() ==1);
24523 }
24524 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
24525 ROSE_ASSERT (exp_stmt != NULL);
24526 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
24527 ROSE_ASSERT (assign_op != NULL);
24528
24529 // remove the existing i=0; preserve its right hand operand
24531 stmt_list.clear();
24532 SageInterface::deepDelete (exp_stmt);
24533
24534 // modify the decl's rhs to be the new one
24537 if (init_name->get_initptr() != NULL)
24538 SageInterface::deepDelete (init_name->get_initptr());
24539 init_name->set_initptr(initor);
24540 initor->set_parent(init_name);
24541
24542 stmt_list.insert (stmt_list.begin(), decl );
24543 break;
24544 }
24545
24546 default:
24547 {
24548 cerr<<"Error. Unhandled target scope type:"<<target_scope->class_name()<<endl;
24549 ROSE_ASSERT (false);
24550 }
24551 }
24552
24553 //make sure the symbol is moved also since prependStatement() (in fact fixVariableDeclaration()) does not handle this detail.
24555 ROSE_ASSERT(sym != NULL);
24556 SgScopeStatement* orig_scope = sym->get_scope();
24557 if (orig_scope != target_scope)
24558 {
24559 // SageInterface::fixVariableDeclaration() cannot switch the scope for init name.
24560 // it somehow always reuses previously associated scope.
24562 init_name->set_scope(target_scope);
24563 SgName sname = sym->get_name();
24564 orig_scope->remove_symbol(sym);
24565 target_scope->insert_symbol(sname, sym);
24566 }
24567 // This is difficult since C++ variables have namespaces
24568 // Details are in SageInterface::fixVariableDeclaration()
24569 ROSE_ASSERT (target_scope->symbol_exists(sym));
24570}
24571
24572class SimpleExpressionEvaluator: public AstBottomUpProcessing <struct SageInterface::const_int_expr_t> {
24573 public:
24575 }
24576
24577 struct SageInterface::const_int_expr_t getValueExpressionValue(SgValueExp *valExp) {
24578 struct SageInterface::const_int_expr_t subtreeVal;
24579 subtreeVal.hasValue_ = true;
24580
24581 if (isSgIntVal(valExp)) {
24582 subtreeVal.value_ = isSgIntVal(valExp)->get_value();
24583 } else if (isSgLongIntVal(valExp)) {
24584 subtreeVal.value_ = isSgLongIntVal(valExp)->get_value();
24585 } else if (isSgLongLongIntVal(valExp)) {
24586 subtreeVal.value_ = isSgLongLongIntVal(valExp)->get_value();
24587 } else if (isSgShortVal(valExp)) {
24588 subtreeVal.value_ = isSgShortVal(valExp)->get_value();
24589 } else if (isSgUnsignedIntVal(valExp)) {
24590 subtreeVal.value_ = isSgUnsignedIntVal(valExp)->get_value();
24591 } else if (isSgUnsignedLongVal(valExp)) {
24592 subtreeVal.value_ = isSgUnsignedLongVal(valExp)->get_value();
24593 } else if (isSgUnsignedLongLongIntVal(valExp)) {
24594 subtreeVal.value_ = isSgUnsignedLongLongIntVal(valExp)->get_value();
24595 } else if (isSgUnsignedShortVal(valExp)) {
24596 subtreeVal.value_ = isSgUnsignedShortVal(valExp)->get_value();
24597 }
24598 return subtreeVal;
24599 }
24600
24601 struct SageInterface::const_int_expr_t evaluateVariableReference(SgVarRefExp *vRef) {
24602 if (isSgModifierType(vRef->get_type()) == NULL) {
24604 val.value_ = -1;
24605 val.hasValue_ = false;
24606 return val;
24607 }
24608 if (isSgModifierType(vRef->get_type())->get_typeModifier().get_constVolatileModifier().isConst()) {
24609 // We know that the var value is const, so get the initialized name and evaluate it
24610 SgVariableSymbol *sym = vRef->get_symbol();
24611 SgInitializedName *iName = sym->get_declaration();
24612 SgInitializer *ini = iName->get_initializer();
24613
24614 if (isSgAssignInitializer(ini)) {
24615 SgAssignInitializer *initializer = isSgAssignInitializer(ini);
24616 SgExpression *rhs = initializer->get_operand();
24617 SimpleExpressionEvaluator variableEval;
24618
24619 return variableEval.traverse(rhs);
24620 }
24621 }
24623 val.hasValue_ = false;
24624 val.value_ = -1;
24625 return val;
24626 }
24627
24628 struct SageInterface::const_int_expr_t evaluateSynthesizedAttribute(SgNode *node, SynthesizedAttributesList synList) {
24629 if (isSgExpression(node) != NULL) {
24630 SgValueExp* valueExp = isSgValueExp(node);
24631 if (valueExp != NULL) {
24632 return this->getValueExpressionValue(valueExp);
24633 }
24634
24635 SgVarRefExp* varRefExp = isSgVarRefExp(node);
24636 if (varRefExp != NULL) {
24637 // std::cout << "Hit variable reference expression!" << std::endl;
24638 return evaluateVariableReference(varRefExp);
24639 }
24640 // Early break out for assign initializer // other possibility?
24641 if (isSgAssignInitializer(node)) {
24642 if(synList.at(0).hasValue_){
24643 return synList.at(0);
24644 } else {
24646 val.value_ = -1;
24647 val.hasValue_ = false;
24648 return val;
24649 }
24650 }
24651 struct SageInterface::const_int_expr_t evaluatedValue;
24652 evaluatedValue.hasValue_ = false;
24653 evaluatedValue.value_ = -1;
24654#if 0
24655 if(synList.size() != 2){
24656 for(SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it){
24657 std::cout << "Node: " << node->unparseToString() << "\n" << (*it).value_ << std::endl;
24658 std::cout << "Parent: " << node->get_parent()->unparseToString() << std::endl;
24659 std::cout << "Parent, Parent: " << node->get_parent()->get_parent()->unparseToString() << std::endl;
24660 }
24661 }
24662#endif
24663 for (SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it) {
24664 if((*it).hasValue_){
24665 if (isSgAddOp(node)) {
24666 assert(synList.size() == 2);
24667 evaluatedValue.value_ = synList[0].value_ + synList[1].value_ ;
24668 evaluatedValue.hasValue_ = true;
24669 } else if (isSgSubtractOp(node)) {
24670 assert(synList.size() == 2);
24671 evaluatedValue.value_ = synList[0].value_ - synList[1].value_ ;
24672 evaluatedValue.hasValue_ = true;
24673 } else if (isSgMultiplyOp(node)) {
24674 assert(synList.size() == 2);
24675 evaluatedValue.value_ = synList[0].value_ * synList[1].value_ ;
24676 evaluatedValue.hasValue_ = true;
24677 } else if (isSgDivideOp(node)) {
24678 assert(synList.size() == 2);
24679 evaluatedValue.value_ = synList[0].value_ / synList[1].value_ ;
24680 evaluatedValue.hasValue_ = true;
24681 } else if (isSgModOp(node)) {
24682 assert(synList.size() == 2);
24683 evaluatedValue.value_ = synList[0].value_ % synList[1].value_ ;
24684 evaluatedValue.hasValue_ = true;
24685 }
24686 } else {
24687 std::cerr << "Expression is not evaluatable" << std::endl;
24688 evaluatedValue.hasValue_ = false;
24689 evaluatedValue.value_ = -1;
24690 return evaluatedValue;
24691 }
24692 }
24693 evaluatedValue.hasValue_ = true;
24694 return evaluatedValue;
24695 }
24696 struct SageInterface::const_int_expr_t evaluatedValue;
24697 evaluatedValue.hasValue_ = false;
24698 evaluatedValue.value_ = -1;
24699 return evaluatedValue;
24700 }
24701};
24702
24706 return eval.traverse(expr);
24707}
24708
24709bool
24711
24712 class TypeEquivalenceChecker {
24713 public:
24714 TypeEquivalenceChecker(bool profile, bool useSemanticEquivalence)
24715 : profile_(profile), useSemanticEquivalence_(useSemanticEquivalence),
24716 namedType_(0), pointerType_(0), arrayType_(0), functionType_(0)
24717 {
24718 }
24719
24720 SgNode * getBasetypeIfApplicable(SgNode *t){
24721 SgNode * node = t;
24722 if (isSgTypedefType(t)) {
24723// std::cout << "This is a typedef nodeT1. We strip everything away and compare the hidden types." << std::endl;
24724 node = isSgTypedefType(t)->stripType(SgType::STRIP_TYPEDEF_TYPE);
24725 }
24726 if(useSemanticEquivalence_){
24727 if(isSgModifierType(t)){
24728 SgModifierType *modType = isSgModifierType(t);
24729 ROSE_ASSERT(modType != NULL);
24730 // We need to check for Volatile/Restrict types. These are modelled as ModifierTypes, but are equal (in some cases)
24731 // volatile seems to make no difference for basic (built in) types like int, bool etc. But it has an impact on types
24732 // like classes
24733 // restrict seems to have no impact on the type itself.
24734 if(SageInterface::isVolatileType(modType)){
24735 // handle volatile case
24736 std::cout << "Hit volatile type, stripping of modifier type" << std::endl;
24737 node = modType->get_base_type();
24738 }
24739 if(SageInterface::isRestrictType(modType)){
24740 // handle restrict case
24741 std::cout << "Hit restrict type, stripping of modifier type" << std::endl;
24742 node = modType->get_base_type();
24743 }
24744 }
24745 }
24746 ROSE_ASSERT(node != NULL);
24747 return node;
24748}
24749
24750bool typesAreEqual(SgType *t1, SgType *t2) {
24751 bool equal = false;
24752 if(t1 == NULL || t2 == NULL){
24753 std::string wasNull;
24754 if(t1 == NULL){
24755 wasNull = "t1";
24756 } else {
24757 wasNull = "t2";
24758 }
24759 std::cerr << "ERROR: " << wasNull << " was NULL" << std::endl;
24760 return equal;
24761 }
24762 // if both pointers point to same location the types MUST be equal!
24763 if(t1 == t2){
24764// std::cout << "Pointers are equal, returning true" << std::endl;
24765 return true;
24766 }
24767#ifndef USE_CMAKEx
24768 RoseAst subT1(t1);
24769 RoseAst subT2(t2);
24770
24771 for (RoseAst::iterator i = subT1.begin(), j = subT2.begin();
24772 i != subT1.end() && j != subT2.end(); ++i, ++j) {
24773 SgNode *nodeT1 = *i;
24774 SgNode *nodeT2 = *j;
24775
24776// std::cout << "nodeT1: " << nodeT1->class_name() << " nodeT2: " << nodeT2->class_name() << std::endl;
24777 nodeT1 = getBasetypeIfApplicable(nodeT1);
24778 nodeT2 = getBasetypeIfApplicable(nodeT2);
24779
24780 if (nodeT1->variantT() == nodeT2->variantT()) {
24781// std::cout << "variantT is the same" << std::endl;
24782 if(isSgModifierType(nodeT1)){
24783 // we need to check whether the modifier is the same or not
24784 SgTypeModifier modT1 = isSgModifierType(nodeT1)->get_typeModifier();
24785 SgTypeModifier modT2 = isSgModifierType(nodeT2)->get_typeModifier();
24786 if(modT1.get_constVolatileModifier().isConst() != modT2.get_constVolatileModifier().isConst()){
24787 return false;
24788 }
24789 if(modT1.get_constVolatileModifier().isVolatile() != modT2.get_constVolatileModifier().isVolatile()){
24790 return false;
24791 }
24792 } else if (isSgNamedType(nodeT1)) { // Two different names -> Must be two different things
24793 if (profile_) {
24794 namedType_++;
24795 }
24796 i.skipChildrenOnForward();
24797 j.skipChildrenOnForward();
24798 SgNamedType *c1 = isSgNamedType(nodeT1);
24799 SgNamedType *c2 = isSgNamedType(nodeT2);
24800
24801 // XXX A function to check whether a named type is anonymous or not would speed
24802 // up this check, since we could get rid of this string compare.
24803 if(!c1->get_autonomous_declaration()){
24804 return false;
24805 }
24806 if (!c2->get_autonomous_declaration()){
24807 return false;
24808 }
24809 if (c1->get_qualified_name() == c2->get_qualified_name()) {
24810 return true;
24811 } else {
24812 return false;
24813 }
24814
24815 } else if (isSgPointerType(nodeT1)) {
24816 if (profile_) {
24817 pointerType_++;
24818 }
24819 SgPointerType *t1 = isSgPointerType(nodeT1);
24820 SgPointerType *t2 = isSgPointerType(nodeT2);
24821
24822 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24823
24824 } else if(isSgReferenceType(nodeT1)){
24825 SgReferenceType *t1 = isSgReferenceType(nodeT1);
24826 SgReferenceType *t2 = isSgReferenceType(nodeT2);
24827
24828 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24829 } else if (isSgArrayType(nodeT1)) {
24830 if (profile_) {
24831 arrayType_++;
24832 }
24833 SgArrayType *a1 = isSgArrayType(nodeT1);
24834 SgArrayType *a2 = isSgArrayType(nodeT2);
24835
24836 bool arrayBaseIsEqual = typesAreEqual(a1->get_base_type(), a2->get_base_type());
24837
24840 bool arrayIndexExpressionIsEquivalent = false;
24841 if(t1Index.hasValue_ && t2Index.hasValue_){
24842 if(t1Index.value_ == t2Index.value_){
24843 arrayIndexExpressionIsEquivalent = true;
24844 }
24845 }
24846 bool arraysAreEqual = (arrayBaseIsEqual && arrayIndexExpressionIsEquivalent);
24847 return arraysAreEqual;
24848 } else if (isSgFunctionType(nodeT1)) {
24849 if(profile_) {
24850 functionType_++;
24851 }
24852 SgFunctionType *funcTypeA = isSgFunctionType(nodeT1);
24853 SgFunctionType *funcTypeB = isSgFunctionType(nodeT2);
24854// std::cout << "Inside SgFunctionType" << std::endl;
24855// assert(funcTypeA != funcTypeB);
24856 if(typesAreEqual(funcTypeA->get_return_type(), funcTypeB->get_return_type())) {
24857 // If functions don't have the same number of arguments, they are not type-equal
24858 if(funcTypeA->get_arguments().size() != funcTypeB->get_arguments().size()) {
24859 return false;
24860 }
24861 // This should always be the same as the if before...
24862 if(funcTypeA->get_argument_list()->get_arguments().size() != funcTypeB->get_argument_list()->get_arguments().size()){
24863 return false;
24864 }
24865
24866 for(SgTypePtrList::const_iterator ii = funcTypeA->get_arguments().begin(),
24867 jj = funcTypeB->get_arguments().begin();
24868 ii != funcTypeA->get_arguments().end() &&
24869 jj != funcTypeB->get_arguments().end();
24870 ++ii, ++jj) {
24871// std::cout << (*ii)->class_name() << " " << (*jj)->class_name() << std::endl;
24872 // For all argument types check whether they are equal
24873 if(!typesAreEqual((*ii), (*jj))) {
24874 return false;
24875 }
24876 }
24877 return true;
24878 }
24879 return false;
24880 } else {
24881 // We don't have a named type, pointer type or array type, so they are equal
24882 // This is for the primitive type - case
24883 return true;
24884 }
24885 } else {
24886 // In this case the types are not equal, since its variantT is not equal.
24887 return false;
24888 }
24889 }
24890 // this should be unreachable code...
24891 return equal;
24892#else
24893 std::cerr << "This feature for now is available with autotools only!" << std::endl;
24894 ROSE_ABORT();
24895#endif
24896}
24897
24898int getNamedTypeCount() {
24899 return namedType_;
24900}
24901
24902int getPointerTypeCount() {
24903 return pointerType_;
24904}
24905
24906int getArrayTypeCount() {
24907 return arrayType_;
24908}
24909
24910int getFunctionTypeCount() {
24911 return functionType_;
24912}
24913 private:
24914// SgNode * getBasetypeIfApplicable(SgNode *t);
24915 bool profile_, useSemanticEquivalence_;
24916 int namedType_, pointerType_, arrayType_, functionType_;
24917};
24918
24919TypeEquivalenceChecker tec(false, false);
24920return tec.typesAreEqual(typeA, typeB);
24921}
24922
24923
24924std::set<SgStatement*>
24926 {
24927 // DQ (6/11/2015): This reports the statements that are marked as transformed.
24928 // It is useful for debugging the token-based unparsing.
24929
24930 class StatementTraversal : public AstSimpleProcessing
24931 {
24932 public:
24933 StatementTraversal() : count (0) {}
24934 void visit (SgNode* node)
24935 {
24936 SgStatement* statement = isSgStatement(node);
24937 if (statement != nullptr && statement->isTransformation() == true)
24938 {
24939 returnset.insert(statement);
24940 count++;
24941 }
24942 }
24943
24944 int count; // running total of statements found marked as transformations in the input AST
24945 std::set<SgStatement*> returnset;
24946 };
24947
24948 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24949 StatementTraversal traversal;
24950 traversal.traverse(node, preorder);
24951
24952 return traversal.returnset;
24953 }
24954
24955std::set<SgStatement*>
24957 {
24958 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24959 // It is useful for debugging the token-based unparsing.
24960
24961#if 1
24962 printf ("In collectModifiedStatements(): node = %p = %s \n",node,node->class_name().c_str());
24963#endif
24964
24965 class StatementTraversal : public AstSimpleProcessing
24966 {
24967 public:
24968 StatementTraversal() : count (0) {}
24969 void visit (SgNode* node)
24970 {
24971 SgStatement* statement = isSgStatement(node);
24972 if (statement != NULL && statement->get_isModified() == true)
24973 {
24974 returnset.insert(statement);
24975 count++;
24976 }
24977 }
24978
24979 int count; // running total of statements found marked as transformations in the input AST
24980 std::set<SgStatement*> returnset;
24981 };
24982
24983 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24984 StatementTraversal traversal;
24985 traversal.traverse(node, preorder);
24986
24987 return traversal.returnset;
24988 }
24989
24990
24991void
24993 {
24994 // DQ (12/2/2019): This reports the file id values of all located nodes in the AST subtree represented by the input node.
24995
24996#if 0
24997 printf ("In outputFileIds(): node = %p = %s \n",node,node->class_name().c_str());
24998#endif
24999
25000 class LocatedNodeTraversal : public AstSimpleProcessing
25001 {
25002 public:
25003 LocatedNodeTraversal() {}
25004 void visit (SgNode* node)
25005 {
25006 SgLocatedNode* locatedNode = isSgLocatedNode(node);
25007 if (locatedNode != NULL)
25008 {
25009#if 0
25010 printf ("In outputFileIds(): isModified() == %s: locatedNode = %p = %s \n",locatedNode->get_isModified() ? "true" : "false",locatedNode,locatedNode->class_name().c_str());
25011 printf (" --- file id = %d physical_file_id = %d \n",node->get_file_info()->get_file_id(),node->get_file_info()->get_physical_file_id());
25012#endif
25013 }
25014 else
25015 {
25016 SgInitializedName* initializedName = isSgInitializedName(node);
25017 if (initializedName != NULL)
25018 {
25019 printf ("In outputFileIds(): isModified() == %s: initializedName = %p = %s \n",initializedName->get_isModified() ? "true" : "false",initializedName,initializedName->class_name().c_str());
25020 printf (" --- file id = %d physical_file_id = %d \n",initializedName->get_file_info()->get_file_id(),initializedName->get_file_info()->get_physical_file_id());
25021 }
25022 }
25023 }
25024 };
25025
25026 // Now buid the traveral object and call the traversal (preorder) on the function definition.
25027 LocatedNodeTraversal traversal;
25028 traversal.traverse(node, preorder);
25029
25030#if 0
25031 printf ("Exiting as a test! \n");
25032 ROSE_ABORT();
25033#endif
25034 }
25035
25036
25037std::set<SgLocatedNode*>
25039 {
25040 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
25041 // It is useful for debugging the token-based unparsing.
25042
25043#if 0
25044 printf ("In collectModifiedLocatedNodes(): node = %p = %s \n",node,node->class_name().c_str());
25045#endif
25046
25047 class LocatedNodeTraversal : public AstSimpleProcessing
25048 {
25049 public:
25050 LocatedNodeTraversal() : count (0) {}
25051 void visit (SgNode* node)
25052 {
25053 SgLocatedNode* locatedNode = isSgLocatedNode(node);
25054 if (locatedNode != NULL && locatedNode->get_isModified() == true)
25055 {
25056#if 0
25057 printf ("In collectModifiedLocatedNodes(): isModified() == true: locatedNode = %p = %s \n",locatedNode,locatedNode->class_name().c_str());
25058#endif
25059 returnset.insert(locatedNode);
25060 count++;
25061 }
25062 }
25063
25064 int count; // running total of statements found marked as transformations in the input AST
25065 std::set<SgLocatedNode*> returnset;
25066 };
25067
25068 // Now buid the traveral object and call the traversal (preorder) on the function definition.
25069 LocatedNodeTraversal traversal;
25070 traversal.traverse(node, preorder);
25071
25072 return traversal.returnset;
25073 }
25074
25075
25077void
25078SageInterface::resetModifiedLocatedNodes(const std::set<SgLocatedNode*> & modifiedNodeSet)
25079 {
25080 // DQ (6/5/2019): Use a previously constructed set to reset the IR nodes to be marked as isModified.
25081
25082#if 0
25083 printf ("In resetModifiedLocatedNodes(): modifiedNodeSet.size() = %zu \n",modifiedNodeSet.size());
25084#endif
25085
25086 std::set<SgLocatedNode*>::const_iterator i = modifiedNodeSet.begin();
25087 while (i != modifiedNodeSet.end())
25088 {
25089 SgLocatedNode* node = *i;
25090#if 0
25091 printf ("Marking node = %p = %s as modified \n",node,node->class_name().c_str());
25092#endif
25093 node->set_isModified(true);
25094
25095 i++;
25096 }
25097 }
25098
25099
25100void
25102 {
25103 // DQ (10/23/2018): This reports the nodes in the AST that are marked as modified (isModified flag).
25104 // It is useful for debugging the token-based unparsing.
25105
25106 printf ("\n\n##################################################### \n");
25107 printf ("Report on modified statements: label = %s \n",label.c_str());
25108
25109 SgSourceFile* sourceFile = isSgSourceFile(node);
25110 if (sourceFile != NULL)
25111 {
25112 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
25113 }
25114 else
25115 {
25116 SgGlobal* globalScope = isSgGlobal(node);
25117 if (globalScope != NULL)
25118 {
25119 sourceFile = isSgSourceFile(globalScope->get_parent());
25120 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
25121 }
25122 }
25123
25124 ROSE_ASSERT(node != NULL);
25125 std::set<SgStatement*> collection = collectModifiedStatements(node);
25126
25127#if 0
25128 printf ("In reportModifiedStatements(): collection.size() = %zu \n",collection.size());
25129#endif
25130
25131 std::set<SgStatement*>::iterator i = collection.begin();
25132 while (i != collection.end())
25133 {
25134 // DQ (10/9/2019): Adding filename to debug output.
25135 string filename = (*i)->get_file_info()->get_filename();
25136
25137 // DQ (10/14/2019): Get the best name possible.
25138 if (filename == "transformation")
25139 {
25140#if 0
25141 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
25142#endif
25143 // filename = (*i)->get_file_info()->get_physical_filename();
25144 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
25145 if (sourceFile != NULL)
25146 {
25147 filename = sourceFile->getFileName();
25148 }
25149 }
25150
25151 printf (" --- filename = %s modified statement = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
25152
25153 i++;
25154 }
25155
25156#if 1
25157 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
25158 // output spew else the message output at the top of this function will scroll off the screen.
25159 printf ("########################################################## \n");
25160 printf ("reportModifiedStatements(): Called using label = %s \n",label.c_str());
25161#endif
25162 printf ("########################################################## \n\n\n");
25163
25164#if 0
25165 printf ("Exiting as a test! \n");
25166 ROSE_ASSERT(false);
25167#endif
25168 }
25169
25170
25171
25172void
25174 {
25175 // DQ (6/21/2021): This reports the nodes in the AST that are marked as modified (isModified flag).
25176 // It is useful for debugging the token-based unparsing.
25177
25178 printf ("\n\n##################################################### \n");
25179 printf ("Report on modified locatedNodes: label = %s \n",label.c_str());
25180
25181 SgSourceFile* sourceFile = isSgSourceFile(node);
25182 if (sourceFile != NULL)
25183 {
25184 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
25185 }
25186 else
25187 {
25188 SgGlobal* globalScope = isSgGlobal(node);
25189 if (globalScope != NULL)
25190 {
25191 sourceFile = isSgSourceFile(globalScope->get_parent());
25192 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
25193 }
25194 }
25195
25196 ROSE_ASSERT(node != NULL);
25197 std::set<SgLocatedNode*> collection = collectModifiedLocatedNodes(node);
25198
25199#if 0
25200 printf ("In reportModifiedLocatedNode(): collection.size() = %zu \n",collection.size());
25201#endif
25202
25203 std::set<SgLocatedNode*>::iterator i = collection.begin();
25204 while (i != collection.end())
25205 {
25206 // DQ (10/9/2019): Adding filename to debug output.
25207 string filename = (*i)->get_file_info()->get_filename();
25208
25209 // DQ (10/14/2019): Get the best name possible.
25210 if (filename == "transformation")
25211 {
25212#if 0
25213 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
25214#endif
25215 // filename = (*i)->get_file_info()->get_physical_filename();
25216 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
25217 if (sourceFile != NULL)
25218 {
25219 filename = sourceFile->getFileName();
25220 }
25221 }
25222
25223 printf (" --- filename = %s modified locatedNode = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
25224
25225 i++;
25226 }
25227
25228#if 1
25229 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
25230 // output spew else the message output at the top of this function will scroll off the screen.
25231 printf ("########################################################## \n");
25232 printf ("reportModifiedLocatedNodes(): Called using label = %s \n",label.c_str());
25233#endif
25234 printf ("########################################################## \n\n\n");
25235
25236#if 0
25237 printf ("Exiting as a test! \n");
25238 ROSE_ASSERT(false);
25239#endif
25240 }
25241
25242
25243
25244
25245// DQ (3/22/2019): Translate CPP directives from attached preprocessor information to CPP Directive Declaration IR nodes.
25246
25247void
25249 {
25250 // Debugging function to print out comments in the statements (added by DQ)
25251
25252 ROSE_ASSERT(locatedNode != NULL);
25253 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
25254
25255#if 0
25256 curprint ("/* Inside of printOutComments() */");
25257#endif
25258
25259 if (comments != NULL)
25260 {
25261#if 0
25262 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25263 curprint ("/* Inside of printOutComments(): comments != NULL */");
25264#endif
25265
25266 AttachedPreprocessingInfoType::iterator i;
25267 for (i = comments->begin(); i != comments->end(); i++)
25268 {
25269 ROSE_ASSERT ( (*i) != NULL );
25270 printf (" Attached Comment (relativePosition=%s): %s \n",
25271 // DQ (2/11/2021): Fixed to report correct relative locations.
25272 // ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25273 PreprocessingInfo::relativePositionName((*i)->getRelativePosition()).c_str(),
25274 (*i)->getString().c_str());
25275 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
25276 // curprint (string("/* Inside of printOutComments(): comments = ") + (*i)->getString() + " */");
25277
25278#if 0
25279 (*i)->get_file_info()->display("comment/directive location");
25280#endif
25281 }
25282 }
25283 else
25284 {
25285#if 0
25286 printf ("In SageInterface::printOutComments(): No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25287#endif
25288 }
25289 }
25290
25291
25292
25293bool
25295 {
25296 bool returnValue = false;
25297
25298 ROSE_ASSERT(currentPreprocessingInfo != NULL);
25299
25300 PreprocessingInfo::DirectiveType directive = currentPreprocessingInfo->getTypeOfDirective();
25301
25302 if (directive == PreprocessingInfo::C_StyleComment ||
25303 directive == PreprocessingInfo::CplusplusStyleComment ||
25304 directive == PreprocessingInfo::FortranStyleComment ||
25305 directive == PreprocessingInfo::CpreprocessorBlankLine ||
25306 directive == PreprocessingInfo::ClinkageSpecificationStart ||
25307 directive == PreprocessingInfo::ClinkageSpecificationEnd)
25308 {
25309 returnValue = true;
25310 }
25311
25312 return returnValue;
25313 }
25314
25315std::vector<SgC_PreprocessorDirectiveStatement*>
25317 {
25318 std::vector<SgC_PreprocessorDirectiveStatement*> directiveList;
25319
25320 // Find existing first and last header.
25321 AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo();
25322
25323 if (comments != nullptr)
25324 {
25325 AttachedPreprocessingInfoType::iterator i; // , firsti, lasti;
25326 for (i = comments->begin (); i != comments->end(); i++)
25327 {
25328 if (skipTranslateToUseCppDeclaration(*i) == true)
25329 {
25330 // 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).
25331 }
25332 else
25333 {
25334 SgC_PreprocessorDirectiveStatement* directive = SgC_PreprocessorDirectiveStatement::createDirective(*i);
25335 ROSE_ASSERT(directive != NULL);
25336 directiveList.push_back(directive);
25337 }
25338
25339 printf ("directiveList.size() = %zu \n",directiveList.size());
25340 }
25341 }
25342
25343 return directiveList;
25344 }
25345
25346
25347void
25349 {
25350 bool declarationsOnly = scope->containsOnlyDeclarations();
25351
25352 printf ("In translateScopeToUseCppDeclarations(): declarationsOnly = %s scope = %p = %s \n",declarationsOnly ? "true" : "false",scope,scope->class_name().c_str());
25353
25354 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> > directiveMap;
25355
25356 if (declarationsOnly == true)
25357 {
25358 // These are scopes such as global scope, namespace definitions, class definitions, etc.
25359 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
25360 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
25361 while (i != declarationList.end())
25362 {
25363 SgDeclarationStatement* declaration = *i;
25364 ROSE_ASSERT(declaration != NULL);
25365
25366 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(declaration,scope);
25367
25368 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25369
25370 if (attachDirectives.empty() == false)
25371 {
25372 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(declaration,attachDirectives));
25373 }
25374
25375 i++;
25376 }
25377
25378 // Need to save the list of things that will be added so we can avoid iterator invalidation.
25379 }
25380 else
25381 {
25382 // These are scopes such as SgBasicBlock (which can contain non-declaration statements.
25383 SgStatementPtrList & statementList = scope->getStatementList();
25384 SgStatementPtrList::iterator i = statementList.begin();
25385 while (i != statementList.end())
25386 {
25387 SgStatement* statement = *i;
25388 ROSE_ASSERT(statement != NULL);
25389
25390 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(statement,scope);
25391
25392 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25393
25394 if (attachDirectives.empty() == false)
25395 {
25396 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(statement,attachDirectives));
25397 }
25398
25399 i++;
25400 }
25401 }
25402
25403 printf ("directiveMap.size() = %zu \n",directiveMap.size());
25404
25405 printf ("Processing the directiveMap: \n");
25406 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >::iterator i = directiveMap.begin();
25407 while (i != directiveMap.end())
25408 {
25409 SgStatement* statement = i->first;
25410 std::vector<SgC_PreprocessorDirectiveStatement*> directives = i->second;
25411
25412 printf ("statement = %p = %s \n",statement,statement->class_name().c_str());
25413 printf ("directives.size() = %zu \n",directives.size());
25414 // std::vector<SgC_PreprocessorDirectiveStatement*>::reverse_iterator j = directives.begin();
25415 std::vector<SgC_PreprocessorDirectiveStatement*>::iterator j = directives.begin();
25416 while (j != directives.end())
25417 {
25418 scope->insert_statement(statement,*j);
25419
25420 j++;
25421 }
25422
25423 // Remove the directives there were attached to the statement.
25424 AttachedPreprocessingInfoType *comments = statement->getAttachedPreprocessingInfo();
25425 ROSE_ASSERT(comments != NULL);
25426
25427 AttachedPreprocessingInfoType deleteList;
25428 // std::vector<PreprocessingInfo*> deleteList;
25429
25430 // comments->erase();
25431 // statement->setAttachedPreprocessingInfo(NULL);
25432 AttachedPreprocessingInfoType::iterator k;
25433 for (k = comments->begin(); k != comments->end(); k++)
25434 {
25435#if 1
25436 ROSE_ASSERT ( (*k) != NULL );
25437 printf (" Attached Comment (relativePosition=%s): %s\n",
25438 ((*k)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25439 (*k)->getString().c_str());
25440 printf ("translateScopeToUseCppDeclarations(): Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*k)->getNumberOfLines(),(*k)->getColumnNumberOfEndOfString());
25441#endif
25442
25443 // We only want to process the CPP directives (skipping comments and a few othr kinds of obscure directives).
25444 if (skipTranslateToUseCppDeclaration(*k) == true)
25445 {
25446 // 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).
25447 printf ("Do NOT delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25448 }
25449 else
25450 {
25451 printf ("DO delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25452
25453 deleteList.push_back(*k);
25454 // delete *k;
25455 // *k = NULL;
25456 }
25457 }
25458
25459 printf ("Iterate over the deleteList: deleteList.size() = %zu comments->size() = %zu \n",deleteList.size(),comments->size());
25460 AttachedPreprocessingInfoType::iterator m = deleteList.begin();
25461 while (m != deleteList.end())
25462 {
25463 // comments->erase(m);
25464 // std::remove(comments->begin(), comments->end(), *m);
25465 comments->erase(std::remove(comments->begin(), comments->end(), *m), comments->end());
25466
25467 printf (" --- comments->size() = %zu \n",comments->size());
25468
25469 m++;
25470 }
25471
25472 // comments->clear();
25473 // delete comments; // statement->getAttachedPreprocessingInfoPtr();
25474 // statement->set_attachedPreprocessingInfoPtr(NULL);
25475
25476 i++;
25477 }
25478
25479 printf ("Leaving translateScopeToUseCppDeclarations(): scope = %p = %s \n",scope,scope->class_name().c_str());
25480 }
25481
25482
25483void
25485 {
25486 class CppTranslationTraversal : public AstSimpleProcessing
25487 {
25488 public:
25489 CppTranslationTraversal() {}
25490 void visit (SgNode* node)
25491 {
25492 printf ("In CppTranslationTraversal::visit(): node = %p = %s \n",node,node->class_name().c_str());
25493
25494 SgScopeStatement* scope = isSgScopeStatement(node);
25495 SgGlobal* globalScope = isSgGlobal(scope);
25496 if (globalScope != NULL)
25497 {
25498 printf ("In CppTranslationTraversal::visit(): processing scope = %p = %s \n",scope,scope->class_name().c_str());
25500 }
25501 else
25502 {
25503 if (scope != NULL)
25504 {
25505 printf ("In SageInterface::translateToUseCppDeclarations(): Currently skipping all but global scope! \n");
25506 }
25507 }
25508 }
25509 };
25510
25511 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
25512 CppTranslationTraversal traversal;
25513
25514 printf ("In translateToUseCppDeclarations(): Calling traversal.traverse() \n");
25515
25516 // We might want to do this traversla POSTORDER since we are transforming the AST at each scope.
25517 // traversal.traverse(n, preorder);
25518 traversal.traverse(n, postorder);
25519
25520 printf ("Leaving translateToUseCppDeclarations(): DONE: Calling traversal.traverse() \n");
25521 }
25522
25524{
25525 // print current level's info
25526 if (!n) return;
25527 cout<<"--------------"<<endl;
25528 cout<<n<<":"<<n->class_name()<< endl;
25529 if (SgLocatedNode * lnode = isSgLocatedNode(n))
25530 {
25531 cout<<"file info:\t ";
25532 lnode->get_file_info()->display();
25533 cout<<"\n unparseToString:\t ";
25534 lnode->unparseToString();
25535 }
25536
25537 // track back to its parent
25539}
25540// forward declaration is needed here,
25541//static void serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel);
25542
25543#if 0 // made it into a template function to handle various ptr lists in AST
25544// A special node in the AST text dump
25545static void serialize(SgTemplateArgumentPtrList& plist, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25546{
25547 out<<prefix;
25548 out<< (hasRemaining?"|---": "|___");
25549
25550// out<<"+"<<edgeLabel<<"+>";
25551 out<<" "<<edgeLabel<<" ->";
25552 // print address
25553 out<<"@"<<&plist<<" "<< "SgTemplateArgumentPtrList ";
25554
25555 out<<endl;
25556
25557 int last_non_null_child_idx =-1;
25558 for (int i = (int) (plist.size())-1; i>=0; i--)
25559 {
25560 if (plist[i])
25561 {
25562 last_non_null_child_idx = i;
25563 break;
25564 }
25565 }
25566
25567 for (size_t i=0; i< plist.size(); i++ )
25568 {
25569 bool n_hasRemaining=false;
25570#if 0
25571 if (i+1 < plist.size())
25572 n_hasRemaining=true;
25573#else
25574 if ((int)i< last_non_null_child_idx) n_hasRemaining = true;
25575#endif
25576 string suffix= hasRemaining? "| " : " ";
25577 string n_prefix = prefix+suffix;
25578 string n_edge_label="";
25579 if (plist[i])
25580 serialize (plist[i], n_prefix, n_hasRemaining, out,n_edge_label);
25581 }
25582}
25583#endif
25584
25585// print essential information from any AST node
25586// hasRemaining if this node has a sibling node to be visited next.
25587void SageInterface::serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25588{
25589 // there may be NULL children!!
25590 //if (!node) return;
25591
25592 out<<prefix;
25593 out<< (hasRemaining?"|---": "|___");
25594
25595 out<<" "<<edgeLabel<<" ->";
25596 if (!node)
25597 {
25598 out<<" NULL "<<endl;
25599 return;
25600 }
25601
25602 // print address
25603 out<<"@"<<node<<" "<< node->class_name()<<" ";
25604
25605 //optionally file info
25606 if (SgLocatedNode* lnode= isSgLocatedNode(node))
25607 {
25608 //Rose::StringUtility::stripPathFromFileName()
25609 out<< lnode->get_file_info()->get_filename() <<" "<<lnode->get_file_info()->get_line()<<":"<<lnode->get_file_info()->get_col();
25610 // also preprocessing info. attached.
25611 AttachedPreprocessingInfoType *comments =
25612 lnode->getAttachedPreprocessingInfo ();
25613
25614 if (comments != NULL)
25615 {
25616// printf ("Found an IR node with preprocessing Info attached:\n");
25617 out<<" AttachedPreprocessingInfoType@"<<comments;
25618 int counter = 0;
25619 AttachedPreprocessingInfoType::iterator i;
25620 out <<"{";
25621 for (i = comments->begin (); i != comments->end (); i++)
25622 {
25623 if (i!=comments->begin ())
25624 out<<endl;
25625 out<<"<id=";
25626 out<<counter++<<" ";
25627 // printf("-------------PreprocessingInfo #%d ----------- : \n",counter++);
25628 // printf("classification = %s:\n String format = %s\n",
25629 // PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str (),
25630 // (*i)->getString ().c_str ());
25631 if (*i==NULL)
25632 out<<" NULL="; // The AST may be in the middle of transformation, with NULL comments attached.
25633 else
25634 {
25635 out<<*i<<" classification="<<PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str ();
25636 out<<" string="<<(*i)->getString ().c_str ();
25637 out<<" relative pos=" ; // << (*i)->getRelativePosition ();
25638#if 1
25639 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
25640 out<<"inside";
25641 else if ((*i)->getRelativePosition () == PreprocessingInfo::before)
25642 out<<"before";
25643 else
25644 out<<"after";
25645#endif
25646 }
25647 out<<">";
25648 }
25649 out <<"}";
25650 }
25651 }
25652
25653 if (SgDeclarationStatement* v= isSgDeclarationStatement(node))
25654 {
25655 out<<" first nondefining decl@"<< v->get_firstNondefiningDeclaration();
25656 out<<" defining decl@"<< v->get_definingDeclaration();
25657 }
25658
25659 if (SgEnumVal* f = isSgEnumVal(node) )
25660 out<<" value="<< f->get_value() <<" declaration="<<f->get_declaration() << " name="<< f->get_name().getString();
25661 // optionally qualified name
25662
25663 if (SgFunctionDeclaration* f = isSgFunctionDeclaration(node) )
25664 out<<" "<< f->get_qualified_name();
25665
25666 if (SgAdaFunctionRenamingDecl* f = isSgAdaFunctionRenamingDecl(node) )
25667 out<<" renamed_function "<< f->get_renamed_function();
25668
25669 if (SgAdaRenamingDecl* f = isSgAdaRenamingDecl(node) )
25670 out<<" name="<< f->get_name() << " renamed decl "<<f->get_renamed() ;
25671
25672 if (SgClassDeclaration* f = isSgClassDeclaration(node) )
25673 out<<" "<< f->get_qualified_name();
25674
25675 if (SgTypedefDeclaration* f = isSgTypedefDeclaration(node) )
25676 out<<" "<< f->get_qualified_name();
25677
25678 if (SgAdaPackageSpecDecl * f = isSgAdaPackageSpecDecl(node) )
25679 out<<" "<< f->get_qualified_name();
25680
25681 if (SgAdaEnumRepresentationClause* f = isSgAdaEnumRepresentationClause(node) )
25682 out<<" enumType="<< f->get_enumType();
25683
25684 if (SgAdaAccessType* v = isSgAdaAccessType(node) )
25685 {
25686 // out<<" "<< v->get_qualified_name();
25687 //out<<" "<< v->get_name();
25688 // PP (2/18/22) updated to reflect properties in AdaAccessType
25689 //~ out<<" is_object_type"<< v->get_is_object_type();
25690 out<<" is_general_access"<< v->get_is_general_access();
25691 //~ out<<" is_constant:"<< v->get_is_constant();
25692 //~ out<<" is_protected:"<< v->get_is_protected ();
25693 out<<" is_anonymous:"<< v->get_is_anonymous ();
25694 }
25695
25696 if (SgAdaSubroutineType* v = isSgAdaSubroutineType(node) )
25697 {
25698 out<<" is_protected"<< v->get_is_protected();
25699 }
25700
25701 if (SgInitializedName * v = isSgInitializedName(node) )
25702 {
25703 out<<" "<< v->get_qualified_name();
25704 out<<" type@"<< v->get_type();
25705 out<<" initializer@"<< v->get_initializer();
25706 out<<" scope@"<< v->get_scope();
25707// type_set.insert (v->get_type());
25708 }
25709
25710 // associated class, function and variable declarations
25711 if (SgTemplateInstantiationDecl* f = isSgTemplateInstantiationDecl(node) )
25712 out<<" template class decl@"<< f->get_templateDeclaration();
25713
25714 if (SgMemberFunctionDeclaration* f = isSgMemberFunctionDeclaration(node) )
25715 out<<" assoc. class decl@"<< f->get_associatedClassDeclaration();
25716
25717 if (SgConstructorInitializer* ctor= isSgConstructorInitializer(node) )
25718 {
25719 out<<" member function decl@"<< ctor->get_declaration();
25720 }
25721
25722 if (SgIntVal* v= isSgIntVal(node))
25723 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25724
25725 if (SgShortVal* v= isSgShortVal(node))
25726 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25727
25728 if (SgLongIntVal* v= isSgLongIntVal(node))
25729 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25730
25731 if (SgLongLongIntVal* v= isSgLongLongIntVal(node))
25732 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25733
25734 if (SgUnsignedIntVal* v= isSgUnsignedIntVal(node))
25735 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25736
25737 if (SgUnsignedShortVal* v= isSgUnsignedShortVal(node))
25738 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25739
25740 if (SgUnsignedLongVal* v= isSgUnsignedLongVal(node))
25741 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25742
25743 if (SgUnsignedLongLongIntVal* v= isSgUnsignedLongLongIntVal(node))
25744 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25745
25746 if (SgFloatVal* v= isSgFloatVal(node))
25747 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25748
25749 if (SgDoubleVal* v= isSgDoubleVal(node))
25750 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25751
25752 if (SgLongDoubleVal* v= isSgLongDoubleVal(node))
25753 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25754
25755 if (SgVarRefExp* var_ref= isSgVarRefExp(node) )
25756 out<<" init name@"<< var_ref->get_symbol()->get_declaration() <<" symbol name="<<var_ref->get_symbol()->get_name();
25757
25758 if (SgMemberFunctionRefExp* func_ref= isSgMemberFunctionRefExp(node) )
25759 out<<" member func decl@"<< func_ref->get_symbol_i()->get_declaration();
25760
25761 if (SgTemplateInstantiationMemberFunctionDecl* cnode= isSgTemplateInstantiationMemberFunctionDecl(node) )
25762 out<<" template member func decl@"<< cnode->get_templateDeclaration();
25763
25764 if (SgFunctionRefExp* func_ref= isSgFunctionRefExp(node) )
25765 {
25766 SgFunctionSymbol* sym= func_ref->get_symbol_i();
25767 out<<" func decl@"<< sym->get_declaration() << " func sym name="<<sym->get_name();
25768 }
25769
25770 if (SgAdaRenamingRefExp* renaming_ref= isSgAdaRenamingRefExp(node) )
25771 {
25772 SgAdaRenamingDecl * renaming_decl = renaming_ref->get_decl();
25773 out<<" ada renaming decl@"<< renaming_decl;
25774 }
25775
25776 // base type of several types of nodes:
25777 if (SgTypedefDeclaration * v= isSgTypedefDeclaration(node))
25778 {
25779 out<<" base_type@"<< v->get_base_type();
25780// type_set.insert (v->get_base_type());
25781 }
25782
25783 if (SgArrayType* v= isSgArrayType(node))
25784 out<<" base_type@"<< v->get_base_type();
25785
25786 if (SgAdaAccessType* v= isSgAdaAccessType(node))
25787 out<<" base_type@"<< v->get_base_type();
25788
25789 if (SgTypeExpression* v= isSgTypeExpression(node))
25790 out<<" type@"<< v->get_type();
25791
25792 if (SgAdaAttributeExp* v= isSgAdaAttributeExp(node))
25793 out<<" attribute@"<< v->get_attribute();
25794
25795 if (SgUsingDirectiveStatement* v= isSgUsingDirectiveStatement(node))
25796 out<<" namespaceDeclaration="<< v->get_namespaceDeclaration();
25797
25798 out<<endl;
25799
25800 std::vector<SgNode* > children = node->get_traversalSuccessorContainer();
25801#if 0
25802 int total_count = children.size();
25803 int current_index=0;
25804#endif
25805
25806 int last_non_null_child_idx =-1;
25807 for (int i = (int) (children.size())-1; i>=0; i--)
25808 {
25809 if (children[i])
25810 {
25811 last_non_null_child_idx = i;
25812 break;
25813 }
25814 }
25815
25816#if 0
25817 // some Sg??PtrList are not AST nodes, not part of children , we need to handle them separatedly
25818 // we sum all children into single total_count to tell if there is remaining children.
25819 if (isSgTemplateInstantiationDecl (node))
25820 total_count += 1; // sn->get_templateArguments().size();
25821#endif
25822
25823 // handling SgTemplateArgumentPtrList first
25824 if (SgTemplateInstantiationDecl* sn = isSgTemplateInstantiationDecl (node))
25825 {
25826 SgTemplateArgumentPtrList& plist = sn->get_templateArguments();
25827 bool n_hasRemaining=false;
25828 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25829 string suffix= hasRemaining? "| " : " ";
25830 string n_prefix = prefix+suffix;
25831 string n_edge_label= "";
25832 serialize_list(plist, "SgTemplateArgumentPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25833 }
25834 else if (SgImportStatement* import_stmt = isSgImportStatement(node))
25835 {
25836 SgExpressionPtrList& plist = import_stmt->get_import_list();
25837 bool n_hasRemaining=false;
25838 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25839 string suffix= hasRemaining? "| " : " ";
25840 string n_prefix = prefix+suffix;
25841 string n_edge_label= "";
25842 serialize_list(plist, "SgExpressionPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25843 }
25844
25845 std::vector< std::string > successorNames= node->get_traversalSuccessorNamesContainer();
25846
25847 // finish sucessors
25848 for (size_t i =0; i< children.size(); i++)
25849 {
25850 bool n_hasRemaining=false;
25851#if 0
25852 if (current_index+1<total_count)
25853 n_hasRemaining=true;
25854 current_index++;
25855#else
25856 if ((int)i<last_non_null_child_idx) n_hasRemaining = true;
25857#endif
25858 string suffix= hasRemaining? "| " : " ";
25859 string n_prefix = prefix+suffix;
25860 if (children[i])
25861 serialize (children[i], n_prefix, n_hasRemaining, out, successorNames[i]);
25862 }
25863}
25864
25866{
25867 ostringstream oss;
25868 string prefix;
25869 string label="";
25870 serialize(node, prefix, false, oss, label);
25871 cout<<oss.str();
25872}
25873
25874void SageInterface::printAST(SgNode* node, const char* filename)
25875{
25876 printAST2TextFile(node, filename, true);
25877}
25878
25879void SageInterface::printAST2TextFile (SgNode* node, std::string filename, bool printType/*=true*/)
25880{
25881 // Rasmussen 9/21/2020: This leads to infinite recursion (clang warning message) and should be removed from API)
25882// ROSE_ABORT();
25883 printAST2TextFile (node, filename.c_str(), printType);
25884}
25885
25886void SageInterface::printAST2TextFile(SgNode* node, const char* filename, bool printType/*=true*/)
25887{
25888 ostringstream oss;
25889 string prefix;
25890 string label="";
25891 serialize(node, prefix, false, oss, label);
25892 ofstream textfile;
25893 textfile.open(filename, ios::out);
25894 textfile<<oss.str();
25895
25896 if (printType)
25897 {
25898 // append type information also
25899 textfile<<"Types encountered ...."<<endl;
25900 ostringstream oss2;
25901 VariantVector vv(V_SgType);
25902 Rose_STL_Container<SgNode*> tnodes= NodeQuery::queryMemoryPool(vv);
25903 for (Rose_STL_Container<SgNode*>::const_iterator i = tnodes.begin(); i != tnodes.end(); ++i)
25904 {
25905 serialize (*i, prefix, false, oss2, label);
25906 }
25907 textfile<<oss2.str();
25908 }
25909
25910 textfile.close();
25911}
25912
25914{
25915 saveToPDF(node, string("temp.pdf.json") );
25916}
25918// node to find its enclosing file node. The entire file's AST will be saved into a pdf.
25919void SageInterface:: saveToPDF(SgNode* node, std::string filename)
25920{
25921 ROSE_ASSERT(node != NULL);
25922 AstJSONGeneration json;
25923 json.generateWithinFile(filename, getEnclosingFileNode(node));
25924}
25925
25927{
25928 bool rtval = false;
25929 ROSE_ASSERT (node != NULL);
25930 Sg_File_Info* finfo = node->get_file_info();
25931 if (finfo!=NULL)
25932 {
25933 string fname = finfo->get_filenameString();
25934 string buildtree_str1 = string("include-staging/gcc_HEADERS");
25935 string buildtree_str2 = string("include-staging/g++_HEADERS");
25936 string installtree_str1 = string("include/edg/gcc_HEADERS");
25937 string installtree_str2 = string("include/edg/g++_HEADERS");
25938 string system_headers = string("/usr/include");
25939 // if the file name has a sys header path of either source or build tree
25940 if ((fname.find (buildtree_str1, 0) != string::npos) ||
25941 (fname.find (buildtree_str2, 0) != string::npos) ||
25942 (fname.find (installtree_str1, 0) != string::npos) ||
25943 (fname.find (installtree_str2, 0) != string::npos) ||
25944 (fname.find (system_headers, 0) != string::npos)
25945 )
25946 rtval = true;
25947 }
25948 return rtval;
25949}
25950
25951
25952// DQ (2/27/2021): Adding support to detect if a SgLocatedNode is located in a header file.
25954 {
25955 // Check if a node is from a header file
25956
25957 bool returnValue = false;
25958
25959 Sg_File_Info* fileInfo = node->get_file_info();
25960 ROSE_ASSERT(fileInfo != NULL);
25961 string filename = fileInfo->get_filenameString();
25962
25963#if 0
25964 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());
25965#endif
25966
25967 // DQ (2/27/2021): We save a map of all of the header files processed in the generation of the ROSE AST,
25968 // so the test is only if the filename is in the list.
25969 if (EDG_ROSE_Translation::edg_include_file_map.find(filename) == EDG_ROSE_Translation::edg_include_file_map.end())
25970 {
25971#if 0
25972 printf ("This is NOT in the EDG_ROSE_Translation::edg_include_file_map \n");
25973#endif
25974 }
25975 else
25976 {
25977#if 0
25978 printf ("This IS in the EDG_ROSE_Translation::edg_include_file_map \n");
25979#endif
25980 returnValue = true;
25981 }
25982
25983 return returnValue;
25984 }
25985
25986
25989{
25990 ROSE_ASSERT(return_type != NULL);
25991 ROSE_ASSERT(typeList != NULL);
25993 ROSE_ASSERT(fTable);
25994
25995 // This function make clever use of a static member function which can't be built
25996 // for the case of a SgMemberFunctionType (or at least not without more work).
25997 SgName typeName = SgFunctionType::get_mangled(return_type, typeList);
25998 SgFunctionType* funcType = isSgFunctionType(fTable->lookup_function_type(typeName));
25999
26000 return funcType;
26001}
26002
26007{
26008 ROSE_ASSERT (lhs != NULL);
26009 ROSE_ASSERT (rhs != NULL);
26010 if (lhs == rhs)
26011 return true;
26012
26013 bool rt = false;
26014 SgType* rt1 = lhs->get_return_type();
26015 SgType* rt2 = rhs->get_return_type();
26016
26017 if (isEquivalentType (rt1, rt2))
26018 {
26019 SgTypePtrList f1_arg_types = lhs->get_arguments();
26020 SgTypePtrList f2_arg_types = rhs->get_arguments();
26021 // Must have same number of argument types
26022 if (f1_arg_types.size() == f2_arg_types.size())
26023 {
26024 // DQ (2/16/2017): Fixed compiler warning about comparison between signed and unsigned integers
26025 // int counter = 0;
26026 size_t counter = 0;
26027 // iterate through all argument types
26028 // for (int i=0; i< f1_arg_types.size(); i++)
26029 for (size_t i=0; i< f1_arg_types.size(); i++)
26030 {
26031 if (isEquivalentType (f1_arg_types[i], f2_arg_types[i]) )
26032 counter ++; // count the number of equal arguments
26033 else
26034 break; // found different type? jump out the loop
26035 }
26036 // all arguments are equivalent, set to true
26037 if (counter == f1_arg_types.size())
26038 rt = true;
26039 }
26040 } // end if equivalent return types
26041
26042 return rt;
26043}
26044
26045bool
26047 {
26048 // This function is called in the SgType::isEquivalentType (const SgType & Y) const function.
26049
26050 // DQ (11/28/2015): A better goal for this function should be to define it as a recursive function.
26051
26052 // DQ (12/8/2015): We need to add support for SgMemberFunctionType as demonstrated by test2007_17.C.
26053 // and for SgTemplateType as demonstrated by tests/nonsmoke/functional/CompileTests/RoseExample_tests/testRoseHeaders_03.C
26054 // Note that this is only required within the change to use this isEquivalentType() function in the
26055 // support to replace:
26056 // templateParameterOrArgumentLocal->get_initializedName()->get_type() == templateParameterOrArgumentFromSymbol->get_initializedName()->get_type()
26057 // in ROSETTA/Grammar/Support.code
26058
26059 ROSE_ASSERT(lhs != NULL);
26060 ROSE_ASSERT(rhs != NULL);
26061
26062 bool isSame = false;
26063
26064 // 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).
26065 static int counter = 0;
26066
26067 const SgType & X = *lhs;
26068 const SgType & Y = *rhs;
26069
26070 // DQ (11/28/2015): We don't want to strip off everything.
26071 // SgType* stripType(unsigned char bit_array = STRIP_MODIFIER_TYPE | STRIP_REFERENCE_TYPE | STRIP_POINTER_TYPE | STRIP_ARRAY_TYPE | STRIP_TYPEDEF_TYPE ) const;
26072
26073 // I think we need to compute the type chain to evaluate equalence.
26074 // Rose_STL_Container< SgType*> getInternalTypes () const
26075
26076#define DEBUG_TYPE_EQUIVALENCE 0
26077
26078#if DEBUG_TYPE_EQUIVALENCE
26079 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
26080 printf (" --- lhs = %s \n",lhs->unparseToString().c_str());
26081 printf (" --- rhs = %s \n",rhs->unparseToString().c_str());
26082#endif
26083
26084#if DEBUG_TYPE_EQUIVALENCE || 0
26085 if (counter == 0)
26086 {
26087 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
26088 printf (" --- lhs = %p = %s = %s \n",lhs,lhs->class_name().c_str(),lhs->unparseToString().c_str());
26089 printf (" --- rhs = %p = %s = %s \n",rhs,rhs->class_name().c_str(),rhs->unparseToString().c_str());
26090 }
26091#endif
26092
26093#if DEBUG_TYPE_EQUIVALENCE || 0
26094 // Debugging output.
26095 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26096 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26097
26098 // Debugging output.
26099 printf ("Output of type chain for lhs: \n");
26100 for (size_t i = 0; i < X_typeChain.size(); i++)
26101 {
26102 SgType* element_type = X_typeChain[i];
26103 printf ("X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26104 printf (" --- X_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
26105 SgModifierType* modifierType = isSgModifierType(element_type);
26106 if (modifierType != NULL)
26107 {
26108 // modifierType->get_typeModifier().display("X type chain");
26109 string s = modifierType->get_typeModifier().displayString();
26110 printf (" --- type chain modifier: %s \n",s.c_str());
26111 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
26112 }
26113 }
26114
26115 printf ("Output of type chain for rhs: \n");
26116 for (size_t i = 0; i < Y_typeChain.size(); i++)
26117 {
26118 SgType* element_type = Y_typeChain[i];
26119 printf ("Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26120 printf (" --- Y_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
26121 SgModifierType* modifierType = isSgModifierType(element_type);
26122 if (modifierType != NULL)
26123 {
26124 // modifierType->get_typeModifier().display("Y type chain");
26125 string s = modifierType->get_typeModifier().displayString();
26126 printf (" --- type chain modifier: %s \n",s.c_str());
26127 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
26128 }
26129 }
26130#endif
26131
26132 // Increment the static variable to control the recursive depth while we debug this.
26133 counter++;
26134
26135 // DQ (11/28/2015): exit with debug output instead of infinte recursion.
26136 // if (counter >= 280)
26137 // if (counter >= 500)
26138 if (counter >= 280)
26139 {
26140 // 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());
26141 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);
26142 }
26143
26144 // DQ (12/23/2015): ASC application code requires this to be increased to over 122 (selected 300 for extra margin of safety).
26145 // DQ (11/28/2015): exit in stead of infinte recursion.
26146 // if (counter > 300)
26147 // if (counter > 600)
26148 // if (counter > 5000)
26149 // if (counter > 300)
26150 if (counter > 350)
26151 {
26152 // DQ (11/28/2015): I think this is a reasonable limit.
26153 printf ("ERROR: In SageInterface::isEquivalentType(): recursive limit exceeded for : counter = %d \n",counter);
26154 ROSE_ABORT();
26155 }
26156
26157 // bool exit = false;
26158
26159 // Strip off any typedefs since they are equivalent by definition.
26160 SgType* X_element_type = X.stripType( SgType::STRIP_TYPEDEF_TYPE );
26161 SgType* Y_element_type = Y.stripType( SgType::STRIP_TYPEDEF_TYPE );
26162
26163 // DQ (11/29/2015): We need to handle references (when they are both references we can support then uniformally).
26164 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26165 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26166
26167 if (X_referenceType != NULL && Y_referenceType != NULL)
26168 {
26169 X_element_type = X_referenceType->get_base_type();
26170 Y_element_type = Y_referenceType->get_base_type();
26171
26172 counter--;
26173
26174 // Recursive call.
26175 // return (*X_element_type) == (*Y_element_type);
26176 return isEquivalentType(X_element_type,Y_element_type);
26177 }
26178 else
26179 {
26180 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26181 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26182 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26183
26184 if (X_pointerType != NULL && Y_pointerType != NULL)
26185 {
26186 X_element_type = X_pointerType->get_base_type();
26187 Y_element_type = Y_pointerType->get_base_type();
26188
26189 counter--;
26190
26191 // Recursive call.
26192 // return (*X_element_type) == (*Y_element_type);
26193 return isEquivalentType(X_element_type,Y_element_type);
26194 }
26195 else
26196 {
26197 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26198 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26199 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26200
26201 // DQ (12/8/2015): We need to check that the array size is the same.
26202 if (X_arrayType != NULL && Y_arrayType != NULL)
26203 {
26204 X_element_type = X_arrayType->get_base_type();
26205 Y_element_type = Y_arrayType->get_base_type();
26206
26207 SgExpression* X_array_index_expression = X_arrayType->get_index();
26208 SgExpression* Y_array_index_expression = Y_arrayType->get_index();
26209
26210 if (X_array_index_expression == Y_array_index_expression)
26211 {
26212#if DEBUG_TYPE_EQUIVALENCE || 0
26213 printf ("In SageInterface::isEquivalentType(): counter = %d: Need to check the array size for static equivalence \n",counter);
26214#endif
26215 counter--;
26216
26217 // Recursive call.
26218 // return (*X_element_type) == (*Y_element_type);
26219 return isEquivalentType(X_element_type,Y_element_type);
26220 }
26221 else
26222 {
26223 // Need more complex test for expression equivalence.
26224#if DEBUG_TYPE_EQUIVALENCE || 0
26225 printf ("In SageInterface::isEquivalentType(): counter = %d Need more complex test for expression equivalence \n",counter);
26226 string str1 = X_array_index_expression->unparseToString();
26227 string str2 = Y_array_index_expression->unparseToString();
26228 printf (" --- array index expressions: str1 = %s str2 = %s \n",str1.c_str(),str2.c_str());
26229#endif
26230 // DQ (12/9/2016): Need to decriment the counter as part of recursive function call.
26231 counter--;
26232
26233 // Recursive call.
26234 return isEquivalentType(X_element_type,Y_element_type);
26235 }
26236 }
26237 else
26238 {
26239 // DQ (12/15/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26240 SgNonrealType* X_templateType = isSgNonrealType(X_element_type);
26241 SgNonrealType* Y_templateType = isSgNonrealType(Y_element_type);
26242
26243 // DQ (12/15/2015): We need to check that the array size is the same.
26244 if (X_templateType != NULL && Y_templateType != NULL)
26245 {
26246 string X_name = X_templateType->get_name();
26247 string Y_name = Y_templateType->get_name();
26248
26249 SgNonrealDecl* X_templateDecl = isSgNonrealDecl(X_templateType->get_declaration());
26250 ROSE_ASSERT(X_templateDecl != NULL);
26251 SgNonrealDecl* Y_templateDecl = isSgNonrealDecl(Y_templateType->get_declaration());
26252 ROSE_ASSERT(Y_templateDecl != NULL);
26253
26254 int X_template_parameter_position = X_templateDecl->get_template_parameter_position();
26255 int Y_template_parameter_position = Y_templateDecl->get_template_parameter_position();
26256
26257 SgNode * X_parent = X_templateDecl->get_parent();
26258 SgNode * Y_parent = Y_templateDecl->get_parent();
26259
26260#if DEBUG_TYPE_EQUIVALENCE
26261 SgNode * X_parent_parent = X_parent ? X_parent->get_parent() : NULL;
26262 SgNode * Y_parent_parent = Y_parent ? Y_parent->get_parent() : NULL;
26263 printf ("In SageInterface::isEquivalentType(): case SgNonrealType:\n");
26264 printf (" -- X_name = %s Y_name = %s\n", X_name.c_str(),Y_name.c_str());
26265 printf (" -- X_template_parameter_position = %d Y_template_parameter_position = %d\n", X_template_parameter_position,Y_template_parameter_position);
26266 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() : "");
26267 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() : "");
26268 printf (" -- X_templateDecl->get_mangled_name() = %s\n", X_templateDecl->get_mangled_name().str());
26269 printf (" -- Y_templateDecl->get_mangled_name() = %s\n", Y_templateDecl->get_mangled_name().str());
26270#endif
26271 bool value = (X_parent == Y_parent);
26272
26273 if (value && X_templateDecl->get_is_template_param() && Y_templateDecl->get_is_template_param()) {
26274 value = (X_template_parameter_position == Y_template_parameter_position);
26275 } else if (value && X_templateDecl->get_is_class_member() && Y_templateDecl->get_is_class_member()) {
26276 value = (X_name == Y_name);
26277 }
26278
26279 counter--;
26280
26281 return value;
26282 }
26283 else
26284 {
26285 // DQ (2/13/2018): I an unclear if we are really done since they could have resolved to different types or the same type.
26286 // Nothing to do here since we have explored all uniform pairs of intermediate types possible.
26287#if 0
26288 printf ("Nothing to do here since we have explored all uniform pairs of intermediate types possible: isSame = %s \n",isSame ? "true" : "false");
26289 // printf (" --- X_element_type = %p = %s \n",X_element_type,X_element_type->unparseToString().c_str());
26290 // printf (" --- Y_element_type = %p = %s \n",Y_element_type,Y_element_type->unparseToString().c_str());
26291 printf (" --- lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26292 printf (" --- rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26293#endif
26294#if DEBUG_TYPE_EQUIVALENCE
26295 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");
26296#endif
26297 }
26298 }
26299 }
26300 } // end if reference type, pointer type, array type, and template type
26301
26302 SgModifierType* X_modifierType = isSgModifierType(X_element_type);
26303 SgModifierType* Y_modifierType = isSgModifierType(Y_element_type);
26304
26305#if DEBUG_TYPE_EQUIVALENCE
26306 printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %p = %s Y_element_type = %p = %s \n",
26307 counter,X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26308#endif
26309
26310 if (X_modifierType != NULL && Y_modifierType != NULL)
26311 {
26312 // Handle the case of both modifiers.
26313#if DEBUG_TYPE_EQUIVALENCE
26314 printf ("In SageInterface::isEquivalentType(): loop: these are the both SgModifierType nodes: isSame = %s \n",isSame ? "true" : "false");
26315#endif
26316 if (X_modifierType == Y_modifierType)
26317 {
26318 isSame = true;
26319#if DEBUG_TYPE_EQUIVALENCE
26320 printf ("In SageInterface::isEquivalentType(): loop: these are the same modifier type: isSame = %s \n",isSame ? "true" : "false");
26321#endif
26322 }
26323 else
26324 {
26325 if (X_modifierType->get_typeModifier() == Y_modifierType->get_typeModifier())
26326 {
26327#if DEBUG_TYPE_EQUIVALENCE
26328 printf ("In SageInterface::isEquivalentType(): loop: these are equivalent modifiers: check the base type: isSame = %s \n",isSame ? "true" : "false");
26329#endif
26330 // Recursive call.
26331 // isSame = (*X_modifierType->get_base_type()) == (*Y_modifierType->get_base_type());
26332 isSame = isEquivalentType(X_modifierType->get_base_type(),Y_modifierType->get_base_type());
26333 }
26334 else
26335 {
26336#if DEBUG_TYPE_EQUIVALENCE
26337 printf ("In SageInterface::isEquivalentType(): loop: these are not equivalent modifier types: check for default settings: isSame = %s \n",isSame ? "true" : "false");
26338#endif
26339 // DQ (5/22/2016): fixing bug which cansed infinite recursion (case there the SgModifiers were different).
26340 bool skippingOverIdentityModifier = false;
26341
26342 if (X_modifierType->get_typeModifier().isIdentity() == true)
26343 {
26344#if DEBUG_TYPE_EQUIVALENCE
26345 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26346#endif
26347 X_element_type = X_modifierType->get_base_type();
26348
26349 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26350 skippingOverIdentityModifier = true;
26351 }
26352
26353 if (Y_modifierType->get_typeModifier().isIdentity() == true)
26354 {
26355#if DEBUG_TYPE_EQUIVALENCE
26356 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26357#endif
26358 Y_element_type = Y_modifierType->get_base_type();
26359
26360 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26361 skippingOverIdentityModifier = true;
26362 }
26363
26364 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26365#if DEBUG_TYPE_EQUIVALENCE
26366 printf ("In SageInterface::isEquivalentType(): loop: skippingOverIdentityModifier = %s \n",skippingOverIdentityModifier ? "true" : "false");
26367#endif
26368 // Recursive call on non-default modifier base types.
26369 // isSame = (*X_element_type) == (*Y_element_type);
26370 // isSame = isEquivalentType(X_element_type,Y_element_type);
26371 if (skippingOverIdentityModifier == true)
26372 {
26373#if DEBUG_TYPE_EQUIVALENCE
26374 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");
26375#endif
26376 // If we have made progress in skipping over an identity modifier then we need to reevaluate if these are the equivalent types.
26377 isSame = isEquivalentType(X_element_type,Y_element_type);
26378 }
26379 else
26380 {
26381 // 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).
26382 isSame = false;
26383#if DEBUG_TYPE_EQUIVALENCE
26384 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");
26385#endif
26386 }
26387
26388#if DEBUG_TYPE_EQUIVALENCE
26389 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isSame = %s \n",isSame ? "true" : "false");
26390#endif
26391 }
26392 }
26393 }
26394 else
26395 {
26396 // At least one of these is not a SgModifierType.
26397
26398 if (X_modifierType != NULL || Y_modifierType != NULL)
26399 {
26400 bool isReduceable = false;
26401
26402 if (X_modifierType != NULL && X_modifierType->get_typeModifier().isIdentity() == true)
26403 {
26404#if DEBUG_TYPE_EQUIVALENCE
26405 printf ("In SageInterface::isEquivalentType(): loop: found default setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26406#endif
26407 X_element_type = X_modifierType->get_base_type();
26408 isReduceable = true;
26409 }
26410
26411 if (Y_modifierType != NULL && Y_modifierType->get_typeModifier().isIdentity() == true)
26412 {
26413#if DEBUG_TYPE_EQUIVALENCE
26414 printf ("In SageInterface::isEquivalentType(): loop: found default setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26415#endif
26416 Y_element_type = Y_modifierType->get_base_type();
26417 isReduceable = true;
26418 }
26419
26420 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26421#if DEBUG_TYPE_EQUIVALENCE
26422 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s \n",isReduceable ? "true" : "false");
26423#endif
26424 if (isReduceable == true)
26425 {
26426 // Recursive call on non-default modifier base types.
26427 // isSame = (*X_element_type) == (*Y_element_type);
26428 isSame = isEquivalentType(X_element_type,Y_element_type);
26429 }
26430 else
26431 {
26432 // Neither of these types were reducable.
26433 isSame = false;
26434 }
26435
26436#if DEBUG_TYPE_EQUIVALENCE
26437 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s isSame = %s \n",
26438 isReduceable ? "true" : "false",isSame ? "true" : "false");
26439#endif
26440 }
26441 else
26442 {
26443 // Neither of these are SgModifierType nodes.
26444 // X_element_type = X_element_type->stripType( STRIP_TYPEDEF_TYPE );
26445 // Y_element_type = Y_element_type->stripType( STRIP_TYPEDEF_TYPE );
26446
26447 if (X_element_type == Y_element_type)
26448 {
26449 isSame = true;
26450#if DEBUG_TYPE_EQUIVALENCE || 0
26451 // printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s \n",isSame ? "true" : "false");
26452 printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s lhs = %p = %s rhs = %p = %s \n",
26453 isSame ? "true" : "false",lhs,lhs->unparseToString().c_str(),rhs,rhs->unparseToString().c_str());
26454#endif
26455#if DEBUG_TYPE_EQUIVALENCE || 0
26456 // DQ (2/13/2018): Debugging type equivalence. If they are the same typedef, they
26457 // still might not be interchangable if one is defined in a restrcited scope.
26458 const SgTypedefType* lhs_typedefType = isSgTypedefType(lhs);
26459 const SgTypedefType* rhs_typedefType = isSgTypedefType(rhs);
26460
26461 if (lhs_typedefType != NULL || rhs_typedefType != NULL)
26462 {
26463#if 0
26464 if (lhs_typedefType != NULL)
26465 {
26466 printf ("lhs was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26467 }
26468 if (rhs_typedefType != NULL)
26469 {
26470 printf ("rhs was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26471 }
26472#else
26473 printf (" --- one was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26474 printf (" --- one was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26475#endif
26476 }
26477#endif
26478 }
26479 else
26480 {
26481 // DQ (3/20/2016): This is reported by GNU as set but not used.
26482 // bool isReduceable = false;
26483
26484 // DQ (11/29/2015): We need to handle reference (when they are both references we can support then uniformally).
26485 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26486 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26487
26488 if (X_referenceType != NULL || Y_referenceType != NULL)
26489 {
26490#if 0
26491 if (X_referenceType != NULL)
26492 {
26493 X_element_type = X_referenceType->get_base_type();
26494
26495 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26496 // isReduceable = true;
26497 isReduceable = false;
26498 }
26499
26500 if (Y_referenceType != NULL)
26501 {
26502 Y_element_type = Y_referenceType->get_base_type();
26503
26504 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26505 // isReduceable = true;
26506 isReduceable = false;
26507 }
26508
26509 if (isReduceable == true)
26510 {
26511 // Recursive call on non-default modifier base types.
26512 // isSame = (*X_element_type) == (*Y_element_type);
26513 isSame = isEquivalentType(X_element_type,Y_element_type);
26514 }
26515 else
26516 {
26517 // Neither of these types were reducable.
26518 isSame = false;
26519 }
26520#else
26521 isSame = false;
26522#endif
26523 }
26524 else
26525 {
26526 // Recursive call on non-typedef base types.
26527 // isSame = (*X_element_type) == (*Y_element_type);
26528 // isSame = isEquivalentType(X_element_type,Y_element_type);
26529
26530#if DEBUG_TYPE_EQUIVALENCE
26531 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26532#endif
26533
26534 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26535 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26536 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26537
26538 if (X_pointerType != NULL || Y_pointerType != NULL)
26539 {
26540#if 0
26541 if (X_pointerType != NULL)
26542 {
26543 X_element_type = X_pointerType->get_base_type();
26544
26545 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26546 // isReduceable = true;
26547 isReduceable = false;
26548 }
26549
26550 if (Y_pointerType != NULL)
26551 {
26552 Y_element_type = Y_pointerType->get_base_type();
26553
26554 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26555 // isReduceable = true;
26556 isReduceable = false;
26557 }
26558
26559 if (isReduceable == true)
26560 {
26561 // Recursive call on non-default modifier base types.
26562 // isSame = (*X_element_type) == (*Y_element_type);
26563 isSame = isEquivalentType(X_element_type,Y_element_type);
26564 }
26565 else
26566 {
26567 // Neither of these types were reducable.
26568 isSame = false;
26569 }
26570#else
26571 isSame = false;
26572#endif
26573 }
26574 else
26575 {
26576 // Recursive call on non-typedef base types.
26577 // isSame = (*X_element_type) == (*Y_element_type);
26578 // isSame = isEquivalentType(X_element_type,Y_element_type);
26579
26580#if DEBUG_TYPE_EQUIVALENCE
26581 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26582#endif
26583
26584 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26585 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26586 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26587
26588 if (X_arrayType != NULL || Y_arrayType != NULL)
26589 {
26590#if 0
26591 if (X_arrayType != NULL)
26592 {
26593 X_element_type = X_arrayType->get_base_type();
26594
26595 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26596 // isReduceable = true;
26597 isReduceable = false;
26598 }
26599
26600 if (Y_arrayType != NULL)
26601 {
26602 Y_element_type = Y_arrayType->get_base_type();
26603
26604 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26605 // isReduceable = true;
26606 isReduceable = false;
26607 }
26608
26609 if (isReduceable == true)
26610 {
26611 // Recursive call on non-default modifier base types.
26612 // isSame = (*X_element_type) == (*Y_element_type);
26613 isSame = isEquivalentType(X_element_type,Y_element_type);
26614 }
26615 else
26616 {
26617 // Neither of these types were reducable.
26618 isSame = false;
26619 }
26620#else
26621 isSame = false;
26622#endif
26623 }
26624 else
26625 {
26626 // Recursive call on non-typedef base types.
26627 // isSame = (*X_element_type) == (*Y_element_type);
26628 // isSame = isEquivalentType(X_element_type,Y_element_type);
26629
26630#if DEBUG_TYPE_EQUIVALENCE
26631 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26632#endif
26633
26634 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26635 SgFunctionType* X_functionType = isSgFunctionType(X_element_type);
26636 SgFunctionType* Y_functionType = isSgFunctionType(Y_element_type);
26637
26638 if (X_functionType != NULL || Y_functionType != NULL)
26639 {
26640 bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (X_functionType == Y_functionType) );
26641 //TODO: Liao, 9/15/2016, better comparison of function types
26642 //bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (isEquivalentFunctionType(X_functionType, Y_functionType)) );
26643#if DEBUG_TYPE_EQUIVALENCE || 0
26644 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgFunctionType: value = %s \n",value ? "true" : "false");
26645#endif
26646 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26647 // isSame == value;
26648 isSame = value;
26649
26650 // DQ (3/20/2016): This is reported by GNU as set but not used.
26651 // isReduceable = false;
26652 }
26653 else
26654 {
26655 // Recursive call on non-typedef base types.
26656 // isSame = isEquivalentType(X_element_type,Y_element_type);
26657
26658 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26659 SgMemberFunctionType* X_memberFunctionType = isSgMemberFunctionType(X_element_type);
26660 SgMemberFunctionType* Y_memberFunctionType = isSgMemberFunctionType(Y_element_type);
26661
26662 if (X_memberFunctionType != NULL || Y_memberFunctionType != NULL)
26663 {
26664 // DQ (12/15/2015): This code should be unreachable since it would have executed the code above (the case of SgFunctionType).
26665 printf ("This should be unreachable code \n");
26666 ROSE_ABORT();
26667
26668#if 0 // [Robb Matzke 2021-03-24]: unreachable
26669 bool value = ( (X_memberFunctionType != NULL && Y_memberFunctionType != NULL) && (X_memberFunctionType == Y_memberFunctionType) );
26670#if DEBUG_TYPE_EQUIVALENCE || 0
26671 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgMemberFunctionType: value = %s \n",value ? "true" : "false");
26672#endif
26673 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26674 // isSame == value;
26675 isSame = value;
26676#endif
26677 }
26678 else
26679 {
26680 // Recursive call on non-typedef base types.
26681 // isSame = isEquivalentType(X_element_type,Y_element_type);
26682#if 0
26683 // Check for irreducable types.
26684 bool X_isReduceable = true;
26685 if (isSgTypeSignedLong(X_element_type) != NULL ||
26686 isSgTypeUnsignedInt(X_element_type) != NULL ||
26687 isSgTypeBool(X_element_type) != NULL ||
26688 isSgTypeInt(X_element_type) != NULL)
26689 {
26690 X_isReduceable = false;
26691 }
26692
26693 bool Y_isReduceable = true;
26694 if (isSgTypeSignedLong(Y_element_type) != NULL ||
26695 isSgTypeUnsignedInt(Y_element_type) != NULL ||
26696 isSgTypeBool(Y_element_type) != NULL ||
26697 isSgTypeInt(Y_element_type) != NULL)
26698 {
26699 Y_isReduceable = false;
26700 }
26701#if DEBUG_TYPE_EQUIVALENCE || 0
26702 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_isReduceable = %s Y_isReduceable = %s \n",
26703 X_isReduceable ? "true" : "false",Y_isReduceable ? "true" : "false");
26704#endif
26705 if (X_isReduceable == true || Y_isReduceable == true)
26706 {
26707 // Recursive call on non-default modifier base types.
26708 isSame = isEquivalentType(X_element_type,Y_element_type);
26709 }
26710 else
26711 {
26712 // Neither of these types were reducable.
26713 isSame = false;
26714 }
26715#else
26716 // DQ (12/20/2015): This is the default case for irreducable types.
26717 if (X_element_type->variantT() == Y_element_type->variantT())
26718 {
26719#if DEBUG_TYPE_EQUIVALENCE || 0
26720 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_element_type = %p = %s Y_element_type = %p = %s \n",
26721 X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26722#endif
26723 // DQ (5/26/2016): It is not good enough that the variants match.
26724 // isSame = true;
26725 // isSame = isEquivalentType(X_element_type,Y_element_type);
26726 isSame = (X_element_type == Y_element_type);
26727 }
26728 else
26729 {
26730 // Neither of these types were reducable or equal.
26731 isSame = false;
26732 }
26733#endif
26734 }
26735 }
26736 }
26737 }
26738 }
26739 }
26740 }
26741 }
26742
26743 // Decrement the static variable to control the recursive depth while we debug this.
26744 counter--;
26745
26746#if DEBUG_TYPE_EQUIVALENCE || 0
26747 printf ("In SageInterface::isEquivalentType(): isSame = %s \n",isSame ? "true" : "false");
26748#endif
26749
26750#if DEBUG_TYPE_EQUIVALENCE || 0
26751 if (counter == 1 && isSame == true)
26752 {
26753 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());
26754
26755 // Debugging output.
26756 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26757 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26758
26759 // Debugging output.
26760 printf (" --- Output of type chain for lhs: \n");
26761 for (size_t i = 0; i < X_typeChain.size(); i++)
26762 {
26763 SgType* element_type = X_typeChain[i];
26764 printf (" --- --- X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26765 SgModifierType* modifierType = isSgModifierType(element_type);
26766 if (modifierType != NULL)
26767 {
26768 // modifierType->get_typeModifier().display("X type chain");
26769 string s = modifierType->get_typeModifier().displayString();
26770 printf (" --- type chain modifier: %s \n",s.c_str());
26771 }
26772 }
26773
26774 printf (" --- Output of type chain for rhs: \n");
26775 for (size_t i = 0; i < Y_typeChain.size(); i++)
26776 {
26777 SgType* element_type = Y_typeChain[i];
26778 printf (" --- --- Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26779 SgModifierType* modifierType = isSgModifierType(element_type);
26780 if (modifierType != NULL)
26781 {
26782 // modifierType->get_typeModifier().display("Y type chain");
26783 string s = modifierType->get_typeModifier().displayString();
26784 printf (" --- --- type chain modifier: %s \n",s.c_str());
26785 }
26786 }
26787 }
26788#endif
26789
26790#if 0
26791 if (counter == 0)
26792 {
26793 if (isSame == true)
26794 {
26795 // 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());
26796 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26797 // printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26798 // printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26799 printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26800 printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26801 }
26802 else
26803 {
26804 // 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());
26805 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26806 }
26807 }
26808 else
26809 {
26810 printf (" --- counter = %d \n",counter);
26811 }
26812#endif
26813
26814 return isSame;
26815 }
26816
26817
26818#if 0
26819// This is modified to be a template function and so must be moved to the header file.
26820// DQ (8/30/2016): Added function to detect EDG AST normalization.
26821bool
26822SageInterface::isNormalizedTemplateInstantiation (SgFunctionDeclaration* function)
26823 {
26824 // This function is called in the Call graph generation to avoid filtering out EDG normalized
26825 // function template instnatiations (which come from normalized template functions and member functions).
26826
26827 bool retval = false;
26828
26829#if 1
26830 // DQ (8/30/2016): We need to mark this as an EDG normalization so that we can detect it as an exception
26831 // to some simple attempts to filter the AST (e.g. for the Call Graph implementation which filters on only
26832 // functions in the current directory). This explicit makring makes it much easier to get this test correct.
26833 // But we still need to look at if the location of the parent template is something that we wnat to output.
26834 // If tis is a template instantiation then it is not enough to look only at the non-defining declaration if
26835 // it is not compiler generated.
26836 retval = function->get_marked_as_edg_normalization();
26837#else
26838 // Test for this to be a template instantation (in which case it was marked as
26839 // compiler generated but we may want to allow it to be used in the call graph,
26840 // if it's template was a part was defined in the current directory).
26841 SgTemplateInstantiationFunctionDecl* templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(function);
26842 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(function);
26843
26844 if (templateInstantiationFunction != NULL)
26845 {
26846 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26847 templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(templateInstantiationFunction->get_firstNondefiningDeclaration());
26848 SgTemplateFunctionDeclaration* templateFunctionDeclaration = templateInstantiationFunction->get_templateDeclaration();
26849 if (templateFunctionDeclaration != NULL)
26850 {
26851 // retval = operator()(templateFunctionDeclaration);
26852 retval = (templateFunctionDeclaration->isCompilerGenerated() == false);
26853 }
26854 else
26855 {
26856 // Assume false.
26857 }
26858
26859#if DEBUG_SELECTOR
26860 printf (" --- case of templateInstantiationFunction: retval = %s \n",retval ? "true" : "false");
26861#endif
26862 }
26863 else
26864 {
26865 if (templateInstantiationMemberFunction != NULL)
26866 {
26867 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26868 templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(templateInstantiationMemberFunction->get_firstNondefiningDeclaration());
26869 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = templateInstantiationMemberFunction->get_templateDeclaration();
26870 if (templateMemberFunctionDeclaration != NULL)
26871 {
26872 // retval = operator()(templateMemberFunctionDeclaration);
26873 retval = (templateMemberFunctionDeclaration->isCompilerGenerated() == false);
26874 }
26875 else
26876 {
26877 // Assume false.
26878 }
26879
26880#if DEBUG_SELECTOR
26881 printf (" --- case of templateInstantiationMemberFunction: retval = %s \n",retval ? "true" : "false");
26882#endif
26883 }
26884 }
26885#endif
26886
26887 return retval;
26888 }
26889#endif
26890
26891void SageInterface::detectCycleInType(SgType * type, const std::string & from) {
26892#if 0
26893 printf("In detectCycleInType():\n");
26894 printf(" -- from = %s\n", from.c_str());
26895 printf(" -- type = %p (%s)\n", type, type->class_name().c_str());
26896#endif
26897 std::vector<SgType *> seen_types;
26898
26899 while (type != NULL) {
26900
26901 // DQ (4/15/2019): Added assertion.
26902 ROSE_ASSERT(type != NULL);
26903
26904 std::vector<SgType *>::const_iterator it = std::find(seen_types.begin(), seen_types.end(), type);
26905 if (it != seen_types.end()) {
26906 printf("ERROR: Cycle found in type = %p (%s):\n", type, type->class_name().c_str());
26907 size_t i = 0;
26908 for (; it != seen_types.end(); it++) {
26909 printf(" [%zd] %p (%s)\n", i, *it, (*it)->class_name().c_str());
26910 i++;
26911 }
26912 printf("-> detectCycleInType() was called from: %s\n", from.c_str());
26913 ROSE_ABORT();
26914 }
26915 seen_types.push_back(type);
26916
26917 SgModifierType * modType = isSgModifierType(type);
26918 SgPointerType * pointType = isSgPointerType(type);
26919 SgReferenceType * refType = isSgReferenceType(type);
26920 SgArrayType * arrayType = isSgArrayType(type);
26921 SgTypedefType * typedefType = isSgTypedefType(type);
26922
26923#if 0
26924 // DQ (4/15/2019): Don't count SgPointerMemberType (also fixed in SgType::stripType() function).
26925 if (isSgPointerMemberType(type) != NULL)
26926 {
26927 pointType = NULL;
26928 }
26929#endif
26930
26931 if ( modType ) {
26932 type = modType->get_base_type();
26933 } else if ( refType ) {
26934 type = refType->get_base_type();
26935 } else if ( pointType ) {
26936 type = pointType->get_base_type();
26937 // } else if ( pointerMemberType ) {
26938 // type = pointerMemberType->get_base_type();
26939 } else if ( arrayType ) {
26940 type = arrayType->get_base_type();
26941 } else if ( typedefType ) {
26942 type = typedefType->get_base_type();
26943 } else {
26944 break;
26945 }
26946 ROSE_ASSERT(type != NULL);
26947 }
26948}
26949
26950
26951#if 0
26952// DQ (11/10/2019): Older original version of the function.
26953
26954// DQ (6/6/2019): Move this to the SageInteface namespace.
26955void
26957 {
26958 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
26959 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
26960 // declarations in the outlined code we can support the outpiled code with those references. This
26961 // approach has the added advantage of also supporting the same include file tree as the original
26962 // file where the outlined code is being taken from.
26963
26964 class TransformFunctionDefinitionsTraversal : public AstSimpleProcessing
26965 {
26966 public:
26967 std::vector<SgFunctionDeclaration*> functionList;
26968 SgSourceFile* sourceFile;
26969 int sourceFileId;
26970 string filenameWithPath;
26971
26972 public:
26973 TransformFunctionDefinitionsTraversal(): sourceFile(NULL), sourceFileId(-99) {}
26974
26975 void visit (SgNode* node)
26976 {
26977#if 0
26978 printf ("In convertFunctionDefinitionsToFunctionPrototypes visit(): node = %p = %s \n",node,node->class_name().c_str());
26979#endif
26980 SgSourceFile* temp_sourceFile = isSgSourceFile(node);
26981 if (temp_sourceFile != NULL)
26982 {
26983 sourceFile = temp_sourceFile;
26984 sourceFileId = sourceFile->get_file_info()->get_file_id();
26985
26986 // The file_id is not sufficnet, not clear why, but the filenames match.
26987 filenameWithPath = sourceFile->get_sourceFileNameWithPath();
26988
26989 printf ("Found source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26990
26991 }
26992
26993 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
26994 if (functionDeclaration != NULL)
26995 {
26996 // This should have been set already.
26997 ROSE_ASSERT(sourceFile != NULL);
26998
26999 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27000 if (functionDeclaration == definingFunctionDeclaration)
27001 {
27002#if 1
27003 printf ("Found a defining function declaration: functionDeclaration = %p = %s name = %s \n",
27004 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
27005
27006 printf (" --- recorded source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
27007 printf (" --- source file: file_info: id = %d name = %s \n",
27008 functionDeclaration->get_file_info()->get_file_id(),functionDeclaration->get_file_info()->get_filenameString().c_str());
27009#endif
27010 // DQ (3/20/2019): The file_id is not sufficent, using the filename with path to do string equality.
27011 // bool isInSourceFile = (sourceFileId == functionDeclaration->get_file_info()->get_file_id());
27012 bool isInSourceFile = (filenameWithPath == functionDeclaration->get_file_info()->get_filenameString());
27013#if 1
27014 printf (" --- isInSourceFile = %s \n",isInSourceFile ? "true" : "false");
27015#endif
27016 // Remove the defining declaration as a test.
27017 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27018 if (isInSourceFile == true && functionDeclarationScope != NULL)
27019 {
27020#if 1
27021 printf (" --- Found a defining function declaration: functionDeclarationScope = %p = %s \n",
27022 functionDeclarationScope,functionDeclarationScope->class_name().c_str());
27023#endif
27024 // functionDeclarationScope->removeStatement(functionDeclaration);
27025 // removeStatement(functionDeclaration);
27026 functionList.push_back(functionDeclaration);
27027 }
27028 }
27029 }
27030 }
27031 };
27032
27033 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27034 TransformFunctionDefinitionsTraversal traversal;
27035 traversal.traverse(node, preorder);
27036
27037 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27038
27039#if 1
27040 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): functionList.size() = %zu \n",functionList.size());
27041#endif
27042
27043 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27044 while (i != functionList.end())
27045 {
27046 SgFunctionDeclaration* functionDeclaration = *i;
27047 ROSE_ASSERT(functionDeclaration != NULL);
27048
27049 SgFunctionDeclaration* nondefiningFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27050 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27051
27052#if 1
27053 printf (" --- Removing function declaration: functionDeclaration = %p = %s name = %s \n",
27054 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
27055#endif
27056 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27057 // removeStatement(functionDeclaration);
27058 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration);
27059
27060 i++;
27061 }
27062
27063#if 0
27064 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): exiting as a test! \n");
27065 ROSE_ABORT();
27066#endif
27067 }
27068#endif
27069
27070
27071void
27073 {
27074 // DQ (10/31/2020): Display function for scopes (useful for debugging).
27075 ROSE_ASSERT(scope != NULL);
27076
27077 printf ("Output the statements in scope = %p = %s \n",scope,scope->class_name().c_str());
27078
27079 // This makes a copy (on the stack) and is inefficent, but this is only for debugging.
27080 SgStatementPtrList statementList = scope->generateStatementList();
27081 for (size_t i = 0; i < statementList.size(); i++)
27082 {
27083 SgStatement* statement = statementList[i];
27084 printf (" --- statement: %zu ptr: %p IR node: %s name: %s \n",i,statement,statement->class_name().c_str(),SageInterface::get_name(statement).c_str());
27085 }
27086
27087#if 0
27088 printf ("Exiting as a test at the end of evaluation of global scope! \n");
27089 ROSE_ABORT();
27090#endif
27091 }
27092
27093
27096 {
27097 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27098 // SgDeclarationStatement* nondefiningFunctionDeclaration = NULL;
27099
27100#if 0
27101 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p = %s name = %s \n",
27102 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
27103#endif
27104
27105 // DQ (11/21/2019): Check if this is a constructor, this is a temporary fix.
27106 bool isConstructor = false;
27107 SgMemberFunctionDeclaration* tmp_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
27108 if (tmp_memberFunctionDeclaration != NULL)
27109 {
27110 isConstructor = tmp_memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
27111
27112#if 0
27113 if (isConstructor == true)
27114 {
27115 printf ("Skipping case of constructors (in building prototype from defining function declaration) \n");
27116 return;
27117 }
27118#endif
27119 }
27120
27121 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27122 // bool replaceWithEmptyDeclaration = false;
27123 // SgDeclarationStatement* emptyDeclaration = NULL;
27124
27125 SgName name = functionDeclaration->get_name();
27126 SgType* return_type = functionDeclaration->get_type()->get_return_type();
27127
27128#if 0
27129 // DQ (12/10/2020): The issue is that the default arguments defined in template functions are represented in the AST.
27130 // Where we output the template as a string, it is included, and in the template instantiation it is represented in
27131 // the AST. So where it is used, default arguments are not represented in the AST and so the are not generated in
27132 // this function that builds the function prototype from the defining function.
27133
27134 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p \n",functionDeclaration);
27135 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
27136 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
27137
27138 // DQ (12/9/2020): Check if there is a default argument. Need to figure out how default arguments
27139 // are specified in the function declarations, and make sure the prototype reproduces them.
27140 for (size_t i = 0; i < functionDeclaration->get_args().size(); i++)
27141 {
27142 SgInitializedName* arg = functionDeclaration->get_args()[i];
27143#if 1
27144 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_args(): (i = %zu) arg = %p = %s isDefaultArgument = %s \n",
27145 i,arg,arg->get_name().str(),arg->get_file_info()->isDefaultArgument() ? "true" : "false");
27146 printf (" --- arg->get_initializer() = %p \n",arg->get_initializer());
27147#endif
27148 if (arg->get_file_info()->isDefaultArgument() == true)
27149 {
27150 printf ("NOTE: default argument (i = %zu) not reproduced in function prototype: arg = %p = %s \n",i,arg,arg->get_name().str());
27151 }
27152 }
27153#endif
27154
27155#if 1
27156 SgFunctionParameterList* param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
27157#else
27158 // 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).
27159 // SgFunctionParameterList *param_list = functionDeclaration->get_parlist();
27160 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27161 SgFunctionParameterList* param_list = NULL;
27162
27163 if (templateInstantiationFunctionDecl == NULL)
27164 {
27165 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
27166 }
27167 else
27168 {
27169 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
27170 if (templateInstantiationMemberFunctionDecl == NULL)
27171 {
27172 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
27173 }
27174 }
27175#endif
27176
27177
27178 // bool isTemplateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration) != NULL);
27179 bool isTemplateInstantiationMemberFunctionDecl = false;
27180
27181 SgScopeStatement* scope = functionDeclaration->get_scope();
27182 // SgTemplateParameterPtrList* templateParameterList = NULL; // functionDeclaration->get_templateParameterList();
27183 SgExprListExp* python_decoratorList = NULL;
27184 bool buildTemplateInstantiation = false;
27185 SgTemplateArgumentPtrList* templateArgumentsList = NULL;
27186
27187 // DQ (9/26/2019): Tracing down a null parent pointer.
27188 // ROSE_ASSERT(param_list->get_parent() != NULL);
27189 // ROSE_ASSERT(param_list->get_parent() == NULL);
27190 ROSE_ASSERT(param_list == NULL || param_list->get_parent() == NULL);
27191
27192 switch (functionDeclaration->variantT())
27193 {
27194 case V_SgTemplateMemberFunctionDeclaration:
27195 {
27196#if 0
27197 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template member functions \n");
27198#endif
27199 SgTemplateMemberFunctionDeclaration* original_templateMemberFunctionDeclaration = isSgTemplateMemberFunctionDeclaration(functionDeclaration);
27200 ROSE_ASSERT(original_templateMemberFunctionDeclaration != NULL);
27201
27202 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = NULL;
27203
27204 unsigned int functionConstVolatileFlags = 0;
27205
27206 ROSE_ASSERT(original_templateMemberFunctionDeclaration->get_type() != NULL);
27207
27208 // Need to call:
27209 // unsigned int get_mfunc_specifier();
27210
27211 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_templateMemberFunctionDeclaration->get_type());
27212 ROSE_ASSERT(memberFunctionType != NULL);
27213
27214 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
27215
27216 // SgTemplateMemberFunctionDeclaration*
27217 // buildNondefiningTemplateMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27218 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList* templateParameterList );
27219
27220 SgTemplateParameterPtrList templateParameterList = original_templateMemberFunctionDeclaration->get_templateParameters();
27221 // ROSE_ASSERT(templateParameterList != NULL);
27222
27223 templateMemberFunctionDeclaration =
27224 buildNondefiningTemplateMemberFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags, &templateParameterList );
27225#if 0
27226 printf ("ERROR: Template functions are not yet supported! \n");
27227 ROSE_ABORT();
27228#endif
27229 nondefiningFunctionDeclaration = templateMemberFunctionDeclaration;
27230
27231 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27232
27233 // DQ (11/21/2019): Handle constructors.
27234 if (isConstructor == true)
27235 {
27236 templateMemberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27237 }
27238
27239 break;
27240 }
27241
27242 case V_SgTemplateFunctionDeclaration:
27243 {
27244#if 0
27245 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template functions \n");
27246#endif
27247 SgTemplateFunctionDeclaration* original_templateFunctionDeclaration = isSgTemplateFunctionDeclaration(functionDeclaration);
27248 ROSE_ASSERT(original_templateFunctionDeclaration != NULL);
27249
27250 SgTemplateFunctionDeclaration* templateFunctionDeclaration = NULL; // isSgTemplateFunctionDeclaration(functionDeclaration);
27251
27252 // SgTemplateFunctionDeclaration*
27253 // buildNondefiningTemplateFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27254 // SgScopeStatement* scope=NULL, SgExprListExp* decoratorList = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
27255
27256 SgTemplateParameterPtrList templateParameterList = original_templateFunctionDeclaration->get_templateParameters();
27257
27258 templateFunctionDeclaration = buildNondefiningTemplateFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, &templateParameterList );
27259#if 0
27260 printf ("ERROR: Template functions are not yet supported! \n");
27261 ROSE_ABORT();
27262#endif
27263 nondefiningFunctionDeclaration = templateFunctionDeclaration;
27264
27265 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27266
27267 break;
27268 }
27269
27270 // DQ (10/29/2020): Added new case.
27271 case V_SgTemplateInstantiationMemberFunctionDecl:
27272 {
27273 buildTemplateInstantiation = true;
27274
27275 isTemplateInstantiationMemberFunctionDecl = true;
27276
27277 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
27278 ROSE_ASSERT(templateInstantiationMemberFunctionDecl != NULL);
27279 templateArgumentsList = &(templateInstantiationMemberFunctionDecl->get_templateArguments());
27280#if 0
27281 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27282 // printf ("name from templateInstantiationMemberFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_template_name().str());
27283 printf ("name from templateInstantiationMemberFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_templateName().str());
27284 SgTemplateMemberFunctionDeclaration* templateDeclaration = templateInstantiationMemberFunctionDecl->get_templateDeclaration();
27285 if (templateDeclaration != NULL)
27286 {
27287 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27288 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27289 }
27290#endif
27291 // name = functionDeclaration->get_name();
27292 // name = templateInstantiationMemberFunctionDecl->get_template_name();
27293 name = templateInstantiationMemberFunctionDecl->get_templateName();
27294#if 0
27295 printf ("In case V_SgTemplateInstantiationMemberFunctionDecl: using name = %s \n",name.str());
27296#endif
27297 // DQ (10/29/2020): Change this to include the functionality to build the member function support without fall-through.
27298 }
27299 // fall through
27300 case V_SgMemberFunctionDeclaration:
27301 {
27302#if 0
27303 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support member functions \n");
27304#endif
27305 SgMemberFunctionDeclaration* original_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
27306 ROSE_ASSERT(original_memberFunctionDeclaration != NULL);
27307
27308 SgMemberFunctionDeclaration* memberFunctionDeclaration = NULL; // isSgMemberFunctionDeclaration(functionDeclaration);
27309
27310 // SgMemberFunctionDeclaration*
27311 // buildNondefiningMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27312 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList* templateArgumentsList);
27313
27314 unsigned int functionConstVolatileFlags = 0;
27315
27316 ROSE_ASSERT(original_memberFunctionDeclaration->get_type() != NULL);
27317
27318 // Need to call:
27319 // unsigned int get_mfunc_specifier();
27320
27321 // DQ (12/2/2019): If it is defined outside of the class, then don't replace with member function prototype,
27322 // since they is not allowed to be declared outside of the class they are a member of.
27323
27324 // We do want to build prototypes for template instantiation member functions, and template instantiation non-member functions (see below).
27325 bool buildPrototype = isTemplateInstantiationMemberFunctionDecl || original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope();
27326#if 0
27327 printf ("In SageInterface::buildFunctionPrototype(): buildPrototype = %s \n",buildPrototype ? "true" : "false");
27328#endif
27329 if (buildPrototype == true)
27330 {
27331 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_memberFunctionDeclaration->get_type());
27332 ROSE_ASSERT(memberFunctionType != NULL);
27333#if 0
27334 printf ("original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope() \n");
27335#endif
27336 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
27337
27338 memberFunctionDeclaration =
27340 ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags,
27341 buildTemplateInstantiation,templateArgumentsList );
27342#if 0
27343 printf ("ERROR: Member functions are not yet supported! \n");
27344 ROSE_ABORT();
27345#endif
27346 // DQ (11/21/2019): Handle constructors.
27347 if (isConstructor == true)
27348 {
27349 memberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27350 }
27351
27352 nondefiningFunctionDeclaration = memberFunctionDeclaration;
27353
27354 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27355 }
27356 else
27357 {
27358 // Case of member function defined outside of it's class.
27359#if 0
27360 printf ("NOTE: Member functions defined outside of their class can not be output as member function prototypes (not allowed in C++) \n");
27361#endif
27362 // We want to build a SgEmptyDeclaration using buildEmptyDeclaration() but this is not a function.
27363 // nondefiningFunctionDeclaration = buildEmptyDeclaration();
27364 nondefiningFunctionDeclaration = NULL;
27365#if 0
27366 nondefiningFunctionDeclaration = NULL;
27367
27368 replaceWithEmptyDeclaration = true;
27369 emptyDeclaration = buildEmptyDeclaration();
27370 ROSE_ASSERT(emptyDeclaration != NULL);
27371#endif
27372 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27373 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27374
27375 // Since we din't build a member function we don't need the parameter list.
27376 delete param_list;
27377 param_list = NULL;
27378#if 0
27379 printf ("Exiting as a test! \n");
27380 ROSE_ABORT();
27381#endif
27382 }
27383
27384 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27385 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27386 break;
27387 }
27388
27389 case V_SgFunctionDeclaration:
27390 {
27391 // This is for a non-member non-template function declaration.
27392 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27393 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27394 break;
27395 }
27396
27397 // DQ (10/29/2020): Added new case.
27398 case V_SgTemplateInstantiationFunctionDecl:
27399 {
27400 // This is for a non-member non-template function declaration.
27401 buildTemplateInstantiation = true;
27402 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27403 ROSE_ASSERT(templateInstantiationFunctionDecl != NULL);
27404 templateArgumentsList = &(templateInstantiationFunctionDecl->get_templateArguments());
27405#if 0
27406 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27407 // printf ("name from templateInstantiationFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationFunctionDecl->get_template_name().str());
27408 printf ("name from templateInstantiationFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationFunctionDecl->get_templateName().str());
27409 SgTemplateFunctionDeclaration* templateDeclaration = templateInstantiationFunctionDecl->get_templateDeclaration();
27410 if (templateDeclaration != NULL)
27411 {
27412 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27413 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27414 }
27415#endif
27416 name = templateInstantiationFunctionDecl->get_templateName();
27417#if 0
27418 printf ("In case V_SgTemplateInstantiationFunctionDecl: using name = %s \n",name.str());
27419#endif
27420 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27421 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27422 break;
27423 }
27424
27425 default:
27426 {
27427 // DQ (12/4/2019): If this is any other case than that handled above, then we just return.
27428 // These cases would be only template instantiations.
27429
27430 // Nothing to do, except delete the parameter list we built, and return.
27431 delete param_list;
27432 param_list = NULL;
27433
27434 return NULL;
27435 }
27436 }
27437
27438 // DQ (10/29/2020): We should be able to change this now that we support SgTemplateInstantiationFunctionDecl and SgTemplateInstantiationMemberFunctionDecl IR nodes.
27439 // DQ (9/26/2019): Tracing down a null parent pointer.
27440 ROSE_ASSERT(param_list == NULL || param_list->get_parent() != NULL);
27441 // ROSE_ASSERT(param_list != NULL);
27442 // ROSE_ASSERT(param_list->get_parent() != NULL);
27443
27444 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27445
27446 if (nondefiningFunctionDeclaration != NULL)
27447 {
27448 if (nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() == NULL)
27449 {
27450#if 0
27451 printf ("Setting the firstNondefiningDeclaration \n");
27452#endif
27453 nondefiningFunctionDeclaration->set_firstNondefiningDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27454 }
27455
27456 if (nondefiningFunctionDeclaration->get_definingDeclaration() == NULL)
27457 {
27458#if 0
27459 printf ("Setting the definingDeclaration \n");
27460#endif
27461 nondefiningFunctionDeclaration->set_definingDeclaration(functionDeclaration->get_definingDeclaration());
27462 }
27463
27464 ROSE_ASSERT(nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() != NULL);
27465 ROSE_ASSERT(nondefiningFunctionDeclaration->get_definingDeclaration() != NULL);
27466
27467 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27468 if (nondefiningFunctionDeclaration != NULL)
27469 {
27470 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27471 // This is a bug in the support for building a new prototype from a defining function declaration
27472 // and caused this problem. This assertion will prevent this sort of error from happening again.
27473 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27474 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27475 }
27476 }
27477
27478 return nondefiningFunctionDeclaration;
27479 }
27480
27481
27482// 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).
27485 {
27486 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27487 ROSE_ASSERT(functionDeclaration != NULL);
27488
27489#if 0
27490 printf ("****************************************************************** \n");
27491 printf ("Attached comments and CPP directives: defining functionDeclaration \n");
27492 SageInterface::printOutComments (functionDeclaration);
27493 printf ("****************************************************************** \n");
27494#endif
27495
27496 // 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.
27497
27498 nondefiningFunctionDeclaration = buildFunctionPrototype(functionDeclaration);
27499
27500 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27501 if (nondefiningFunctionDeclaration != NULL)
27502 {
27503 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27504 // This is a bug in the support for building a new prototype from a defining function declaration
27505 // and caused this problem. This assertion will prevent this sort of error from happening again.
27506 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27507 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27508 }
27509
27510 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27511
27512 if (templateInstantiationFunctionDecl == NULL)
27513 {
27514 if (nondefiningFunctionDeclaration != NULL)
27515 {
27516 // DQ (10/29/2020): Match the associated declaration modifiers.
27517 nondefiningFunctionDeclaration->get_declarationModifier() = functionDeclaration->get_declarationModifier();
27518
27519 // DQ (11/11/2020): Match the associated other kinds of modifiers.
27520 nondefiningFunctionDeclaration->get_functionModifier() = functionDeclaration->get_functionModifier();
27521 nondefiningFunctionDeclaration->get_specialFunctionModifier() = functionDeclaration->get_specialFunctionModifier();
27522
27523 nondefiningFunctionDeclaration->set_linkage( functionDeclaration->get_linkage() );
27524 nondefiningFunctionDeclaration->set_externBrace( functionDeclaration->get_externBrace() );
27525
27526 ROSE_ASSERT(nondefiningFunctionDeclaration->get_forward() == true);
27527
27528 // DQ (10/15/2019): Set the physical_file_id of the transformation to match that of the original defining declaration.
27529 int file_id = functionDeclaration->get_file_info()->get_physical_file_id();
27530 nondefiningFunctionDeclaration->get_file_info()->set_physical_file_id(file_id);
27531
27532 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27533 // removeStatement(functionDeclaration);
27534 // DQ (11/22/2020): Note that this step will move the comments and CPP directives to the new statement
27535 // (better in this step than in the copy of the pointer to the list above, which cause an iterator invalidation error).
27536 // DQ (10/21/2020): I think we may want to return the orignal defining function declaration.
27537 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27538 // DQ (11/15/2020): Note that the default is false, and we need true.
27539 bool movePreprocessingInfo = true;
27540 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration,movePreprocessingInfo);
27541
27542 // DQ (11/25/2020): This is the cause of a problem in the outliner caught in the resetParentPointer.C (definingDeclaration->get_parent() != __null).
27543 // 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.
27544 // This is the cause of a name qualification bug when the functionDeclaration is inserted into global scope and the name qualification
27545 // is not computed correctly (since the parent was still the namespace scope where it was originally.
27546 ROSE_ASSERT(nondefiningFunctionDeclaration->get_parent() != NULL);
27547 }
27548 }
27549 else
27550 {
27551 // DQ (7/12/2019): Template instantiations are not directly from the source code, so we don't have to move them.
27552 nondefiningFunctionDeclaration = NULL;
27553 }
27554
27555 // Check that static declaration is preserved.
27556 if (functionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true)
27557 {
27558 ROSE_ASSERT(nondefiningFunctionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true);
27559 }
27560
27561 // DQ (10/27/2020): Added return value so that we can access the new function prototype.
27562 return nondefiningFunctionDeclaration;
27563 }
27564
27565
27566std::vector<SgFunctionDeclaration*>
27568 {
27569 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
27570 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
27571 // declarations in the outlined code we can support the outpiled code with those references. This
27572 // approach has the added advantage of also supporting the same include file tree as the original
27573 // file where the outlined code is being taken from.
27574
27575 class FunctionDefinitionsTraversal : public AstSimpleProcessing
27576 {
27577 public:
27578 std::vector<SgFunctionDeclaration*> functionList;
27579 FunctionDefinitionsTraversal() {}
27580
27581 void visit (SgNode* node)
27582 {
27583 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
27584 if (functionDeclaration != NULL)
27585 {
27586 // This should have been set already.
27587 // ROSE_ASSERT(sourceFile != NULL);
27588
27589 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27590 if (functionDeclaration == definingFunctionDeclaration)
27591 {
27592 // Remove the defining declaration as a test.
27593 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27594 if (functionDeclarationScope != NULL)
27595 {
27596 functionList.push_back(functionDeclaration);
27597 }
27598 }
27599 }
27600 }
27601 };
27602
27603 // Now build the traveral object and call the traversal (preorder) on the AST subtree.
27604 FunctionDefinitionsTraversal traversal;
27605
27606 traversal.traverseWithinFile(node, preorder);
27607
27608 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27609
27610 return functionList;
27611 }
27612
27613
27614void
27616 {
27617 ROSE_ASSERT(node != NULL);
27618
27619 std::vector<SgFunctionDeclaration*> functionList = generateFunctionDefinitionsList(node);
27620 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27621
27622 while (i != functionList.end())
27623 {
27624 SgFunctionDeclaration* functionDeclaration = *i;
27625 ROSE_ASSERT(functionDeclaration != NULL);
27626 // Transform into prototype.
27628 i++;
27629 }
27630 }
27631
27632
27633
27634// DQ (7/14/2020): Added test for initializers to support debugging of Cxx11_tests/test2020_69.C.
27635void
27637 {
27638 // This function checks variable declarations for initializers. An issue (bug) in EDG 6.0
27639 // support for variable declarations initialized using lambda functions is that the initalizer
27640 // is discarded at some point in the processing of the AST. This function reports on all
27641 // variable declarations and if they contain initializers and if so what kind of initializer.
27642
27643 ROSE_ASSERT(node != nullptr);
27644
27645 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
27646 class CheckInitializerTraversal : public AstSimpleProcessing
27647 {
27648 public:
27649 void visit (SgNode* node)
27650 {
27651 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node);
27652 if (variableDeclaration != NULL)
27653 {
27654 SgInitializedName* initializedName = getFirstInitializedName(variableDeclaration);
27655 SgExpression* initializer = initializedName->get_initializer();
27656
27657 printf ("variableDeclaration = %p initializedName = %p = %s initializer = %p \n",
27658 variableDeclaration,initializedName,initializedName->get_name().str(),initializer);
27659
27660 if (initializer != NULL)
27661 {
27662 printf (" --- initializer = %s \n",initializer->class_name().c_str());
27663 }
27664 }
27665 }
27666 };
27667
27668 // Now buid the traveral object and call the traversal (preorder) on the project.
27669 CheckInitializerTraversal traversal;
27670 traversal.traverse(node, preorder);
27671 }
27672
27673namespace
27674{
27675 struct DeclaredType : sg::DispatchHandler<SgNamedType*>
27676 {
27677 void setResult(SgNamedType* ty) { res = ty; }
27678 void setResult(SgType*) { /* not a named type */ }
27679
27680 void handle(SgNode& n, SgNode&) { SG_UNEXPECTED_NODE(n); }
27681
27682 template <class SageDeclarationStatement>
27683 void handle(SageDeclarationStatement& n, SgDeclarationStatement&)
27684 {
27685 // SgDeclarationStatement::get_type is not a virtual function
27686 // => find overloaders returning SgNamedType in subclasses
27687 // by using the full type (SageDeclarationStatement).
27688 setResult(n.get_type());
27689 }
27690
27691 template <class SageNode>
27692 void handle(SageNode& n)
27693 {
27694 handle(n, n);
27695 }
27696 };
27697}
27698
27700{
27701 return sg::dispatch(DeclaredType{}, declaration);
27702}
27703
27705 SgGlobal * gsaf = project->get_globalScopeAcrossFiles();
27706 ROSE_ASSERT(gsaf != nullptr);
27707 SgSymbolTable * st = gsaf->get_symbol_table();
27708 ROSE_ASSERT(st != nullptr);
27709 rose_hash_multimap * hmm = st->get_table();
27710 ROSE_ASSERT(hmm != nullptr);
27711 hmm->clear();
27712
27713 st = SgNode::get_globalTypeTable()->get_type_table();
27714 ROSE_ASSERT(st != nullptr);
27715 hmm = st->get_table();
27716 ROSE_ASSERT(hmm != nullptr);
27717 hmm->clear();
27718
27720 ROSE_ASSERT(st != nullptr);
27721 hmm = st->get_table();
27722 ROSE_ASSERT(hmm != nullptr);
27723 hmm->clear();
27724}
27725
27727/*
27728
27729By default, only transformation generated AST nodes will be normalized since this is designed to normalize translator-generated code.
27730
27731--- p_lhs_operand_i ->@0x7ff2fc3f1010 SgArrowExp c_rc-575-out.cpp 16:13
27732 |--- p_lhs_operand_i ->@0x7ff2fc428010 SgAddressOfOp c_rc-575-out.cpp 16:4
27733 | |___ p_operand_i ->@0x7ff2fc582078 SgVarRefExp c_rc-575-out.cpp 16:5 init name@0x7ff2fcf03890 symbol name="table1"
27734 |___ p_rhs_operand_i ->@0x7ff2fc5820e0 SgVarRefExp c_rc-575-out.cpp 16:16 init name@0x7ff2fcf03480 symbol name="item1"
27735
27736
27737TODO: we only handle simplest pattern for now: both leaf operands involved are SgVarRefExp.
27738
27739 * */
27740int SageInterface::normalizeArrowExpWithAddressOfLeftOperand(SgNode* root, bool transformationGeneratedOnly /* =true */)
27741{
27742 int match_count = 0;
27743 ROSE_ASSERT (root);
27744
27745 // find all SgArrowExp, then try to match the expected pattern
27746 // SgArrowExp(SgAddressOfOp(SgVarRefExp:table1),SgVarRefExp:item1)
27747 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgArrowExp);
27748
27749 // The jovial2cpp translator generates two source file ASTs: and they often share the same subtrees.
27750 // So we need to make sure the same subtree is only processed once
27751 boost::unordered::unordered_map <SgNode*, bool> visited;
27752
27753 // reverse iterator is safer to use than forward iterator to support translation
27754 for (Rose_STL_Container<SgNode *>::reverse_iterator i = nodeList.rbegin(); i != nodeList.rend(); i++)
27755 {
27756 // skip a node if it is previously processed.
27757 if (visited.count(*i)==1)
27758 continue;
27759
27760 visited[*i]=true;
27761
27762 SgArrowExp* a_exp = isSgArrowExp(*i);
27763
27764 if (!a_exp)
27765 {
27766 cerr<<"SageInterface::normalizeArrowExpWithAddressOfLeftOperand() expects SgArrowExp while encountering "<<(*i)->class_name()<<"@"<<(*i) <<endl;
27767 ROSE_ASSERT (a_exp);
27768 }
27769
27770 if (transformationGeneratedOnly)
27771 {
27772 if (!(a_exp->get_file_info()->isTransformation()))
27773 continue;
27774 }
27775
27776 if (SgAddressOfOp* address_op = isSgAddressOfOp(a_exp->get_lhs_operand()) )
27777 {
27778 if (SgVarRefExp* left = isSgVarRefExp(address_op->get_operand())) // match left side pattern
27779 {
27780 if (SgVarRefExp* right = isSgVarRefExp (a_exp->get_rhs_operand())) // match right side pattern
27781 {
27782 // do the transformation: copy two operands, making a dot exp instead
27783 SgDotExp* dot_exp = buildDotExp (deepCopy(left), deepCopy(right));
27784 replaceExpression (a_exp, dot_exp);
27785 match_count++;
27786 }
27787 }
27788 }
27789 } // end for
27790
27791 return match_count;
27792}
27793
27794bool
27796 {
27797 class Traversal : public AstSimpleProcessing
27798 {
27799 public:
27800 bool found;
27801 Traversal() : found(false) {}
27802 void visit (SgNode* node)
27803 {
27804 SgCastExp* castExpression = isSgCastExp(node);
27805 if (castExpression != NULL)
27806 {
27807 // SgNode* parent = castExpression->get_parent();
27808 SgInitializer* initializer = isSgInitializer(castExpression->get_parent());
27809 if (initializer == NULL)
27810 {
27811 ROSE_ASSERT(castExpression->get_file_info() != NULL);
27812 if (castExpression->get_file_info()->isTransformation() == true)
27813 {
27814 printf (" --- Found a SgCastExp marked as a transformation: castExpression = %p \n",castExpression);
27815 found = true;
27816#if 0
27817 printf ("Exiting as a test! \n");
27818 ROSE_ASSERT(false);
27819#endif
27820 }
27821 else
27822 {
27823#if 0
27824 printf (" --- SgCastExp (but not marked as a transformation) node = %p = %s \n",node,node->class_name().c_str());
27825#endif
27826 }
27827 }
27828 else
27829 {
27830 // DQ (7/14/2021): This case is less interesting (not the SgCastExp that I was looking for in testing).
27831#if 1
27832 printf (" --- SgCastExp (but from an initializer) node = %p = %s \n",node,node->class_name().c_str());
27833#endif
27834 }
27835 }
27836 else
27837 {
27838#if 0
27839 printf (" --- node = %p = %s \n",node,node->class_name().c_str());
27840#endif
27841 }
27842 }
27843 };
27844
27845#if 1
27846 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s \n",s.c_str());
27847#endif
27848
27849 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27850 Traversal traversal;
27851 traversal.traverse(n, preorder);
27852
27853#if 1
27854 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s traversal.found = %s \n",s.c_str(),traversal.found ? "true" : "false");
27855#endif
27856#if 0
27857 // DQ (7/13/2021): return false so that we can test the execution of the code to generate that backend code.
27858 if (traversal.found == true)
27859 {
27860 printf ("In findFirstSgCastExpMarkedAsTransformation(): returning false \n");
27861 }
27862
27863 return false;
27864#else
27865 return traversal.found;
27866#endif
27867 }
27868
27869// A helper function to check
27870// begin: return 1
27871// middle (#else, #elif): return 2
27872// end directive: return -1
27873// othewise return 0;
27874static int isBeginDirective (PreprocessingInfo* info)
27875{
27876 ROSE_ASSERT (info != NULL);
27877 PreprocessingInfo::DirectiveType dtype= info->getTypeOfDirective();
27878 if (dtype == PreprocessingInfo::CpreprocessorIfdefDeclaration ||
27879 dtype == PreprocessingInfo::CpreprocessorIfndefDeclaration ||
27880 dtype == PreprocessingInfo::CpreprocessorIfDeclaration )
27881 {
27882 return 1;
27883 }
27884 else if (dtype==PreprocessingInfo::CpreprocessorElseDeclaration||
27885 dtype==PreprocessingInfo::CpreprocessorElifDeclaration)
27886 {
27887 return 2;
27888 }
27889 else if (dtype==PreprocessingInfo::CpreprocessorEndifDeclaration)
27890 {
27891 return -1;
27892 }
27893
27894 return 0;
27895}
27896
27897// a helper function to move things, the associated directive in the middle
27898static void moveInofListToNewPlace(AttachedPreprocessingInfoType* infoList, int cidx, set <AttachedPreprocessingInfoType*>& relatedInfoList, SgLocatedNode* lnode, int &retVal)
27899{
27900// AttachedPreprocessingInfoType* infoList = (*ki).first;
27901// int cidx= (*ki).second;
27902
27903 relatedInfoList.insert (infoList);
27904
27905 PreprocessingInfo* info = (*infoList)[cidx];
27906 // rewrite relative position
27907 info->setRelativePosition(PreprocessingInfo::after);
27908
27909 // insert after lnode
27910 lnode->addToAttachedPreprocessingInfo (info);
27911 retVal++;
27912
27913 // zero out from original list
27914 (*infoList)[cidx]= NULL;
27915}
27916
27917// Return the number of NULL PreprocessingInfo* within a subtree of a SgLocatedNode, inclusive
27919{
27920 int retVal=0;
27921 ROSE_ASSERT(lnode);
27922
27923 // collecting NULL entries
27924 RoseAst ast(lnode);
27925 RoseAst::iterator ast_i=ast.begin();
27926
27927 vector < pair< AttachedPreprocessingInfoType*, int> > empty_entries; // preprocessing info. to be erased, list vs. idx/offset
27928 for(;ast_i!=ast.end();++ast_i) {
27929 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27930 if (current ==NULL ) // skip non located nodes
27931 continue;
27932
27933 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27934 if (infoList == NULL) continue;
27935
27936 int commentIndex=0;
27937 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27938 {
27939 // fundamentally, we want to move individual PreprocessingInfo objects
27940 // Or just duplicate them (easier)
27941 PreprocessingInfo * info = *ci;
27942 if (info==NULL)
27943 empty_entries.push_back( make_pair (infoList, commentIndex) );
27944 commentIndex++;
27945 }
27946 }
27947
27948 // using reverse iterator to remove from backwards
27949 for (auto ki = empty_entries.rbegin(); ki != empty_entries.rend(); ki ++)
27950 {
27951 AttachedPreprocessingInfoType* infoList = (*ki).first;
27952 int cidx= (*ki).second;
27953
27954 PreprocessingInfo* info = (*infoList)[cidx];
27955 ROSE_ASSERT (info==NULL);
27956
27957 // erase start+offset
27958 AttachedPreprocessingInfoType::iterator k = infoList->begin();
27959 infoList->erase(k+cidx);
27960// cout<<"debugging: direct erasing: info@"<< infoList<< " idx="<<cidx<<endl;
27961 retVal ++;
27962 }
27963 return retVal;
27964}
27965
27966//TODO: expose this to header file?
27967// We keep all things, including level : starting from 0. Later iteration ignore the level 0 directives.
27968// Should this be maintained by librose or user space code?
27969static std::unordered_map <PreprocessingInfo*, SageInterface::PreprocessingInfoData> infoMap;
27970
27971void SageInterface::preOrderCollectPreprocessingInfo(SgNode* current, vector<PreprocessingInfo*>& infoList, int depth)
27972{
27973 // stop condition
27974 if (current == NULL)
27975 return;
27976
27977 // Three possible locations: before, inside, and after
27978 // immediately add prepression info that is before and inside of current node
27979 // delayed additions of these that are located after the current node
27980 vector<PreprocessingInfo*> afterList;
27981 if (SgLocatedNode* locatedNode = isSgLocatedNode(current))
27982 {
27983 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
27984
27985 if (comments != nullptr)
27986 {
27987 AttachedPreprocessingInfoType::iterator i;
27988 int idx=0;
27989 for (i = comments->begin (); i != comments->end (); i++)
27990 {
27991 PreprocessingInfo* info= *i;
27992
27993 // prepare the data just in case
27995 data.container=comments;
27996 data.index = idx;
27997 data.depth = depth;
27998
27999 // put directives with before location into the infoList
28000 if (info->getRelativePosition () == PreprocessingInfo::before)
28001 {
28002 infoList.push_back (info);
28003 infoMap[info] = data;
28004 }
28005 // How about inside position?
28006 // why it should be intepreted as the last one after all inner statment's preprocessingInfo?
28007 // because if it should be unparsed before all of them, it should have been attached to the first stmt's before location instead!
28008 else if (info->getRelativePosition () == PreprocessingInfo::after
28009 || info->getRelativePosition () == PreprocessingInfo::inside
28010 )
28011 {
28012 afterList.push_back (info); // if attached to be after, save to afterList
28013 infoMap[info] = data;
28014 }
28015 else
28016 {
28017 mlog[Sawyer::Message::Common::WARN] <<"Warning: unhandled relative position value:" <<info->getRelativePosition () <<endl;
28018 // ROSE_ASSERT (false); // Jovial has end_of
28019 }
28020
28021 idx++;
28022 } // end for
28023 }
28024 } // end if
28025
28026 // handling children nodes
28027 std::vector<SgNode* > children = current->get_traversalSuccessorContainer();
28028 for (auto c: children)
28029 preOrderCollectPreprocessingInfo (c, infoList, depth +1);
28030
28031 // append after locations after recursively handling children nodes.
28032 for (auto fi : afterList)
28033 infoList.push_back(fi);
28034}
28035
28036// This may be expensive to run since it is called anytime replace() is called.
28038// We need to attach them to be after lnode, before we can safely remove lnode. So the inner preprocessing info. can be preserved properly.
28039// This should be done before removing or replace the statement: lnode
28040// TODO: this may need to be a recursive function for multiple levels of nested directives.
28041//
28042// We only care about directives attached to inner nodes, not lnode : TODO: double check this for corner cases
28043//
28045{
28046 int retVal=0;
28047 ROSE_ASSERT(lnode);
28048
28049// algorithm: using a queue (vector to simulate it)
28050// queue <PreProcessingInfo* > q;
28051// start from 2nd node: ignore the first root node
28052// if start preprocessing info: (if, ifndef, ifdef), push to the end of q
28053// if end of preprocessing info. (endif), neturalize possible end p info at the end of q, otherwise push it to the end
28054//
28055// the queue in the end may contain mixed preprocessing info. #endif #endif ... #if #ifndef
28056// They cannot neutralize each other.
28057// They should be attached to be after lnode !
28058 RoseAst ast(lnode);
28059 RoseAst::iterator ast_i=ast.begin();
28060 ++ast_i; // skip the root node itself
28061
28062 // we store both the container and the element's index within the container. so later we can easily remove elements from containers
28063 vector < pair< AttachedPreprocessingInfoType*, int> > keepers; // preprocessing info. to be kept
28064 // for the middle directives like #else or #elif, sometimes their status (balanced or not) is directly associatd with its preceeding begin directive
28065 // it is not always an independent decision.
28066 // Note : the association is between individual preprocessing info. however, to faciliate removing them, the second part uses InfoList vs offset
28067 unordered_map < PreprocessingInfo * , vector< pair<AttachedPreprocessingInfoType*, int>> > associated_directives;
28068
28069 // store the associated middle directives what should be erased in the end
28070 // we have to store this separatedly since the begin diretive pinfo becomes NULL after they have been erased!
28071 // associated_directives[BeginInfo] will not retrieve them!
28072 vector< pair<AttachedPreprocessingInfoType*, int>> associated_erase;
28073
28074 // Two steps here
28075 // Step 1: We build the list first, then go through them to neutralize them
28076 // to simplify the problem: we exclude comments attached to the current located node, only consider things inside
28077 //
28078 // The list must provide the following information
28079 // infoList (container), index of the directive, PreprocessingInfo* itself
28080 vector<PreprocessingInfo*> candidateInfoList;
28081 // recursively search all directives, preserving original order in AST, consider attachment locations: before, inside and after.
28082 preOrderCollectPreprocessingInfo (lnode, candidateInfoList, 0);
28083 // now we have both candidateInfoList and infoMap.
28084
28085 for (auto candidate: candidateInfoList)
28086 {
28087 // fundamentally, we want to move individual PreprocessingInfo objects
28088 // Or just duplicate them (easier)
28089 PreprocessingInfo * info = candidate;
28090
28091 // we skip candidate that is attached to a node with depth of 0 (root node of the subtree)
28092 if (infoMap[info].depth ==0)
28093 continue;
28094
28095 int commentIndex = infoMap[info].index;
28096 AttachedPreprocessingInfoType* infoList = infoMap[info].container;
28097
28098 // begin directives
28099 if ( isBeginDirective(info) == 1)
28100 {
28101 keepers.push_back(make_pair (infoList,commentIndex));
28102 }
28103 // the middle #else, #elif,
28104 else if (isBeginDirective(info) == 2)
28105 {
28106 // two situtations for immediate decision of unbalanced status
28107 //1. empty stack, or
28108 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
28109 if (keepers.size()==0)
28110 keepers.push_back(make_pair (infoList, commentIndex));
28111 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
28112 {
28113 keepers.push_back(make_pair (infoList,commentIndex));
28114 }
28115 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
28116 {
28117 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
28118 // we associated this middle directive with the beginning directive
28119 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
28120 }
28121 }
28122 // end directive
28123 else if ( isBeginDirective(info) == -1)
28124 {
28125 bool neutralized = false;
28126 // neutralize an internall matched pair, if any
28127 if (keepers.size()>0)
28128 {
28129 AttachedPreprocessingInfoType* comments = keepers.back().first;
28130 int idx = keepers.back().second;
28131
28132 if(isBeginDirective( (*comments)[idx] )==1)
28133 {
28134 keepers.pop_back();
28135 neutralized = true;
28136 }
28137 }
28138
28139 if (!neutralized)
28140 keepers.push_back(make_pair (infoList,commentIndex));
28141 }
28142
28143 }
28144
28145#if 0 // old and wrong linear search of directives
28146
28147 // Then we go through the list, extract keepers, neutralize anything else.
28148 for(;ast_i!=ast.end();++ast_i) {
28149 SgLocatedNode* current = isSgLocatedNode(*ast_i);
28150 if (current ==NULL ) // skip non located nodes
28151 continue;
28152
28153 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
28154 if (infoList == NULL) continue;
28155
28156 int commentIndex=0;
28157 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
28158 {
28159 ROSE_ASSERT(*ci != NULL);
28160 // fundamentally, we want to move individual PreprocessingInfo objects
28161 // Or just duplicate them (easier)
28162 PreprocessingInfo * info = *ci;
28163
28164 // begin directives
28165 if ( isBeginDirective(info) == 1)
28166 {
28167 keepers.push_back(make_pair (infoList,commentIndex));
28168 }
28169 // the middle #else, #elif,
28170 else if (isBeginDirective(info) == 2)
28171 {
28172 // two situtations for immediate decision of unbalanced status
28173 //1. empty stack, or
28174 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
28175 if (keepers.size()==0)
28176 keepers.push_back(make_pair (infoList,commentIndex));
28177 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
28178 {
28179 keepers.push_back(make_pair (infoList,commentIndex));
28180 }
28181 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
28182 {
28183 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
28184 // we associated this middle directive with the beginning directive
28185 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
28186 }
28187 }
28188 // end directive
28189 else if ( isBeginDirective(info) == -1)
28190 {
28191 bool neutralized = false;
28192 // neutralize an internall matched pair, if any
28193 if (keepers.size()>0)
28194 {
28195 AttachedPreprocessingInfoType* comments = keepers.back().first;
28196 int idx = keepers.back().second;
28197
28198 if(isBeginDirective( (*comments)[idx] )==1)
28199 {
28200 keepers.pop_back();
28201 neutralized = true;
28202 }
28203 }
28204
28205 if (!neutralized)
28206 keepers.push_back(make_pair (infoList,commentIndex));
28207 }
28208 commentIndex++;
28209 }
28210 }
28211#endif
28212// TODO this variable is not used in the end.
28213 set <AttachedPreprocessingInfoType*> relatedInfoList; // containers with comments to be moved
28214 // 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!
28215 // move from old containers, and add into lnode's after position
28216 for (auto ki = keepers.begin(); ki != keepers.end(); ki ++)
28217 {
28218 AttachedPreprocessingInfoType* infoList = (*ki).first;
28219 int cidx= (*ki).second;
28220 // TODO replace the code block below with moveInofListToNewPlace()
28221 relatedInfoList.insert (infoList);
28222
28223 PreprocessingInfo* info = (*infoList)[cidx];
28224 // rewrite relative position
28225 info->setRelativePosition(PreprocessingInfo::after);
28226
28227 // insert after lnode
28228 lnode->addToAttachedPreprocessingInfo (info);
28229 retVal++;
28230
28231 // we additionally process the associated directives, if any, TODO: reverse processing also??
28232 if (associated_directives.count (info)!=0)
28233 {
28234 vector<pair<AttachedPreprocessingInfoType*,int>> a_list_vec = associated_directives[info];
28235 for (auto vec_i = a_list_vec.rbegin(); vec_i != a_list_vec.rend(); vec_i ++ )
28236 {
28237 AttachedPreprocessingInfoType* a_infoList = (*vec_i).first;
28238 int aidx= (*vec_i).second;
28239 moveInofListToNewPlace (a_infoList, aidx, relatedInfoList, lnode, retVal);
28240 associated_erase.push_back(make_pair (a_infoList, aidx));
28241 }
28242 } // each begin directive may associate multiple other middle directives
28243
28244 // Doing this after the associated directives are processed.
28245 // zero out from original list, Note this element slot is NULL now!
28246 (*infoList)[cidx]= NULL;
28247
28248 }
28250 return retVal;
28251}
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