ROSE 0.11.145.267
sageInterface.C
1
2#include "sage3basic.h"
3#include "markLhsValues.h"
4#include "fixupNames.h"
5#include "FileUtility.h"
6#include <Sawyer/Message.h>
7
8#include "AstJSONGeneration.h"
9
10#include "SgNodeHelper.h" //Markus's helper functions
11
12#include "Rose/AST/Utility.h"
13
14#include "sageInterface.h"
15#include "Combinatorics.h"
16
17
18#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
19#include "replaceExpressionWithStatement.h"
20
21#include "constantFolding.h"
22#endif
23
24// DQ (10/14/2006): Added supporting help functions. tps commented out since it caused no compilation errors
25//#include "rewrite.h"
26
27// Liao 1/24/2008 : need access to scope stack sometimes
28#include "sageBuilder.h"
29
30// DQ (3/14/2017): Try to comment this out since it is not tested (used in get_C_array_dimensions(),
31// from midend/programTransformation/ompLowering/omp_lowering.cpp, but not tested).
32#include "sageGeneric.h"
33
34#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
35// For reusing some code from Qing's loop optimizer
36// Liao, 2/26/2009
37#include "AstInterface_ROSE.h"
38#include "LoopTransformInterface.h"
39
40#include "DepInfoAnal.h" // for AnalyzeStmtRefs()
41#include "ArrayAnnot.h"
42#include "ArrayInterface.h"
43
44#include "LoopUnroll.h"
45#include "abstract_handle.h"
46#include "roseAdapter.h"
47#endif
48
49#include <boost/lexical_cast.hpp>
50#include <boost/foreach.hpp>
51#include <sstream>
52#include <iostream>
53#include <algorithm> // for set operations
54#include <numeric> // for std::accumulate
55#include <map>
56#include <unordered_map>
57
58#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
59# include "jni.h"
60
61namespace Rose {
62 namespace Frontend {
63 namespace Java {
64 namespace Ecj {
65
66 extern jclass currentJavaTraversalClass;
67 extern JNIEnv *currentEnvironment;
68 extern jmethodID mainMethod;
69 extern jmethodID hasConflictsMethod;
70 extern jmethodID getTempDirectoryMethod;
71 extern jmethodID createTempFileMethod;
72 extern jmethodID createTempNamedFileMethod;
73 extern jmethodID createTempNamedDirectoryMethod;
74
75 } // ::Rose::Frontend::Java::Ecj
76 }// ::Rose::frontend::java
77 }// ::Rose::frontend
78}// ::Rose
79
80using namespace Rose::Frontend::Java::Ecj;
81
82#endif
83
84
85// DQ (11/5/2019): Added to support SageInterface::statementCanBeTransformed().
86namespace EDG_ROSE_Translation
87 {
88 // DQ (9/18/2018): Declare this map so that we can use it for the unparse header files option.
89#if defined(ROSE_BUILD_CXX_LANGUAGE_SUPPORT) && !defined(ROSE_USE_CLANG_FRONTEND)
90 // DQ (12/11/2018): Use the definition in the EDG edgRose.C file if C/C++ support IS defined.
91 extern std::map<std::string, SgIncludeFile*> edg_include_file_map;
92#else
93 // DQ (12/11/2018): Allow this to be the definition if C/C++ support is NOT defined.
94 std::map<std::string, SgIncludeFile*> edg_include_file_map;
95#endif
96 }
97
98
99
100// DQ (12/1/2015): Added to support macro handling.
101#include "detectMacroOrIncludeFileExpansions.h"
102
103namespace SageInterface {
104 template<class T> void setSourcePositionToDefault( T* node );
105}
106
107
108#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
109 #include "transformationSupport.h"
110#endif
111
112// We need this so that USE_CMAKE will be seen (set via configure).
113#include "rose_config.h"
114
115// DQ (3/4/2014): We need this feature to support the function: isStructurallyEquivalentAST().
116#include "RoseAst.h"
117
118// DQ (2/13/2022): We need this feature to support the function: deleteAllNodes().
119#include "AST_FILE_IO.h"
120
121
122// DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
123// The value of 0 allows the old implementation to be tested, and the value of 1 allows the new optimized implementation to be tested.
124#define OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS 1
125
128
129// DQ (3/21/2016): Added support for generateUniqueNameForUseAsIdentifier().
131std::map<std::string,SgNode*> SageInterface::local_name_to_node_map;
132std::map<SgNode*,std::string> SageInterface::local_node_to_name_map;
133
134typedef std::set<SgLabelStatement*> SgLabelStatementPtrSet;
135
136namespace SageInterface
137{
138 Transformation_Record trans_records;
139}
140
141// DQ (12/31/2005): This is OK if not declared in a header file
142using namespace std;
143using namespace Rose;
144using namespace SageBuilder;
145//using namespace Rose::Diagnostics; // for mlog, INFO, WARN, ERROR, FATAL, etc.
146
147// Used by serialize() to collect all types visited
148//std::set<SgType*> type_set;
149// DQ (1/18/2015): Define this container locally in this file only.
150namespace SageInterface
151 {
152 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
153 vector<SgBasicBlock*> addedBasicBlockNodes;
154 }
155
156
157#if 1
158// DQ (2/13/2022): Adding support to delete the whole AST (every SgNode).
159void
161 {
162 // This function uses a memory pool traversal specific to the SgFile IR nodes
163
164 // We need to use this function to get all of the SgNodes.
165 // template <typename NodeType> std::vector<NodeType*> getSgNodeListFromMemoryPool()
166
167 class MyTraversal : public ROSE_VisitTraversal
168 {
169 public:
170 std::vector<SgNode*> resultlist;
171 void visit ( SgNode* node)
172 {
173 SgNode* result = dynamic_cast<SgNode*>(node);
174 ROSE_ASSERT(result != NULL);
175#if 0
176 printf ("In SageInterface::deleteAllNodes(): result = %p = %s \n",result,result->class_name().c_str());
177#endif
178#if 0
179 if (result != NULL)
180 {
181 resultlist.push_back(result);
182 }
183#else
184 resultlist.push_back(result);
185#endif
186 };
187
188 virtual ~MyTraversal() {}
189 };
190
191 // For debugging, recode the number of IR nodes before we delete the AST.
192 size_t numberOfNodes_before = numberOfNodes();
193
194 MyTraversal my_traversal;
195
196 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
197 // NodeType::traverseMemoryPoolNodes(my_traversal);
198 my_traversal.traverseMemoryPool();
199
200 // return my_traversal.resultlist;
201
202
203 // vector<SgNode*> nodeList = getSgNodeListFromMemoryPool<SgNode>();
204 vector<SgNode*> & nodeList = my_traversal.resultlist;
205
206 printf ("In SageInterface::deleteAllNodes(): get list of SgNode: nodeList.size() = %zu \n",nodeList.size());
207
208 vector<SgNode*>::iterator i = nodeList.begin();
209
210 // This loop will call the delete operator on all of the IR nodes in the AST.
211 while (i != nodeList.end())
212 {
213 SgNode* node = *i;
214#if 0
215 // It is an error to be calling get_name() while so many nodes are being deleted.
216 // printf (" --- calling delete (and thus the destructor) node = %p = %s name = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
217 printf (" --- calling delete (and thus the destructor) node = %p = %s \n",node,node->class_name().c_str());
218#endif
219 delete node;
220 node = NULL;
221
222 i++;
223 }
224
225#if 0
226 // This demonstrates that this function only visits the specific IR node that is used as a template parameter.
227 vector<SgFunctionDeclaration*> functionDeclarationList = getSgNodeListFromMemoryPool<SgFunctionDeclaration>();
228 printf ("In SageInterface::deleteAllNodes(): get list of SgFunctionDeclaration: functionDeclarationList.size() = %zu \n",functionDeclarationList.size());
229#endif
230
231 // Now we need to delete the memory pools (implemented by ROSETTA).
232 AST_FILE_IO::clearAllMemoryPools();
233
234 size_t numberOfNodes_after = numberOfNodes();
235
236#if 1
237 printf ("Leaving SageInterface::deleteAllNodes(): numberOfNodes_before = %zu numberOfNodes_after = %zu \n",numberOfNodes_before,numberOfNodes_after);
238#endif
239 }
240#endif
241
242
243#if 0
244// DQ (3/5/2022): Adding support to check AST for invalide poionters.
245void
247 {
248 // This function uses a memory pool traversal to look for any pointers to invalid IR nodes.
249
250 // Step 1: is to build a map of the boundaries of the memory pools for each IR node kind.
251 // Step 2: traverse all of the IR nodes across all of the memory pools and check
252 // a) if the pointer to each node in the list of child IR nodes is in the map from step 1.
253 // b) if it is then we can expect to dereference the pointer and check the value of
254 // get_freepointer(), the value should be 0xffffffffffffffff, else it is an error
255 // (when it is an error it usually should be a value that is in the map from step 1, but it
256 // is a node that was previously deleted, so it is a stale pointer).
257
258 class BuildMapTraversal : public ROSE_VisitTraversal
259 {
260 public:
261 // std::vector<SgNode*> resultlist;
262 // std::map<enum VariantT,std::vector<std::pair<SgNode*,SgNode*>> mapOfMemoryPoolsBounds;
263
264 // We need to get the pools variable for each IR node.
265
266 void visit ( SgNode* node)
267 {
268 // Get list of all pointers to all IR nodes in the current node.
269
270 // $CLASSNAME::pools
272
273 resultlist.push_back(result);
274 };
275
276 virtual ~MyTraversal() {}
277 };
278
279 // For debugging, recode the number of IR nodes before we delete the AST.
280 size_t numberOfNodes_before = numberOfNodes();
281
282 MyTraversal my_traversal;
283
284 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
285 // NodeType::traverseMemoryPoolNodes(my_traversal);
286 my_traversal.traverseMemoryPool();
287 }
288#endif
289
290void
291SageInterface::DeclarationSets::addDeclaration(SgDeclarationStatement* decl)
292 {
293 // DQ (4/3/2014): This function either builds a new set or inserts declarations into an
294 // existing set based on if a set defined by the key (firstNondefiningDeclaration) is present.
295 ASSERT_not_null(decl);
296
297#if 0
298 printf ("TOP of SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
299#endif
300
301 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
302
303 if (firstNondefiningDeclaration == nullptr)
304 {
305 // It appears that some loop transformations (pass3.C) don't set the firstNondefiningDeclaration.
306#if 0
307 printf ("WARNING: SageInterface::DeclarationSets::addDeclaration(): firstNondefiningDeclaration == NULL: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
308#endif
309 return;
310 }
311 ASSERT_not_null(firstNondefiningDeclaration);
312
313 if (decl == firstNondefiningDeclaration)
314 {
315#if 0
316 if (isSgTypedefDeclaration(decl) != nullptr)
317 {
318 printf ("TOP of SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
319 }
320#endif
321 if (declarationMap.find(firstNondefiningDeclaration) == declarationMap.end())
322 {
323#if 0
324 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add a set for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
325#endif
326#if 0
327 if (isSgTypedefDeclaration(decl) != nullptr)
328 {
329 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add a set for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
330 }
331#endif
332 // Add a new set.
333 declarationMap[decl] = new set<SgDeclarationStatement*>();
334
335 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
336 ROSE_ASSERT(declarationMap[decl] != nullptr);
337
338 // Add a declaration to an existing set.
339 declarationMap[firstNondefiningDeclaration]->insert(decl);
340 }
341 else
342 {
343 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
344 {
345#if 0
346 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add the declaration to the existing set: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
347#endif
348#if 0
349 if (isSgTypedefDeclaration(decl) != nullptr)
350 {
351 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add the declaration to the existing set: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
352 }
353#endif
354 // Add a declaration to an existing set.
355 declarationMap[firstNondefiningDeclaration]->insert(decl);
356 }
357 else
358 {
359#if 0
360 printf ("WARNING: SageInterface::DeclarationSets::addDeclaration(): A set already exists for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
361#endif
362 // DQ (4/5/2014): The case of SgFunctionParameterList fails only for boost examples (e.g. test2014_240.C).
363 // Problem uses are associated with SgTemplateInstantiationFunctionDecl IR nodes.
364 bool ignore_error = (isSgFunctionParameterList(decl) != nullptr);
365
366 // DQ (4/17/2014): This is required for the EDG version 4.8 and I don't know why.
367 // Currently the priority is to pass our existing tests.
368 // An idea is that this is sharing introduced as a result of the use of default parameters.
369
370 // DQ (7/2/2014): I am seeing that this is required for a new application using GNU 4.4.7.
371 // It allows a boost issue specific to a revisited SgTypedefDeclaration pass, but I still
372 // don't understand the problem. so this needs a better fix.
373
375 bool isInTemplateFunctionDeclaration = enclosingFunction != nullptr && (isSgTemplateMemberFunctionDeclaration(enclosingFunction) || isSgTemplateFunctionDeclaration(enclosingFunction));
376
377 // Use short-circuit evaluation to improve performance.
378 SgClassDefinition* enclosingClassDefinition = isInTemplateFunctionDeclaration == true ? nullptr : getEnclosingClassDefinition(decl);
379 bool isInTemplateClassDefinition = enclosingClassDefinition != nullptr && isSgTemplateClassDefinition(enclosingClassDefinition);
380
381 bool isInTemplateDeclaration = isInTemplateFunctionDeclaration || isInTemplateClassDefinition;
382
383 ignore_error = ignore_error || (isSgTypedefDeclaration(decl) != nullptr) || (isSgTemplateInstantiationDecl(decl) != nullptr) || (isInTemplateDeclaration == true);
384
385 // DQ (2/5/2015): We need to ignore the case of un-named classes (or maybe those classes
386 // from unnamed classes with lambda member functions). See test2015_13.C for an example.
387 // Or maybe these should have been added to the declarationMap in the front-end?
388 if (isSgClassDeclaration(decl) != nullptr)
389 {
390 ignore_error = ignore_error || (isSgClassDeclaration(decl)->get_isUnNamed() == true);
391 }
392 }
393 }
394 }
395 else
396 {
397 // Add the declaration (make sure there is a set that exists).
398 if (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end())
399 {
400 // Make sure it does not already exist in the set.
401 ROSE_ASSERT (declarationMap[firstNondefiningDeclaration] != nullptr);
402 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
403 {
404 // Add a declaration to an existing set.
405 declarationMap[firstNondefiningDeclaration]->insert(decl);
406 }
407 else
408 {
409#if 0
410 printf ("This declaration is already in the set (skip adding it twice): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
411#endif
412 }
413 }
414 else
415 {
416 // In this case the defining declaration might be the only declaration to be traversed and
417 // so a set has not been built yet.
418#if 0
419 printf ("In SageInterface::DeclarationSets::addDeclaration(): Adding set and declaration for the firstNondefiningDeclaration = %p = %s = %s \n",
420 firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str(),get_name(firstNondefiningDeclaration).c_str());
421#endif
422
423 // DQ (4/5/2014): Just build the set and don't insert the firstNondefiningDeclaration.
424 // If we were to do so then it would be an error to use the insert it later.
425 // Note recursive call.
426 // addDeclaration(firstNondefiningDeclaration);
427 declarationMap[firstNondefiningDeclaration] = new set<SgDeclarationStatement*>();
428
429 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
430
431 // DQ (4/5/2014): We have to insert this since it is different from the firstNondefiningDeclaration.
432 // Add the declaration to the existing set.
433 declarationMap[firstNondefiningDeclaration]->insert(decl);
434
435 // DQ (4/5/2014): Added assertion.
436 ROSE_ASSERT(declarationMap[firstNondefiningDeclaration]->find(decl) != declarationMap[firstNondefiningDeclaration]->end());
437#if 0
438 printf ("SageInterface::DeclarationSets::addDeclaration(): No set exists for the firstNondefiningDeclaration = %p = %s = %s \n",firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str(),get_name(firstNondefiningDeclaration).c_str());
439 ROSE_ABORT();
440#endif
441 }
442 }
443
444#if 0
445 printf ("Leaving SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
446#endif
447 }
448
449const std::set<SgDeclarationStatement*>*
450SageInterface::DeclarationSets::getDeclarations(SgDeclarationStatement* decl)
451 {
452 // DQ (4/3/2014): This function returns the associated set of declarations.
453 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
454
455 ROSE_ASSERT(declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
456
457 const set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
458
459 // return this->declarationMap[firstNondefiningDeclaration];
460 return declarationSet;
461 }
462
463std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* > &
464SageInterface::DeclarationSets::getDeclarationMap()
465 {
466 return declarationMap;
467 }
468
469bool
470SageInterface::DeclarationSets::isLocatedInDefiningScope(SgDeclarationStatement* decl)
471 {
472 // DQ (4/7/2014): This function assumes that the input is a friend declaration.
473
474 // The existence of a declaration in a named scope (if a friend function) will cause
475 // subsequent declarations to be qualified where name qualification is required.
476 // A couple of issues:
477 // We likely need to keep track of the order of the declarations in the more
478 // complex cases because name qualification will be required after the declaration
479 // that appears in the named scope; but will not be required before the declaration in
480 // the named scope.
481
482#define DEBUG_LOCATED_IN_DEFINING_SCOPE 0
483
484 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
485 ROSE_ASSERT(firstNondefiningDeclaration != nullptr);
486
487 set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
488 ROSE_ASSERT(declarationSet != nullptr);
489
490 set<SgDeclarationStatement*>::iterator i = declarationSet->begin();
491
492 bool isDefinedInNamedScope = false;
493
494#if DEBUG_LOCATED_IN_DEFINING_SCOPE
495 printf ("In DeclarationSets::isLocatedInDefiningScope(): decl = %p = %s \n",decl,decl->class_name().c_str());
496 printf (" --- declarationSet->size() = %" PRIuPTR " \n",declarationSet->size());
497#endif
498
499 while (isDefinedInNamedScope == false && i != declarationSet->end())
500 {
501 ROSE_ASSERT(*i != nullptr);
502#if DEBUG_LOCATED_IN_DEFINING_SCOPE
503 printf (" --- *i = %p = %s \n",*i,(*i)->class_name().c_str());
504#endif
505 // We want to know the structural position, not the semantic scope.
506 SgScopeStatement* semantic_scope = (*i)->get_scope();
507 SgScopeStatement* structural_scope = isSgScopeStatement((*i)->get_parent());
508
509#if DEBUG_LOCATED_IN_DEFINING_SCOPE
510 printf (" --- semantic_scope = %p = %s \n",semantic_scope,semantic_scope->class_name().c_str());
511 printf (" --- structural_scope = %p = %s \n",structural_scope,structural_scope->class_name().c_str());
512#endif
513 // DQ (4/7/2014): If it is a member of a class then we don't consider the structural scope, else it makes a difference,
514 SgScopeStatement* scope = isSgClassDefinition(semantic_scope) != nullptr ? semantic_scope : structural_scope;
515 ASSERT_not_null(scope);
516
517#if DEBUG_LOCATED_IN_DEFINING_SCOPE
518 printf (" --- scope = %p = %s \n",scope,scope->class_name().c_str());
519 printf (" --- scope->isNamedScope() = %s \n",scope->isNamedScope() ? "true" : "false");
520#endif
521 SgGlobal* globalScope = isSgGlobal(scope);
522
523 // Friend functions declared in the class definition are not meaningful for determining name qualification.
524 if (globalScope != nullptr || (scope->isNamedScope() == true && isSgClassDefinition(structural_scope) == nullptr) )
525 {
526 // Check if the function is output in the unparing, else it would not be defined.
527 bool willBeOutput = ((*i)->get_file_info()->isCompilerGenerated() == false ||
528 ((*i)->get_file_info()->isCompilerGenerated() &&
529 (*i)->get_file_info()->isOutputInCodeGeneration()) );
530#if DEBUG_LOCATED_IN_DEFINING_SCOPE
531 printf (" --- before: willBeOutput = %s \n",willBeOutput ? "true" : "false");
532#endif
533 // Being output only count when it is output where it is located structurally.
534 willBeOutput = willBeOutput && scope == structural_scope;
535
536#if DEBUG_LOCATED_IN_DEFINING_SCOPE
537 printf (" --- after: willBeOutput = %s \n",willBeOutput ? "true" : "false");
538#endif
539 // DQ (3/20/2016): this is reported by GNU as set but not used.
540 // associatedDeclaration = *i;
541
542 // isDefinedInNamedScope = true;
543 isDefinedInNamedScope = willBeOutput;
544 }
545
546 i++;
547 }
548
549#if DEBUG_LOCATED_IN_DEFINING_SCOPE
550 if (associatedDeclaration != nullptr)
551 {
552 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p = %s \n",associatedDeclaration,associatedDeclaration->class_name().c_str());
553 }
554 else
555 {
556 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p \n",associatedDeclaration);
557 }
558#endif
559
560 return isDefinedInNamedScope;
561 }
562
564SageInterface::buildDeclarationSets(SgNode* n)
565 {
566 DeclarationSets* declarationSet = new DeclarationSets();
567
568 class DeclarationSetTraversal : public AstSimpleProcessing
569 {
570 private:
571 DeclarationSets* declarationSet;
572
573 public:
574 DeclarationSetTraversal(DeclarationSets* ds) : declarationSet(ds) {}
575 void visit (SgNode* node)
576 {
577 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
578 if (decl != nullptr)
579 {
580 declarationSet->addDeclaration(decl);
581 }
582 }
583 };
584
585 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
586 DeclarationSetTraversal traversal(declarationSet);
587 traversal.traverse(n, preorder);
588
589 return declarationSet;
590 }
591
593// DQ: 09/23/03
594// We require a global function for getting the string associated
595// with the definition of a variant (which is a global enum).
596string getVariantName ( VariantT v )
597 {
598 ROSE_ASSERT( int(v) < int(V_SgNumVariants));
599
600 // This code is far simpler (if the function is static)
601
602 // DQ (4/8/2004): Modified code to use new global list of sage
603 // class names (simpler this way)
604 // return string(SgTreeTraversal<int,int>::get_variantName(v));
605 extern const char* roseGlobalVariantNameList[];
606 return string(roseGlobalVariantNameList[v]);
607 }
608
609bool
611 {
612 // DQ (6/7/2012): This refactors the test for template instantiation syntax in names used for classes, member functions, and functions
613 bool usingTemplateSyntax = false;
614 string nameString = name.getString();
615
616 // DQ (6/7/2012): We need to avoid the identification of the "operator<()" as valid template syntax.
617 usingTemplateSyntax = (nameString.find('<') != string::npos) && (nameString.find('>') != string::npos);
618
619 // DQ (5/10/2016): Debugging case of C++11 using the Intel v16 compiler and it's associated mutex header file.
620 // See Cxx11_tests/test2016_32.C for an example that demonstrates this problem.
621 if (nameString == "<unnamed>")
622 {
623 printf ("In SageInterface::hasTemplateSyntax(): Identified case of name == <unnamed> \n");
624
625 usingTemplateSyntax = false;
626 }
627
628 // return (name.getString().find('<') == string::npos);
629 return usingTemplateSyntax;
630 }
631
632
633
634void
636 {
637 // DQ (2/12/2012): Refactoring disagnostic support for detecting where we are when something fails.
638
639 // This highest level node acceptable for us by this function is a SgGlobal (global scope).
640
641 ROSE_ASSERT(node != NULL);
642// printf ("Inside of SageInterface::whereAmI(node = %p = %s) \n",node,node->class_name().c_str());
643
644 // Enforce that some IR nodes should not be acepted inputs.
645 ROSE_ASSERT(isSgFile(node) == NULL);
646 ROSE_ASSERT(isSgFileList(node) == NULL);
647 ROSE_ASSERT(isSgProject(node) == NULL);
648
649 SgNode* parent = node->get_parent();
650
651 // Don't traverse past the SgFile level.
652 while (parent != nullptr && isSgFileList(parent) == nullptr)
653 {
654 // DQ (7/14/2019): These were commented out, but they are intended for debugging, so
655 // if someone does not need this output then the function should not have been called.
656 printf ("--- parent = %p = %s \n",parent,parent->class_name().c_str());
657
658 ROSE_ASSERT(parent->get_file_info() != NULL);
659 parent->get_file_info()->display("In SageInterface::whereAmI() diagnostics support");
660
661 parent = parent->get_parent();
662 }
663 }
664
665void
666SageInterface::initializeIfStmt(SgIfStmt *ifstmt, SgStatement* conditional, SgStatement * true_body, SgStatement * false_body)
667 {
668 // DQ (2/13/2012): Added new function to support proper initialization of a SgIfStmt that has already been built.
669 // This is important when we have to build the scope ahead of the test becasue the text contains a simple
670 // declaration (which must be put into the SgIfStmt scope).
671
672 // SgIfStmt *ifstmt = new SgIfStmt(conditional, true_body, false_body);
673 ROSE_ASSERT(ifstmt);
674
675 if (ifstmt->get_conditional() == nullptr)
676 ifstmt->set_conditional(conditional);
677
678 if (ifstmt->get_true_body() == nullptr)
679 ifstmt->set_true_body(true_body);
680
681 if (ifstmt->get_false_body() == nullptr)
682 ifstmt->set_false_body(false_body);
683
684 // Rasmussen (3/22/2020): Fixed setting case insensitivity
686 ifstmt->setCaseInsensitive(true);
687
689 if (conditional) conditional->set_parent(ifstmt);
690 if (true_body) true_body->set_parent(ifstmt);
691 if (false_body) false_body->set_parent(ifstmt);
692 }
693
694
695void
697 {
698 ROSE_ASSERT(switchStatement != NULL);
699
700 // Rasmussen (3/22/2020): Fixed setting case insensitivity
702 switchStatement->setCaseInsensitive(true);
703
704 if (switchStatement->get_item_selector() == nullptr)
705 switchStatement->set_item_selector(item_selector);
706
707 if (switchStatement->get_body() == nullptr)
708 switchStatement->set_body(body);
709
711 if (item_selector != nullptr)
712 item_selector->set_parent(switchStatement);
713 if (body != nullptr)
714 body->set_parent(switchStatement);
715 }
716
717
718void
720 {
721 ROSE_ASSERT(whileStatement);
722
723 // Rasmussen (3/22/2020): Fixed setting case insensitivity
725 whileStatement->setCaseInsensitive(true);
726
727 if (whileStatement->get_condition() == nullptr)
728 whileStatement->set_condition(condition);
729 if (whileStatement->get_body() == nullptr)
730 whileStatement->set_body(body);
731
732 // Python support.
733 if (whileStatement->get_else_body() == nullptr)
734 whileStatement->set_else_body(else_body);
735
736 setOneSourcePositionNull(whileStatement);
737 if (condition) condition->set_parent(whileStatement);
738 if (body) body->set_parent(whileStatement);
739
740 // DQ (8/10/2011): This is added by Michael to support a Python specific feature.
741 if (else_body != nullptr)
742 {
743 whileStatement->set_else_body(else_body);
744 else_body->set_parent(whileStatement);
745 }
746 }
747
748
749
752 {
753 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
754
755 // This function returns the namespace associated with any declaration.
756 // If the declaration is nested inside of other scopes this function
757 // iterates through these scopes to get the the first namespace.
758 // This is important for details of template handling, namely making sure
759 // that the template specializations (generated by ROSE) are put into the
760 // correct location (namespace) since stricted rules in gnu now enforce
761 // these details. If the declaration is not in a namespace as computed
762 // in the chain of scopes then this function returns nullptr.
763
764 ROSE_ASSERT(declaration != NULL);
765 SgScopeStatement* tempScope = declaration->get_scope();
766
767 // Loop back to the first namespace or stop at global scope (stop on either a namespace or the global scope)
768 while ( isSgNamespaceDefinitionStatement(tempScope) == nullptr && isSgGlobal(tempScope) == nullptr )
769 {
770 tempScope = tempScope->get_scope();
771 ROSE_ASSERT(tempScope != NULL);
772#if 0
773 printf ("Iterating back through scopes: tempScope = %p = %s = %s \n",tempScope,tempScope->class_name().c_str(),SageInterface::get_name(tempScope).c_str());
774#endif
775 }
776
777 SgNamespaceDefinitionStatement* namespaceScope = isSgNamespaceDefinitionStatement(tempScope);
778 return namespaceScope;
779 }
780
781
784 {
785 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
786 // DQ (11/4/2007): Get the associated declaration that will be in the original source code,
787 // if it is part of a template instantiation then get the original template declaration.
788
789 SgDeclarationStatement* parentDeclaration = nullptr;
790
791 SgScopeStatement* defn = memberFunctionInstantiation->get_class_scope();
792 ASSERT_not_null(defn);
793
794 // SgTemplateDeclaration* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
795 SgDeclarationStatement* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
796 ASSERT_not_null(templateDeclaration);
797
798 // If it is a template instatiation, then we have to find the temple declaration (not the template instantiation declaration), else we want the class declaration.
799 SgClassDefinition* cdefn = isSgClassDefinition(defn);
800 SgDeclarationScope* nrscope = isSgDeclarationScope(defn);
801 SgTemplateInstantiationDefn* templateInstatiationClassDefinition = isSgTemplateInstantiationDefn(defn);
802 if (templateInstatiationClassDefinition != nullptr)
803 {
804 // This is the case of a template member function in a templated class (see test2005_172.C).
805 SgTemplateInstantiationDefn* parentTemplateInstantiationDefinition = isSgTemplateInstantiationDefn(templateDeclaration->get_scope());
806 ASSERT_not_null(parentTemplateInstantiationDefinition);
807 SgTemplateInstantiationDecl* parentTemplateInstantiationDeclaration = isSgTemplateInstantiationDecl(parentTemplateInstantiationDefinition->get_declaration());
808 ASSERT_not_null(parentTemplateInstantiationDeclaration);
809
810 parentDeclaration = parentTemplateInstantiationDeclaration->get_templateDeclaration();
811 ASSERT_not_null(parentDeclaration);
812 }
813 else if (cdefn != nullptr)
814 {
815 // This is the case of a template member function in a class definition (see test2005_168.C).
816 parentDeclaration = cdefn->get_declaration();
817 ASSERT_not_null(parentDeclaration);
818 }
819 else if (nrscope != nullptr)
820 {
821 parentDeclaration = isSgDeclarationStatement(nrscope->get_parent());
822 ASSERT_not_null(parentDeclaration);
823 }
824 else
825 {
826 ROSE_ABORT();
827 }
828
829 return parentDeclaration;
830 }
831
835void
837{
838 ASSERT_not_null(var_decl);
839 ASSERT_not_null(base_decl);
840
841 // There is a bug (see gitlab-issue-349.jov) that arises when base_decl has a comment and it is the
842 // first statement, because base_decl will be removed (causing comments to be moved, where? good question!).
843 // Consider moving comments to var_decl first to circumvent (by artfulness or deception) potential problems.
844 // [Rasmussen 2024.04.10]
845
846 // try to remove it from the scope's declaration list
847 // If the struct decl was previously inserted into its scope
848 if (base_decl->get_parent() != nullptr)
849 {
850 if (base_decl->get_scope() == base_decl->get_parent())
851 {
852 SgStatementPtrList stmt_list = base_decl->get_scope()->generateStatementList();
853 if (find(stmt_list.begin(), stmt_list.end(), base_decl) != stmt_list.end())
855 }
856 }
857 base_decl->set_parent(var_decl);
858 var_decl->set_baseTypeDefiningDeclaration(base_decl);
859
860 //Set an internal mangled name for the anonymous declaration, if necessary
861 // resetNamesInAST(); // this will trigger mangleNameMap.size() ==0 assertion.
862 // We call resetEmptyNames directly instead.
863 ResetEmptyNames t1;
864 t1.traverseMemoryPool();
865}
866
867// DQ (11/4/2007): This looks for a forward temple member function declaration of matching name exists in the specified scope.
868bool
870 {
871 // DQ (11/3/2007): Look for an existing previously inserted (or existing) template member function declaration and only add one if we can't find it.
872
873 bool foundExistingPrototype = false;
874
875 ROSE_ASSERT(scope != NULL);
876 ROSE_ASSERT(functionDeclaration != NULL);
877 ROSE_ASSERT(startingAtDeclaration != NULL);
878
879 // TV (09/17/2018): ROSE-1378
880 if (isSgDeclarationScope(scope)) {
881 printf("TODO: SgDeclarationScope handling in SageInterface::isPrototypeInScope see ROSE-1378\n");
882 return false;
883 }
884
885 // These are the scopes for which get_declarationList() is properly defined.
886 ROSE_ASSERT(scope->containsOnlyDeclarations() == true);
887
888 // Note that this is only defined for certain scopes, but we only want it for THOSE scopes
889 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
890
891 // This is a simple way to restrict the evaluation (still linear, but jumps to initial position to start search).
892 SgDeclarationStatementPtrList::iterator startingLocation = find(declarationList.begin(),declarationList.end(),startingAtDeclaration);
893
894 if (startingLocation != declarationList.end())
895 {
896#if 0
897 printf ("startingLocation = %p = %s = %s \n",*startingLocation,(*startingLocation)->class_name().c_str(),SageInterface::get_name(*startingLocation).c_str());
898#endif
899 // printf ("Found the startingLocation is the global scope, now check if we need to add a new declaration \n");
900 SgDeclarationStatementPtrList::iterator i = startingLocation;
901 SgScopeStatement* targetScope = functionDeclaration->get_scope();
902 SgName targetName = functionDeclaration->get_name();
903
904 while (i != declarationList.end())
905 {
906 // printf ("i = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
907
908 // Look for a prototype like what we want to insert, if we find it then we don't need to add a second one!
909 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(*i);
910 if (templateMemberFunction != nullptr)
911 {
912 // Check the name and the scope
913 if (targetScope == templateMemberFunction->get_scope())
914 {
915 if (targetName == templateMemberFunction->get_name())
916 {
917 // Don't count the defining declaration which may be at the end of the global scope.
918 if (templateMemberFunction->isForward() == true)
919 {
920 foundExistingPrototype = true;
921
922 // Exit the loop (optimization)
923 break;
924 }
925 }
926 }
927 }
928
929 i++;
930 }
931 }
932
933 return foundExistingPrototype;
934 }
935
936bool
938 {
939 ROSE_ASSERT(node1 && node2);
940
941 SgNode* curnode = node2;
942 if (node1==node2)
943 {
944 return false;
945 }
946
947 do {
948 curnode= curnode->get_parent();
949 } while( (curnode!=nullptr) && (curnode!=node1));
950
951 if (curnode==node1)
952 {
953 return true;
954 }
955 else
956 {
957 return false;
958 }
959 }
960
961bool
963 {
964 // DQ (12/7/2020): This is supporting the recognition of functions in header files from two different AST.
965
966#define DEBUG_HAS_SAME_SCOPE 0
967
968#if DEBUG_HAS_SAME_SCOPE
969 printf ("In SageInterface::hasSameGlobalScope(): \n");
970 printf (" --- statement_1 = %p = %s \n",statement_1,statement_1->class_name().c_str());
971 printf (" --- statement_2 = %p = %s \n",statement_2,statement_2->class_name().c_str());
972#endif
973
974 bool includingSelf = true;
975 SgGlobal* global_scope_1 = getEnclosingNode<SgGlobal>(statement_1,includingSelf);
976 SgGlobal* global_scope_2 = getEnclosingNode<SgGlobal>(statement_2,includingSelf);
977
978#if DEBUG_HAS_SAME_SCOPE
979 printf (" --- global_scope_1 = %p = %s \n",global_scope_1,global_scope_1->class_name().c_str());
980 SgSourceFile* sourcefile_1 = isSgSourceFile(global_scope_1->get_parent());
981 printf (" --- --- sourcefile_1 = %p filename = %s \n",sourcefile_1,sourcefile_1->getFileName().c_str());
982
983 printf (" --- global_scope_2 = %p = %s \n",global_scope_2,global_scope_2->class_name().c_str());
984 SgSourceFile* sourcefile_2 = isSgSourceFile(global_scope_2->get_parent());
985 printf (" --- --- sourcefile_2 = %p filename = %s \n",sourcefile_2,sourcefile_2->getFileName().c_str());
986#endif
987
988 bool returnResult = (global_scope_1 == global_scope_2);
989
990#if DEBUG_HAS_SAME_SCOPE
991 printf ("Leaving SageInterface::hasSameGlobalScope(): returning: %s \n",returnResult ? "true" : "false");
992#endif
993
994 return returnResult;
995 }
996
997
998std::vector<SgNode*>
1000 {
1001 std::vector<SgNode*> intersectionSet;
1002
1003 // Collect all the IR nodes for the original AST
1004 std::vector<SgNode*> AST_original = NodeQuery::querySubTree (original,V_SgNode);
1005 std::vector<SgNode*> AST_copy = NodeQuery::querySubTree (copy,V_SgNode);
1006
1007 int AST_original_size = AST_original.size();
1008 int AST_copy_size = AST_copy.size();
1009
1010 if (SgProject::get_verbose() > 0)
1011 {
1012 printf ("Original AST size = %d \n",AST_original_size);
1013 printf ("Copy of original AST size = %d \n",AST_copy_size);
1014 }
1015
1016 int differenceInSizes = AST_original_size - AST_copy_size;
1017 if (differenceInSizes == 0)
1018 {
1019 if (SgProject::get_verbose() > 0)
1020 printf ("Copied AST is the SAME size as the original (size = %d) \n",AST_original_size);
1021 }
1022 else
1023 {
1024 printf ("Warning: Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) \n",AST_original_size,AST_copy_size);
1025 }
1026
1027 // Compute the intersection (reference in the copy that point to the origal AST).
1028 // std::set<SgNode*> AST_set_original = AST_original;
1029 std::set<SgNode*> AST_set_original;
1030 for (int i = 0; i < AST_original_size; i++)
1031 {
1032 AST_set_original.insert(AST_original[i]);
1033 }
1034
1035 std::set<SgNode*> AST_set_copy;
1036 for (int i = 0; i < AST_copy_size; i++)
1037 {
1038 AST_set_copy.insert(AST_copy[i]);
1039 }
1040
1041 int size = AST_original_size;
1042 std::vector<SgNode*> intersectionList(size);
1043
1044 // Is there a better way to do this? Build scratch space and then use the different between begin() and end to build another vector.
1045 std::vector<SgNode*>::iterator end = set_intersection(AST_set_original.begin(),AST_set_original.end(),AST_set_copy.begin(),AST_set_copy.end(),intersectionList.begin());
1046
1047 // Build a new vector from the relevant elements of the intersectionList scratch space.
1048 std::vector<SgNode*> meaningIntersectionList = std::vector<SgNode*>(intersectionList.begin(),end);
1049 std::vector<SgNode*> deleteList;
1050 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
1051 {
1052 if (meaningIntersectionList[i] != nullptr && isSgType(meaningIntersectionList[i]) != nullptr)
1053 {
1054 deleteList.push_back(meaningIntersectionList[i]);
1055 }
1056 }
1057
1058 // Remove the types since they are allowed to be shared...
1059 if (SgProject::get_verbose() > 0)
1060 printf ("Remove the types that are allowed to be shared: deleteList.size() = %ld \n",(long)deleteList.size());
1061
1062 for (std::vector<SgNode*>::iterator i = deleteList.begin(); i != deleteList.end(); i++)
1063 {
1064 meaningIntersectionList.erase(find(meaningIntersectionList.begin(),meaningIntersectionList.end(),*i));
1065 }
1066
1067 if (SgProject::get_verbose() > 0)
1068 printf ("After removing the types there are meaningIntersectionList.size() = %ld \n",(long)meaningIntersectionList.size());
1069
1070 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
1071 {
1072 printf (" meaningIntersectionList[%d] = %p = %s = %s \n",i,meaningIntersectionList[i],meaningIntersectionList[i]->class_name().c_str(),get_name(meaningIntersectionList[i]).c_str());
1073 }
1074
1075 int unmatchedIRnodes = 0;
1076 if (help != nullptr)
1077 {
1078 std::vector<SgNode*> tmp_AST_original; // = AST_original;
1079 std::vector<SgNode*> tmp_AST_copy; // = AST_copy;
1080
1081 int AST_original_size = AST_original.size();
1082 for (int j = 0; j < AST_original_size; j++)
1083 {
1084 if (AST_original[j] != NULL && isSgType(AST_original[j]) == NULL)
1085 {
1086 tmp_AST_original.push_back(AST_original[j]);
1087 }
1088 }
1089
1090 int AST_copy_size = AST_copy.size();
1091 for (int j = 0; j < AST_copy_size; j++)
1092 {
1093 if (AST_copy[j] != NULL && isSgType(AST_copy[j]) == NULL)
1094 {
1095 tmp_AST_copy.push_back(AST_copy[j]);
1096 }
1097 }
1098
1099 std::vector<SgNode*> deleteList_original;
1100 std::vector<SgNode*> deleteList_copy;
1101 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1102 {
1103 // printf (" (before removing types) meaningIntersectionList[%d] = %p = %s \n",i,meaningIntersectionList[i],(meaningIntersectionList[i] != NULL) ? meaningIntersectionList[i]->class_name().c_str() : "NULL");
1104 SgCopyHelp::copiedNodeMapTypeIterator i = help->get_copiedNodeMap().find(tmp_AST_original[j]);
1105 // printf ("SgCopyHelp::copiedNodeMapTypeIterator i != help->get_copiedNodeMap().end() = %s \n",i != help->get_copiedNodeMap().end() ? "true" : "false");
1106 if (i != help->get_copiedNodeMap().end())
1107 {
1108 // Matched up an original IR node with it's copy
1109 SgNode* associated_node_copy = i->second;
1110 ROSE_ASSERT(associated_node_copy != NULL);
1111 deleteList_original.push_back(tmp_AST_original[j]);
1112 deleteList_copy.push_back(associated_node_copy);
1113#if 0
1114 // printf ("Original IR node = %p = %s copy = %p \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),associated_node_copy);
1115 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(tmp_AST_original[j]);
1116 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction_copy = isSgTemplateInstantiationMemberFunctionDecl(associated_node_copy);
1117 if (templateMemberFunction != NULL)
1118 {
1119 printf ("In SageInterface::astIntersection(): Found a SgTemplateInstantiationMemberFunctionDecl = %p copy = %p \n",templateMemberFunction,associated_node_copy);
1120 // templateMemberFunction->get_startOfConstruct()->display("original: debug");
1121 // templateMemberFunction_copy->get_startOfConstruct()->display("copy: debug");
1122 }
1123#endif
1124 }
1125 }
1126
1127 int deleteList_original_size = deleteList_original.size();
1128 for (int j = 0; j < deleteList_original_size; j++)
1129 {
1130 // tmp_AST_original.erase(find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]));
1131 std::vector<SgNode*>::iterator k = find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]);
1132 if (k != tmp_AST_original.end())
1133 {
1134 tmp_AST_original.erase(k);
1135 }
1136 }
1137
1138 if (SgProject::get_verbose() > 0)
1139 printf ("IR nodes different between the original AST and the copy of the AST = %" PRIuPTR " \n",tmp_AST_original.size());
1140
1141 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1142 {
1143 printf ("non matched IR node = %p = %s = %s \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),get_name(tmp_AST_original[j]).c_str());
1144 // tmp_AST_original[j]->get_startOfConstruct()->display("debug");
1145 }
1146
1147 unmatchedIRnodes = (int)tmp_AST_original.size();
1148 }
1149
1150 // DQ (11/2/2007): Make this an error now!
1151 if (differenceInSizes != 0)
1152 {
1153 SgProject* originalProject = isSgProject(original);
1154 if (originalProject != NULL)
1155 {
1156 printf ("In %s Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) IR nodes different = %d \n",
1157 (*originalProject)[0]->get_sourceFileNameWithoutPath().c_str(),AST_original_size,AST_copy_size,unmatchedIRnodes);
1158 }
1159
1160 if (unmatchedIRnodes > 0)
1161 {
1162 printf ("Make this an error under stricter testing \n");
1163 ROSE_ABORT();
1164 }
1165 }
1166
1167 return intersectionSet;
1168 }
1169
1170// AJ (10/21/2004): Added support for changing the symbol name associated with an SgInitializedName
1171// by updating the symbol table
1172int
1173SageInterface::set_name ( SgInitializedName *initializedNameNode, SgName new_name )
1174 {
1175 // find the appropriate symbol table, delete the symbol
1176 // with the old name and add a symbol with the new name.
1177 ROSE_ASSERT(initializedNameNode != NULL);
1178
1179#define DEBUG_SET_NAME 0
1180
1181 // SgNode * node = this;
1182#if DEBUG_SET_NAME
1183 printf ("In SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1184#endif
1185
1186#if 0
1187 // DQ (12/9/2004): This should likely call the get_scope function (which is more robust than traversing
1188 // parents, there is a reason why we are forced to include the scope explicitly on some IR nodes,
1189 // see test2004_133.C for details).
1190 while((node!=NULL) && ( isSgScopeStatement(node)==NULL))
1191 node = node->get_parent();
1192
1193 ROSE_ASSERT(node!=NULL);
1194
1195 SgScopeStatement * scope_stmt = isSgScopeStatement(node);
1196#else
1197 SgScopeStatement *scope_stmt = initializedNameNode->get_scope();
1198#endif
1199
1200 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1201 if (isSgEnumDeclaration(initializedNameNode->get_parent()) != NULL)
1202 {
1203 ROSE_ASSERT(scope_stmt != NULL);
1204 printf ("scope_stmt = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1205#if 0
1206 printf ("Detected isSgEnumDeclaration as parent: exiting as a test in SageInterface::set_name() \n");
1207 ROSE_ASSERT(false);
1208#endif
1209 }
1210
1211 ROSE_ASSERT(scope_stmt != NULL);
1212 ROSE_ASSERT(scope_stmt->get_symbol_table() != NULL);
1213 ROSE_ASSERT(scope_stmt->get_symbol_table()->get_table() != NULL);
1214
1215 SgDeclarationStatement * parent_declaration = initializedNameNode->get_declaration();
1216
1217 ROSE_ASSERT(parent_declaration != NULL);
1218
1219 // Find the symbols associated with p_name
1220 std::pair<SgSymbolTable::hash_iterator,SgSymbolTable::hash_iterator> pair_it = scope_stmt->get_symbol_table()->get_table()->equal_range(initializedNameNode->get_name());
1221
1222 SgSymbolTable::hash_iterator found_it = scope_stmt->get_symbol_table()->get_table()->end();
1223
1224 for (SgSymbolTable::hash_iterator it = pair_it.first; it != pair_it.second; ++it)
1225 {
1226#if DEBUG_SET_NAME
1227 printf ("Looking for symbol in scope = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1228 printf (" --- *it = %p = %s \n",(*it).second,(*it).second->class_name().c_str());
1229#endif
1230 switch(parent_declaration->variantT())
1231 {
1232 case V_SgFunctionParameterList:
1233 case V_SgVariableDeclaration:
1234 {
1235 if (isSgVariableSymbol((*it).second) != NULL)
1236 found_it = it;
1237 break;
1238 }
1239
1240 case V_SgClassDeclaration:
1241 {
1242 if (isSgClassSymbol((*it).second) != NULL)
1243 found_it = it;
1244 break;
1245 }
1246
1247 case V_SgFunctionDeclaration:
1248 {
1249 if (isSgFunctionSymbol((*it).second) != NULL)
1250 found_it = it;
1251 break;
1252 }
1253
1254 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1255 case V_SgEnumDeclaration:
1256 {
1257 if (isSgEnumFieldSymbol((*it).second) != NULL)
1258 found_it = it;
1259 break;
1260 }
1261
1262 default:
1263 {
1264 printf ("Default reached in switch in SageInterface::set_name() \n");
1265 }
1266 };
1267 }
1268
1269 // there is no Variable, Class or Function symbol associated with p_name
1270 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1271 {
1272 printf ("Warning: There is no Variable, Class, Function, or EnumValue symbol associated with p_name \n");
1273 return 0;
1274 }
1275
1276 // DQ (11/12/2018): In general, this can't be tested if we permit it to be transformed.
1277 if (statementCanBeTransformed(parent_declaration) == false)
1278 {
1279 printf ("WARNING: SageInterface::set_name(): This statement can not be transformed because it is part of a header file specific more then once with different include file syntax \n");
1280 return 0;
1281 }
1282 else
1283 {
1284#if DEBUG_SET_NAME
1285 printf ("In SageInterface::set_name(): This statement can be transformed! parent_declaration = %p = %s \n",parent_declaration,get_name(parent_declaration).c_str());
1286#endif
1287
1288#if 0
1289 // DQ (11/12/2018): Initial test problem should not permit a transformation!
1290 printf ("Exiting as a test! \n");
1291 ROSE_ABORT();
1292#endif
1293 }
1294
1295 SgSymbol * associated_symbol = (*found_it).second;
1296
1297 // erase the name from there
1298 scope_stmt->get_symbol_table()->get_table()->erase(found_it);
1299
1300 // insert the new_name in the symbol table
1301// CH (4/9/2010): Use boost::unordered instead
1302//#ifdef _MSCx_VER
1303#if 0
1304 // DQ (11/28/2009): Unclear if this code is a problem (testing).
1305
1306// CH (4/7/2010): It seems that the following code can be compiled under MSVC 9.0
1307//#pragma message ("WARNING: this code does not apprear to compile with MSVC.")
1308// printf ("ERROR: this code does not apprear to compile with MSVC. \n");
1309// ROSE_ASSERT(false);
1310 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1311#else
1312 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1313#endif
1314 // if insertion failed
1315 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1316 {
1317 printf ("Warning: insertion of new symbol failed \n");
1318 return 0;
1319 }
1320
1321#if DEBUG_SET_NAME
1322 // Set the p_name to the new_name
1323 printf ("Reset initializedNameNode->get_name() = %s to new_name = %s \n",initializedNameNode->get_name().str(),new_name.str());
1324#endif
1325
1326 // p_name = new_name;
1327 initializedNameNode->set_name(new_name);
1328
1329 // DQ (11/30/2018): Mark the enclosing statement as modified, so that it will be recognized
1330 // in the header file unparsing as being a header file that should be unparsed.
1331 SgStatement* enclosingStatement = getEnclosingStatement(initializedNameNode);
1332 ROSE_ASSERT(enclosingStatement != NULL);
1333 enclosingStatement->set_isModified(true);
1334 enclosingStatement->setTransformation();
1335
1336 // Invalidate the p_iterator, p_no_name and p_name data members in the Symbol table
1337
1338#if 1
1339 // Search the AST for references to this SgInitializedName (SgVarRefExp), check if the symbol matches
1340 // (we can do this since we only reused the exisitng symbol), and mark those expressions as modified.
1341 class RoseVisitor : public ROSE_VisitTraversal
1342 {
1343 public:
1344 int counter;
1345 SgSymbol* symbol;
1346
1348 void visit (SgNode* node)
1349 {
1350 SgVarRefExp* varRefExp = isSgVarRefExp(node);
1351 SgVariableSymbol* variableSymbol = isSgVariableSymbol(symbol);
1352
1353 ROSE_ASSERT(varRefExp != NULL);
1354 ROSE_ASSERT(variableSymbol != NULL);
1355
1356 if (varRefExp->get_symbol() == variableSymbol)
1357 {
1358#if DEBUG_SET_NAME
1359 printf ("In SageInterface::set_name(): Found associated SgVarRefExp varRefExp = %p to symbol associated_symbol = %p \n",varRefExp,variableSymbol);
1360#endif
1361#if 0
1362 printf ("Exiting as a test! \n");
1363 ROSE_ABORT();
1364#endif
1365 varRefExp->set_isModified(true);
1366 varRefExp->setTransformation();
1367#if 1
1368 // DQ (5/2/2021): The traversal over the file will identify the nesting of and transformations in outer (enclosing) IR nodes.
1369 // DQ (5/1/2021): I think that we may have to set the physical node id and maybe make it to be output. This is
1370 // special to the case of using the header file unparsing (any maybe the token-based unparsing with the header
1371 // file unparsing, but I think just the header file unparsing).
1372#if 0
1373 printf ("In SageInterface::set_name(): When unparsing header files, we need to set the physical file id to the correct file \n");
1374#endif
1375 // DQ (4/23/2021): I think it is a problem that the statement is not marked as a transformation so that we
1376 // know how to handle it with the token-based unparsing.
1377 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1378 ROSE_ASSERT(associatedStatement != NULL);
1379 associatedStatement->setTransformation();
1380#endif
1381#if 0
1382 // DQ (11/13/2018): Mark the statement associated with this SgVarRefExp (see test9 in UnparseHeaders_tests).
1383 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1384 ROSE_ASSERT(associatedStatement != NULL);
1385 // associatedStatement->set_isModified(true);
1386 // associatedStatement->set_containsTransformation(true);
1387 associatedStatement->setTransformation();
1388#endif
1389 }
1390 }
1391
1392 RoseVisitor(SgSymbol* symbol_parmeter) : counter(0), symbol(symbol_parmeter)
1393 {
1394#if 0
1395 printf ("roseVisitor::visit: counter %4d node = %s \n",counter,symbol_parmeter->class_name().c_str());
1396#endif
1397 counter++;
1398 }
1399 };
1400
1401 // RoseVisitor visitor;
1402 // visitor.traverseMemoryPool();
1403 RoseVisitor t1(associated_symbol);
1405#endif
1406
1407#if DEBUG_SET_NAME
1408 printf ("Leaving SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s (return 1) \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1409#endif
1410
1411 // DQ (4/23/2021): I think that we should be returning zero for no error
1412 // and one for an error, this function appears to have this detail reversed.
1413 return 1;
1414 }
1415
1416
1417void
1419 {
1420 printf ("In SageInterface::listHeaderFiles(): includeFile filename = %s \n",includeFile->get_filename().str());
1421
1422 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
1423 class PrefixTraversal : public AstSimpleProcessing
1424 {
1425 public:
1426 void visit (SgNode* node)
1427 {
1428 printf ("In listHeaderFiles visit(): node = %p = %s \n",node,node->class_name().c_str());
1429 SgIncludeFile* includeFile = isSgIncludeFile(node);
1430 if (includeFile != NULL)
1431 {
1432 printf ("include file: filename = %s \n",includeFile->get_filename().str());
1433 }
1434 }
1435 };
1436
1437 // Now buid the traveral object and call the traversal (preorder) on the function definition.
1438 PrefixTraversal traversal;
1439 traversal.traverse(includeFile, preorder);
1440
1441 }
1442
1443
1444bool
1446 {
1447 // DQ (5/9/2021): Adding support for detection of statements in a scope that must be unparsed.
1448 // This function supports the token-based unparsing when used with unparsing of header files
1449 // to know when the scope can be unparsed via it's token stream, even though a statement from
1450 // a header file may contain a transformation.
1451 // returns true if there is a statement in the scope that has to be unparsed (is from the same file as the scope).
1452 // returns false if the scope is empty or contains only statements associated with one or more header files.
1453 // When the scope has statements from the same file, then if there is a transformation contained in any of
1454 // those statements then we have to unparse the scope one statement at a time when using the token-based
1455 // unparsing. If the scope has no statements from the same file, then the existance of any statement that
1456 // contains a transformation does not case the statements to be unparsed individually.
1457
1458 ROSE_ASSERT(scope != NULL);
1459 int scope_file_id = scope->get_file_info()->get_physical_file_id();
1460
1461 bool return_value = false;
1462
1463 if (scope->containsOnlyDeclarations() == true)
1464 {
1465 SgDeclarationStatementPtrList & declarationStatementList = scope->getDeclarationList();
1466#if 1
1467 printf ("In scopeHasStatementsFromSameFile(): DeclarationStatementList not implemented \n");
1468#endif
1469#if 1
1470 printf ("declarationStatementList.size() = %zu \n",declarationStatementList.size());
1471#endif
1472 SgDeclarationStatementPtrList::iterator i = declarationStatementList.begin();
1473
1474 while (i != declarationStatementList.end() && return_value == false)
1475 {
1476 SgDeclarationStatement* statement = *i;
1477 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1478
1479 if (statement_file_id == scope_file_id)
1480 {
1481 return_value = true;
1482 }
1483
1484 i++;
1485 }
1486#if 0
1487 printf ("Exiting as a test! \n");
1488 ROSE_ASSERT(false);
1489#endif
1490 }
1491 else
1492 {
1493 SgStatementPtrList & statementList = scope->getStatementList();
1494#if 1
1495 printf ("In scopeHasStatementsFromSameFile(): StatementList not implemented \n");
1496#endif
1497 SgStatementPtrList::iterator i = statementList.begin();
1498
1499 while (i != statementList.end() && return_value == false)
1500 {
1501 SgStatement* statement = *i;
1502 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1503
1504 if (statement_file_id == scope_file_id)
1505 {
1506 return_value = true;
1507 }
1508
1509 i++;
1510 }
1511 }
1512
1513 return return_value;
1514 }
1515
1516
1517namespace
1518{
1519 template <class SageDecl>
1520 std::string genericGetName(SageDecl* dcl)
1521 {
1522 ROSE_ASSERT(dcl);
1523 return dcl->get_name();
1524 }
1525}
1526
1527
1528
1529
1530string
1532 {
1533 string name = "undefined_name";
1534
1535 ROSE_ASSERT(directive != NULL);
1536
1537 name = directive->class_name();
1538
1539#if 1
1540 // I don't think we need this code now!
1541 switch (directive->variantT())
1542 {
1543 // Separate out these cases...
1544 case V_SgIncludeDirectiveStatement:
1545 case V_SgDefineDirectiveStatement:
1546 case V_SgUndefDirectiveStatement:
1547 case V_SgIfdefDirectiveStatement:
1548 case V_SgIfndefDirectiveStatement:
1549 case V_SgDeadIfDirectiveStatement:
1550 case V_SgIfDirectiveStatement:
1551 case V_SgElseDirectiveStatement:
1552 case V_SgElseifDirectiveStatement:
1553 case V_SgLineDirectiveStatement:
1554 case V_SgWarningDirectiveStatement:
1555 case V_SgErrorDirectiveStatement:
1556 case V_SgEmptyDirectiveStatement:
1557 {
1558 name = directive->class_name();
1559 break;
1560 }
1561
1562 // case ClinkageDeclarationStatement:
1563 case V_SgClinkageStartStatement:
1564 case V_SgClinkageEndStatement:
1565 {
1566 name = directive->class_name();
1567 break;
1568 }
1569
1570 case V_SgFortranIncludeLine:
1571 {
1572 name = directive->class_name();
1573 break;
1574 }
1575
1576 default:
1577 // name = "default name (default case reached: not handled)";
1578 printf ("Warning: default case reached in SageInterface::get_name ( const SgC_PreprocessorDirectiveStatement* directive ), directive = %p = %s \n",
1579 directive,directive->class_name().c_str());
1580 ROSE_ABORT();
1581#if 0 // [Robb Matzke 2021-03-24]: unreachable
1582 name = "directive_default_name_case_reached_not_handled";
1583 break;
1584#endif
1585 }
1586#endif
1587
1588 return name;
1589 }
1590
1591string
1593 {
1594 string name = "undefined_name";
1595
1596 ROSE_ASSERT(declaration != NULL);
1597
1598 // DQ (11/23/2008): Handle the case of a Cpp directive...
1599 const SgC_PreprocessorDirectiveStatement* directive = isSgC_PreprocessorDirectiveStatement(declaration);
1600 if (directive != NULL)
1601 {
1602 return SageInterface::get_name (directive);
1603 }
1604
1605 switch (declaration->variantT())
1606 {
1607 case V_SgTemplateMemberFunctionDeclaration:
1608 name = isSgTemplateMemberFunctionDeclaration(declaration)->get_name().str();
1609 break;
1610
1611 case V_SgTemplateFunctionDeclaration:
1612 name = isSgTemplateFunctionDeclaration(declaration)->get_name().str();
1613 break;
1614
1615 case V_SgTemplateClassDeclaration:
1616 name = isSgTemplateClassDeclaration(declaration)->get_name().str();
1617 break;
1618
1619 case V_SgTemplateDeclaration:
1620 name = isSgTemplateDeclaration(declaration)->get_name().str();
1621 break;
1622
1623 case V_SgTemplateInstantiationDecl:
1624 name = isSgTemplateInstantiationDecl(declaration)->get_templateName().str();
1625 break;
1626
1627 case V_SgClassDeclaration:
1628 case V_SgDerivedTypeStatement:
1629 case V_SgJovialTableStatement:
1630 name = isSgClassDeclaration(declaration)->get_name().str();
1631 break;
1632
1633 // Rasmussen (8/2/2019): Added SgJovialDefineDeclaration and SgJovialDirectiveStatement
1634 // I'm not sure class_name() is correct. Probably get_name() should be fixed.
1635 case V_SgJovialDefineDeclaration:
1636 case V_SgJovialDirectiveStatement:
1637 case V_SgJovialCompoolStatement:
1638 name = "__" + declaration->class_name() + "_";
1639 name += StringUtility::numberToString(declaration);
1640 break;
1641
1642 case V_SgJovialLabelDeclaration:
1643 name = isSgJovialLabelDeclaration(declaration)->get_label();
1644 break;
1645
1646 case V_SgEnumDeclaration:
1647 name = isSgEnumDeclaration(declaration)->get_name().str();
1648 break;
1649
1650 // DQ (11/5/2014): Adding support for template typedef declarations (C++11 feature).
1651 case V_SgTemplateInstantiationTypedefDeclaration:
1652 // DQ (11/3/2014): Adding support for template typedef declarations (C++11 feature).
1653 case V_SgTemplateTypedefDeclaration:
1654 case V_SgTypedefDeclaration:
1655 name = isSgTypedefDeclaration(declaration)->get_name().str();
1656 break;
1657
1658 case V_SgFunctionDeclaration:
1659 case V_SgProgramHeaderStatement:
1660 case V_SgProcedureHeaderStatement:
1661 case V_SgMemberFunctionDeclaration:
1662 case V_SgTemplateInstantiationFunctionDecl:
1663 case V_SgTemplateInstantiationMemberFunctionDecl:
1664 case V_SgAdaFunctionRenamingDecl:
1665 case V_SgAdaEntryDecl:
1666 name = isSgFunctionDeclaration(declaration)->get_name().str();
1667 break;
1668
1669 case V_SgNamespaceDeclarationStatement:
1670 name = isSgNamespaceDeclarationStatement(declaration)->get_name().str();
1671 break;
1672
1673 // DQ (2/12/2006): Added support to get name of SgFunctionParameterList
1674 case V_SgFunctionParameterList:
1675 {
1676 // Parents should be set prior to calling these functions (if not we might have to implement that case)
1677 ROSE_ASSERT(declaration->get_parent() != NULL);
1678
1679 if (SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration->get_parent()))
1680 {
1681 name = get_name(functionDeclaration);
1682 }
1683 else if (SgScopeStatement* scopeStmt = isSgScopeStatement(declaration->get_parent()))
1684 {
1685 name = get_name(scopeStmt);
1686 }
1687 else ROSE_ABORT();
1688
1689 name += "_parameter_list_";
1690 break;
1691 }
1692
1693 // DQ (2/10/2012): Added support for template variable declarations (using base class support).
1694 case V_SgTemplateVariableDeclaration:
1695 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.make64Bits();
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 SgSymbol* symbol = NULL;
6739 if (currentScope == NULL)
6740 {
6741 currentScope = SageBuilder::topScopeStack();
6742 }
6743
6744 ROSE_ASSERT(currentScope != NULL);
6745
6746#define DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS 0
6747
6748#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6749 printf ("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): currentScope = %p = %s (templateParameterList = %p templateArgumentList = %p) \n",
6750 currentScope,currentScope->class_name().c_str(),templateParameterList,templateArgumentList);
6751#endif
6752
6753 while ((currentScope != NULL) && (symbol == NULL))
6754 {
6755#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6756 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): name = %s currentScope = %p = %s \n",
6757 name.str(),currentScope,currentScope->class_name().c_str());
6758#endif
6759
6760 // DQ (8/16/2013): Changed API to support template parameters and template arguments.
6761 // symbol = cscope->lookup_symbol(name);
6762 symbol = currentScope->lookup_symbol(name,templateParameterList,templateArgumentList);
6763
6764 if (isSgAliasSymbol(symbol) != NULL)
6765 {
6766#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6767 printf ("Found a SgAliasSymbol: reset to NULL: symbol = %p = %s \n",symbol,symbol->class_name().c_str());
6768#endif
6769 symbol = NULL;
6770 }
6771
6772#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS && 1
6773 // debug
6774 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): symbol = %p \n",symbol);
6775 currentScope->print_symboltable("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): debug");
6776#endif
6777 if (currentScope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6778 currentScope = isSgGlobal(currentScope) ? NULL : currentScope->get_scope();
6779 else
6780 currentScope = NULL;
6781
6782#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6783 printf (" --- In SageInterface:: (base of loop) lookupSymbolInParentScopesIgnoringAliasSymbols(): cscope = %p symbol = %p \n\n",currentScope,symbol);
6784#endif
6785 }
6786
6787 if (symbol == NULL)
6788 {
6789#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6790 printf ("Warning: In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): could not locate the specified name %s in any outer symbol table (templateParameterList = %p templateArgumentList = %p) \n",
6791 name.str(),templateParameterList,templateArgumentList);
6792#endif
6793 // ROSE_ASSERT(false);
6794 }
6795
6796#if 0
6797 printf ("Support for lookupSymbolInParentScopesIgnoringAliasSymbols() is not yet implemented \n");
6798 ROSE_ABORT();
6799#endif
6800
6801 return symbol;
6802 }
6803
6804
6805
6806
6807
6808
6809
6810
6811#if 0
6812// DQ (7/13/2011): This was part of a merge conflict with the above modified function.
6813// It appeas they are the same so this one is commented out.
6815{
6816 SgSymbol* symbol = NULL;
6817 if (cscope == NULL)
6818 cscope = SageBuilder::topScopeStack();
6819 ROSE_ASSERT(cscope);
6820
6821 while ((cscope!=NULL)&&(symbol==NULL))
6822 {
6823 symbol = cscope->lookup_symbol(name);
6824 //debug
6825 // cscope->print_symboltable("debug sageInterface.C L3749...");
6826 if (cscope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6827 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6828 else
6829 cscope = NULL;
6830 }
6831
6832 if (symbol==NULL)
6833 {
6834 // printf ("Warning: could not locate the specified name %s in any outer symbol table \n"e,
6835 // name.str());
6836 // ROSE_ASSERT(false);
6837 }
6838 return symbol;
6839}
6840#endif
6841
6844 {
6845 // DQ (1/24/2011): This function is inconsistant with an implementation that would correctly handle SgAliasSymbols.
6846 // Also this function might get a SgClassSymbol instead of a SgVariableSymbol when both names are used.
6847 // This function needs to be fixed to handle the multi-map semantics of the symbol tables.
6848
6849#if 0
6850 // DQ (5/7/2011): I think this implementation is not correct (does not resolve past hidden types) and so should
6851 // be fixed to be consistant with the implementation of SageInterface::lookupClassSymbolInParentScopes().
6852 // Since I don't know where this function is used, I don't want to change it just yet.
6853 printf ("WARNING: SageInterface::lookupVariableSymbolInParentScopes() should be implemented similar to SageInterface::lookupClassSymbolInParentScopes() \n");
6854
6855 SgVariableSymbol* result = NULL;
6856 SgSymbol* symbol=lookupSymbolInParentScopes(name,cscope);
6857 if (symbol != NULL)
6858 {
6859 if (isSgAliasSymbol(symbol) != NULL)
6860 {
6861 printf ("Error: This SageInterface::lookupVariableSymbolInParentScopes() function does not handle SgAliasSymbols \n");
6862 ROSE_ABORT();
6863 }
6864 result = isSgVariableSymbol(symbol);
6865 }
6866 return result;
6867#else
6868 // I think this is the better implementation.
6869 SgVariableSymbol* symbol = NULL;
6870 if (cscope == NULL)
6871 cscope = SageBuilder::topScopeStack();
6872 ROSE_ASSERT(cscope != NULL);
6873
6874 while ((cscope != NULL) && (symbol == NULL))
6875 {
6876 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6877 symbol = cscope->lookup_variable_symbol(name);
6878
6879 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6880 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6881 else
6882 cscope = NULL;
6883 }
6884
6885 return symbol;
6886#endif
6887 }
6888
6889#define DEBUG_LOOKUP_TEMPLATE_VARIABLE 0
6890
6892SageInterface::lookupTemplateVariableSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList * tplparams, SgTemplateArgumentPtrList* tplargs, SgScopeStatement *cscope)
6893 {
6894#if DEBUG_LOOKUP_TEMPLATE_VARIABLE
6895 printf ("In SageInterface::lookupTemplateVariableSymbolInParentScopes():\n");
6896 printf (" -- name = %s\n", name.str());
6897 printf (" -- tplparams = %p [%zd]\n", tplparams, tplparams ? tplparams->size() : 0);
6898 printf (" -- tplargs = %p [%zd]\n", tplargs, tplargs ? tplargs->size() : 0);
6899 printf (" -- cscope = %p (%s)\n", cscope, cscope ? cscope->class_name().c_str() : "");
6900#endif
6901
6902 SgTemplateVariableSymbol* symbol = NULL;
6903 if (cscope == NULL)
6904 cscope = SageBuilder::topScopeStack();
6905 ROSE_ASSERT(cscope != NULL);
6906
6907 while ((cscope != NULL) && (symbol == NULL))
6908 {
6909 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6910 symbol = cscope->lookup_template_variable_symbol(name, tplparams, tplargs);
6911
6912 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6913 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6914 else
6915 cscope = NULL;
6916 }
6917
6918 return symbol;
6919 }
6920
6921// SgClassSymbol* SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
6923SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateArgumentPtrList* templateArgumentList)
6924 {
6925 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6926 SgClassSymbol* symbol = NULL;
6927 if (cscope == NULL)
6928 cscope = SageBuilder::topScopeStack();
6929 ROSE_ASSERT(cscope != NULL);
6930
6931 while ((cscope != NULL) && (symbol == NULL))
6932 {
6933 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6934 // symbol = cscope->lookup_class_symbol(name,NULL);
6935 symbol = cscope->lookup_class_symbol(name,templateArgumentList);
6936
6937 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6938 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6939 else
6940 cscope = NULL;
6941 }
6942
6943 return symbol;
6944 }
6945
6947SageInterface::lookupNonrealSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6948 {
6949 SgNonrealSymbol* symbol = NULL;
6950 if (cscope == NULL)
6951 cscope = SageBuilder::topScopeStack();
6952 ROSE_ASSERT(cscope != NULL);
6953
6954 while ((cscope != NULL) && (symbol == NULL))
6955 {
6956 symbol = cscope->lookup_nonreal_symbol(name,templateParameterList,templateArgumentList);
6957
6958 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6959 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6960 else
6961 cscope = NULL;
6962 }
6963
6964 return symbol;
6965 }
6966
6969 {
6970 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6971 SgTypedefSymbol* symbol = NULL;
6972 if (cscope == NULL)
6973 cscope = SageBuilder::topScopeStack();
6974 ROSE_ASSERT(cscope != NULL);
6975
6976#if 0
6977 printf ("In lookupTypedefSymbolInParentScopes(): name = %s starting with cscope = %p = %s \n",name.str(),cscope,cscope->class_name().c_str());
6978 printf ("--- parent scope = %p = %s \n",cscope->get_scope(),(cscope->get_scope() != NULL) ? cscope->get_scope()->class_name().c_str() : "null");
6979#endif
6980
6981 while ((cscope != NULL) && (symbol == NULL))
6982 {
6983 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6984 symbol = cscope->lookup_typedef_symbol(name);
6985
6986 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6987 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6988 else
6989 cscope = NULL;
6990
6991#if 0
6992 printf ("In lookupTypedefSymbolInParentScopes(): symbol = %p next cscope = %p = %s \n",symbol,cscope,(cscope != NULL) ? cscope->class_name().c_str() : "null");
6993#endif
6994 }
6995
6996#if 0
6997 printf ("Leaving lookupTypedefSymbolInParentScopes(): symbol = %p \n",symbol);
6998#endif
6999
7000 return symbol;
7001 }
7002
7003#if 0
7004// DQ (8/13/2013): This function does not make since any more, now that we have make the symbol
7005// table handling more precise and we have to provide template parameters for any template lookup.
7006// We also have to know if we want to lookup template classes, template functions, or template
7007// member functions (since each have specific requirements).
7009SageInterface::lookupTemplateSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
7010 {
7011 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7012 SgTemplateSymbol* symbol = NULL;
7013 if (cscope == NULL)
7014 cscope = SageBuilder::topScopeStack();
7015 ROSE_ASSERT(cscope != NULL);
7016
7017 while ((cscope != NULL) && (symbol == NULL))
7018 {
7019 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7020 // In this case these are unavailable from this point.
7021 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7022 // symbol = cscope->lookup_template_symbol(name);
7023 symbol = cscope->lookup_template_symbol(name,NULL,NULL);
7024#if 0
7025 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7026#endif
7027 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7028 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7029 else
7030 cscope = NULL;
7031 }
7032
7033 return symbol;
7034 }
7035#endif
7036
7037
7039SageInterface::lookupTemplateClassSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList, SgScopeStatement *cscope)
7040 {
7041 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7042 SgTemplateClassSymbol* symbol = NULL;
7043 if (cscope == NULL)
7044 cscope = SageBuilder::topScopeStack();
7045 ROSE_ASSERT(cscope != NULL);
7046
7047 while ((cscope != NULL) && (symbol == NULL))
7048 {
7049 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7050 // In this case these are unavailable from this point.
7051 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7052 // symbol = cscope->lookup_template_symbol(name);
7053 symbol = cscope->lookup_template_class_symbol(name,templateParameterList,templateArgumentList);
7054#if 0
7055 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7056#endif
7057 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7058 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7059 else
7060 cscope = NULL;
7061 }
7062
7063 return symbol;
7064 }
7065
7066
7069 {
7070 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7071 // A templated solution might make for a better implementation.
7072 SgEnumSymbol* symbol = NULL;
7073 if (cscope == NULL)
7074 cscope = SageBuilder::topScopeStack();
7075 ROSE_ASSERT(cscope != NULL);
7076
7077 while ((cscope != NULL) && (symbol == NULL))
7078 {
7079 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7080 symbol = cscope->lookup_enum_symbol(name);
7081
7082 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7083 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7084 else
7085 cscope = NULL;
7086 }
7087
7088 return symbol;
7089 }
7090
7093 {
7094 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7095 SgNamespaceSymbol* symbol = NULL;
7096 if (cscope == NULL)
7097 cscope = SageBuilder::topScopeStack();
7098 ROSE_ASSERT(cscope != NULL);
7099
7100 while ((cscope != NULL) && (symbol == NULL))
7101 {
7102 // I think this will resolve SgAliasSymbols to be a SgNamespaceSymbol where the alias is of a SgNamespaceSymbol.
7103 symbol = cscope->lookup_namespace_symbol(name);
7104
7105 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7106 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7107 else
7108 cscope = NULL;
7109 }
7110
7111 return symbol;
7112 }
7113
7114template<class T>
7115void
7116SageInterface::setSourcePositionToDefault( T* node )
7117 {
7118 // This is a templated function because SgPragma is not yet derived from SgLocatedNode.
7119
7120 // DQ (2/17/2013): This function is called a lot, so it might be a performance issue.
7121 // All IR nodes built by the Build Interface are assighed source position information
7122 // using this function and then reset afterward as we use information within EDG to
7123 // reset the source position information. Ideally, the EDG/ROSE connection would
7124 // use NULL pointers as the behavior for the front-end mode. We can move to that
7125 // later to maek the source position handling more efficient.
7126
7127 // DQ (1/24/2009): It might be that this function is only called from the Fortran support.
7128
7129 // This function sets the source position to be marked as not
7130 // available (since we often don't have token information)
7131 // These nodes WILL be unparsed in the conde generation phase.
7132
7133 // The SgLocatedNode has both a startOfConstruct and endOfConstruct source position.
7134 ROSE_ASSERT(node != NULL);
7135
7136 // We have to support this being called where the Sg_File_Info have previously been set.
7137 if (node->get_endOfConstruct() == NULL && node->get_startOfConstruct() == NULL)
7138 {
7139#if 0
7140 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());
7141#endif
7142 // Check the endOfConstruct first since it is most likely NULL (helpful in debugging)
7143 ROSE_ASSERT(node->get_endOfConstruct() == NULL);
7144 ROSE_ASSERT(node->get_startOfConstruct() == NULL);
7145
7148
7149 // DQ (5/2/2012): I think we don't want to do this.
7150#if 0
7151 printf ("In SageInterface::setSourcePositionToDefault(): Calling setSourcePositionUnavailableInFrontend() \n");
7152#endif
7153 start_fileInfo->setSourcePositionUnavailableInFrontend();
7154 end_fileInfo->setSourcePositionUnavailableInFrontend();
7155
7156 // DQ (5/2/2012): I think we don't want to do this.
7157#if 0
7158 printf ("In SageInterface::setSourcePositionToDefault(): Calling setOutputInCodeGeneration() \n");
7159#endif
7160 // This is required for the unparser to output the code from the AST.
7161 start_fileInfo->setOutputInCodeGeneration();
7162 end_fileInfo->setOutputInCodeGeneration();
7163
7164 node->set_startOfConstruct(start_fileInfo);
7165 node->set_endOfConstruct (end_fileInfo);
7166
7167 node->get_startOfConstruct()->set_parent(node);
7168 node->get_endOfConstruct ()->set_parent(node);
7169 }
7170 else
7171 {
7172 // If both the starting and ending Sg_File_Info pointers are not NULL then both must be valid.
7173 // We don't want to support partially completed source code position information.
7174#if 0
7175 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());
7176#endif
7177 if (node->get_startOfConstruct() == NULL)
7178 {
7179 printf ("ERROR: startOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7180 }
7181 if (node->get_endOfConstruct() == NULL)
7182 {
7183 printf ("ERROR: endOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7184 }
7185
7186 ROSE_ASSERT(node->get_startOfConstruct() != NULL);
7187 ROSE_ASSERT(node->get_endOfConstruct() != NULL);
7188 ROSE_ASSERT(node->get_endOfConstruct() != NULL && node->get_startOfConstruct() != NULL);
7189 }
7190
7191 // DQ (11/2/2012): This is an important fix to support the new EDG 4.x branch.
7192 // Note that because the unparser will use the function isFromAnotherFile() in the unparsing
7193 // of expressions, specifically: SgAggregateInitializer, SgCompoundInitializer, and anything
7194 // in their expression lists (which could be any expression). The isFromAnotherFile() will
7195 // use the get_file_info() function on the SgExpression IR nodes and the data from that
7196 // Sg_File_Info object to determine if that expression subtree should be unparsed. This
7197 // expression level granularity of unparsing capability is extremely useful in handling
7198 // now #includes and other CPP directives are woven back into the AST. But since the
7199 // get_file_info() function is used, and it returns the value of get_operatorPosition(),
7200 // it is critically important to have correct data in the SgExpression::p_operatorPosition
7201 // Sg_File_Info object (it counts more that the startOfConstruct and endOfConstruct
7202 // Sg_File_Info objects in controlling what expressions are unparsed. So we have to set these
7203 // up for all expressions (since any SgExpression could appear in the list contained in
7204 // a SgAggregateInitializer or SgCompoundInitializer.
7205
7206 // DQ (11/2/2012): Set the operator source position information to default values.
7207 // This will trigger it to be reset to valid source position information in the front-end.
7208 SgExpression* expression = isSgExpression(node);
7209 if (expression != NULL)
7210 {
7211#if 0
7212 SgBinaryOp* binaryOp = isSgBinaryOp(expression);
7213 if (binaryOp != NULL)
7214 {
7215 if (binaryOp->get_operatorPosition() == NULL)
7216 {
7218 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7219 operator_fileInfo->setOutputInCodeGeneration();
7220 binaryOp->set_operatorPosition(operator_fileInfo);
7221
7222 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7223 binaryOp->get_operatorPosition()->set_parent(binaryOp);
7224 }
7225 }
7226#else
7227 // Setup all of the SgExpression operatorPosition pointers to default objects.
7228 if (expression->get_operatorPosition() == NULL)
7229 {
7231 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7232 operator_fileInfo->setOutputInCodeGeneration();
7233 expression->set_operatorPosition(operator_fileInfo);
7234
7235 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7236 // expression->get_operatorPosition()->set_parent(expression);
7237 operator_fileInfo->set_parent(expression);
7238 ROSE_ASSERT(expression->get_operatorPosition()->get_parent() == expression);
7239 }
7240#endif
7241 }
7242 }
7243
7244
7245void
7247 {
7248 // DQ (5/1/2012): Older depricated function.
7249#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
7250 printf ("+++++ Depricated function (use setSourcePositionAsTransformation() instead) (no using internal source position mode) \n");
7251#endif
7252
7253 // setSourcePositionAsTransformation(node);
7254 setSourcePosition(node);
7255 }
7256
7257
7258void
7260 {
7261 // DQ (5/1/2012): Newer function to support specification of IR nodes being a part of a transformation.
7262
7263 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionAsTransformation(SgNode *node)"
7264 // The logic should be make more independent of if (locatedNode->get_startOfConstruct() == NULL)
7265 // Since that make understanding where the function is applied too complex.
7266 // If (locatedNode->get_startOfConstruct() != NULL), then we should just make that Sg_File_Info as
7267 // a transforamtion directly, this function misses that step.
7268
7269 ROSE_ASSERT(node != NULL);
7270
7271 // DQ (10/12/2012): Commented out since we are past AST regression tests passing and now trying to get this work checked in.
7272// printf ("In SageInterface::setSourcePositionAsTransformation() for node = %p = %s (make this an error while debugging AST construction) \n",node,node->class_name().c_str());
7273 // ROSE_ASSERT(false);
7274
7275 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7276 SgExpression* expression = isSgExpression(node);
7277 // SgInitializedName* initName = isSgInitializedName(node);
7278 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7279 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7280
7281#if 0
7282 SgVariableDefinition * v_d = isSgVariableDefinition(node);
7283 if (v_d )
7284 printf ("Debug, Found a variable definition: %p\n", v_d);
7285#endif
7286
7287 if (locatedNode != NULL)
7288 {
7290 locatedNode->get_startOfConstruct()->set_parent(locatedNode);
7291
7292 if (global==NULL)
7293 {
7295 locatedNode->get_endOfConstruct ()->set_parent(locatedNode);
7296 }
7297
7298 // Only SgExpression IR nodes have a 3rd source position data structure.
7299 if (expression!=NULL)
7300 {
7301 expression->set_operatorPosition(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7302 expression->get_operatorPosition()->set_parent(expression);
7303 }
7304 }
7305 else // special non-located node with file info
7306 {
7307 if ( (pragma != NULL) && (pragma->get_startOfConstruct() == NULL) )
7308 {
7309 pragma->set_startOfConstruct(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7310 pragma->get_startOfConstruct()->set_parent(pragma);
7311 }
7312 }
7313 }
7314
7315
7316void
7318 {
7319 // DQ (5/1/2012): Older depricated function (use setSourcePositionPointersToNull() instead).
7320#if 0
7321 printf ("+++++ Depricated name setOneSourcePositionNull() (use setSourcePositionPointersToNull() instead) (no using internal source position mode) \n");
7322#endif
7323
7324 setSourcePosition(node);
7325 }
7326
7327// DQ (5/1/2012): Newly renamed function (previous name preserved for backward compatability).
7328void
7330 {
7331 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionToNULL(SgNode *node)"
7332 // However, if this is doen then the logic should be that it asserts that: (locatedNode->get_startOfConstruct() == NULL)
7333 // so that we know when we are leaking memory. Similarly, we should assert that:
7334 // (locatedNode->get_endOfConstruct() == NULL).
7335 // But then this function just asserts that everything is already NULL and is less about setting them to NULL.
7336 // If (locatedNode->get_startOfConstruct() != NULL), should we delete the existing Sg_File_Info object?
7337 // This function misses that step.
7338
7339 ROSE_ASSERT(node != NULL);
7340
7341 SgLocatedNode * locatedNode = isSgLocatedNode(node);
7342 SgExpression* expression = isSgExpression(node);
7343 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7344 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7345
7346 // DQ (1/24/2009): If the point is to set the source position to NULL pointers,
7347 // why do we only handle the case when (get_startOfConstruct() == NULL)
7348 // (i.e. when the start source postion is already NULL).
7349
7350 if (locatedNode != NULL)
7351 {
7352 if (locatedNode->get_startOfConstruct() != NULL)
7353 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of startOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7354
7355 locatedNode->set_startOfConstruct(NULL);
7356
7357 // Note that SgGlobal should have NULL endOfConstruct()
7358 if (global == NULL)
7359 {
7360 if (locatedNode->get_endOfConstruct() != NULL)
7361 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of endOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7362
7363 locatedNode->set_endOfConstruct(NULL);
7364 }
7365
7366 // Only SgExpression IR nodes have a 3rd source position data structure.
7367 if (expression != NULL)
7368 {
7369 if (expression->get_operatorPosition() != NULL)
7370 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of operatorPosition Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7371
7372 expression->set_operatorPosition(NULL);
7373 }
7374 }
7375 else
7376 {
7377 if ( (pragma != NULL) && (pragma->get_startOfConstruct() != NULL) )
7378 {
7379 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7380
7381 pragma->set_startOfConstruct(NULL);
7382 }
7383 }
7384 }
7385
7386// DQ (1/24/2009): Could we change the name to be "setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)"
7387void
7389 {
7390#if 1
7391#if 0
7392 printf ("+++++ Depricated name setSourcePositionForTransformation() (use setSourcePositionAtRootAndAllChildrenAsTransformation() instead) \n");
7393#endif
7394
7395 // This is the semantically correct function to call.
7396 // setSourcePositionAtRootAndAllChildrenAsTransformation(root);
7397
7398 // 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.
7399 // setSourcePosition(root);
7400 // Liao 11/21/2012. This function should only be called when the mode is transformation
7401 // Liao 8/2/2013. It can actually be called inside frontend by OmpSupport::lower_omp().
7402 //ROSE_ASSERT(SageBuilder::SourcePositionClassificationMode == SageBuilder::e_sourcePositionTransformation);
7404#else
7405 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7406 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7407 {
7409 }
7410#endif
7411 }
7412
7413
7414#if 0
7415// DQ (5/1/2012): New function with improved name (still preserving the previous interface).
7416void
7417SageInterface::setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)
7418 {
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 }
7425#endif
7426
7427#if 0
7428void
7429SageInterface::setSourcePositionAtRootAndAllChildrenAsDefault(SgNode *root)
7430 {
7431 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7432 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7433 {
7434 setSourcePositionAsDefault(*i);
7435 }
7436 }
7437#endif
7438
7439void
7441 {
7442 // DQ (2/17/2013): This is a relatively expensive operation so we might look into this.
7443
7444 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7445
7446#if 0
7447 printf ("In setSourcePositionAtRootAndAllChildren(): nodeList.size() = %" PRIuPTR " \n",nodeList.size());
7448#endif
7449
7450 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
7451 {
7452#if 0
7453 printf ("In setSourcePositionAtRootAndAllChildren(): *i = %p = %s \n",*i,(*i)->class_name().c_str());
7454#endif
7456 }
7457 }
7458
7459// DQ (5/1/2012): This function queries the SageBuilder::SourcePositionClassification mode (stored in the SageBuilder
7460// interface) and used the specified mode to initialize the source position data (Sg_File_Info objects). This
7461// function is the only function that should be called directly (though in a namespace we can't define permissions).
7462void
7464 {
7465 // Check the mode and build the correct type of source code position.
7467
7468 // DQ (2/17/2013): Note that the SourcePositionClassification will be e_sourcePositionFrontendConstruction
7469 // during construction of the AST from the EDG frontend.
7470
7471#if 0
7472 printf ("In SageInterface::setSourcePosition(): SourcePositionClassification scp = %s \n",display(scp).c_str());
7473#endif
7474
7475 switch(scp)
7476 {
7477 case e_sourcePositionError: // Error value for enum.
7478 {
7479 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7480 ROSE_ABORT();
7481 }
7482
7483 case e_sourcePositionDefault: // Default source position.
7484 {
7485#if 0
7486 printf ("e_sourcePositionDefault in SageInterface::setSourcePosition() \n");
7487#endif
7488 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7489 if (locatedNode != NULL)
7490 {
7491 setSourcePositionToDefault(locatedNode);
7492 }
7493 else
7494 {
7495 // This is not supported (not clear if it need be).
7496 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionDefault with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7497 ROSE_ABORT();
7498 }
7499 break;
7500 }
7501
7502 case e_sourcePositionTransformation: // Classify as a transformation.
7503 {
7504#if 0
7505 printf ("e_sourcePositionTransformation in SageInterface::setSourcePosition() \n");
7506#endif
7507 // setSourcePositionAtRootAndAllChildrenAsTransformation(node);
7509 break;
7510 }
7511
7512 case e_sourcePositionCompilerGenerated: // Classify as compiler generated code (e.g. template instantiation).
7513 {
7514 printf ("e_sourcePositionCompilerGenerated in SageInterface::setSourcePosition() \n");
7515
7516 printf ("Sorry, not implemented \n");
7517 ROSE_ABORT();
7518 }
7519
7520 case e_sourcePositionNullPointers: // Set pointers to Sg_File_Info objects to NULL.
7521 {
7522 // DQ (2/17/2013): We want to move to this mode as the one used for EDG/ROSE connection so that we can
7523 // avoid building and rebuilding source position information.
7524#if 0
7525 printf ("e_sourcePositionNullPointers in SageInterface::setSourcePosition() \n");
7526#endif
7528 break;
7529 }
7530
7531 case e_sourcePositionFrontendConstruction: // Specify as source position to be filled in as part of AST construction in the front-end.
7532 {
7533 // DQ (2/17/2013): The setSourcePositionToDefault() function is called a lot, so it might be a performance issue.
7534 // All IR nodes built by the Build Interface are assighed source position information
7535 // using this function and then reset afterward as we use information within EDG to
7536 // reset the source position information. Ideally, the EDG/ROSE connection would
7537 // use NULL pointers as the behavior for the front-end mode. We can move to that
7538 // later to make the source position handling more efficient.
7539
7540 // This function builds an empty Sg_File_Info entry (valid object but filled with default values; must be reset in front-end processing).
7541#if 0
7542 printf ("e_sourcePositionFrontendConstruction in SageInterface::setSourcePosition() \n");
7543#endif
7544 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7545 if (locatedNode != NULL)
7546 {
7547 // setSourcePositionAtRootAndAllChildrenAsDefault(locatedNode);
7548 setSourcePositionToDefault(locatedNode);
7549 }
7550 else
7551 {
7552 // This is not supported (not clear if it need be).
7553 SgPragma* pragma = isSgPragma(node);
7554 if (pragma != NULL)
7555 {
7556 setSourcePositionToDefault(pragma);
7557 }
7558 else
7559 {
7560 // printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7561 // ROSE_ASSERT(false);
7562 SgType* type = isSgType(node);
7563 if (type != NULL)
7564 {
7565 // Ignore this case, OK.
7566 }
7567 else
7568 {
7569 SgFunctionParameterTypeList* functionParameterTypeList = isSgFunctionParameterTypeList(node);
7570 if (functionParameterTypeList != NULL)
7571 {
7572 // Ignore this case, OK.
7573 }
7574 else
7575 {
7576 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7577 ROSE_ABORT();
7578 }
7579 }
7580 }
7581 }
7582
7583 break;
7584 }
7585
7586
7588 {
7589 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7590 ROSE_ABORT();
7591 }
7592
7593 default:
7594 {
7595 printf ("Error: default reached in SageInterface::setSourcePosition() \n");
7596 break;
7597 }
7598 }
7599
7600#if 0
7601 if (node->get_file_info() != NULL)
7602 {
7603 node->get_file_info()->display("Leaving SageInterface::setSourcePosition()");
7604 }
7605#endif
7606 }
7607
7608#if 0
7609void
7610SageInterface::setSourcePositionForTransformation_memoryPool()
7611 {
7612 // DQ (1/24/2009): This seems like a very dangerous function to have, is it required!
7613
7614 // DQ (5/1/2012): Make it an error to call this function.
7615 printf ("ERROR: In setSourcePositionForTransformation_memoryPool(): This seems like a very dangerous function to have, is it required? \n");
7616 ROSE_ABORT();
7617
7618 VariantVector vv(V_SgNode);
7619 Rose_STL_Container<SgNode*> nodeList = NodeQuery::queryMemoryPool(vv);
7620 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++ )
7621 {
7623 }
7624 }
7625#endif
7626
7628 {
7629 // Liao, 1/9/2008, get the first global scope from current project
7630 // mostly used to prepare for AST construction under the global scope
7631 ROSE_ASSERT(project != NULL);
7632
7633 // DQ (1/24/2009): Added a check to make sure STL list is non-empty.
7634 ROSE_ASSERT(project->get_fileList().empty() == false);
7635
7636 // SgGlobal* global = project->get_file(0).get_root();
7637 SgSourceFile* file = isSgSourceFile(project->get_fileList()[0]);
7638 SgGlobal* global = file->get_globalScope();
7639
7640#if 0
7641 SgFilePtrListPtr fileList = project->get_fileList();
7642 SgFilePtrList::const_iterator i= fileList->begin();
7643
7644 SgGlobal* global = (*i)->get_globalScope();
7645#endif
7646 ROSE_ASSERT(global != NULL);
7647
7648 return global;
7649 }
7650
7651// Liao, 1/10/2008, get the last stmt from the scope
7652// two cases
7653// SgScopeStatement::getDeclarationList
7654// SgScopeStatement::getStatementList()
7656 {
7657 ROSE_ASSERT(scope);
7658 SgStatement* stmt = NULL;
7659
7660 if (scope->containsOnlyDeclarations())
7661 {
7662 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7663 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7664 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7665
7666 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7667 if (declList.empty() == false)
7668 {
7669 stmt = isSgStatement(declList.back());
7670 }
7671 }
7672 else
7673 {
7674 // DQ (2/17/2013): Fixed stmtList to be a reference instead of a copy.
7675 SgStatementPtrList & stmtList = scope->getStatementList();
7676
7677 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7678 if (stmtList.empty() == false)
7679 {
7680 stmt = stmtList.back();
7681 }
7682 }
7683
7684 return stmt;
7685 }
7686
7687
7688SgStatement* SageInterface::getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated/*=false*/)
7689 {
7690 // DQ (2/17/2013): This function appears to be a performance problem (so a pass was made to
7691 // use lower complexity operations that are equivalent in funcionality for this context).
7692
7693 ROSE_ASSERT(scope);
7694 SgStatement* stmt = NULL;
7695
7696 if (scope->containsOnlyDeclarations())
7697 {
7698 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7699 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7700 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7701 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7702 if (includingCompilerGenerated)
7703 {
7704 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7705 // DQ Note: (declList.empty() == false) is a much faster test O(1) than (declList.size() > 0), which is O(n).
7706 if (declList.empty() == false)
7707 {
7708 stmt = isSgStatement(declList.front());
7709 }
7710 }
7711 else
7712 {
7713 // skip compiler-generated declarations
7714 SgDeclarationStatementPtrList::iterator i=declList.begin();
7715 while (i != declList.end())
7716 {
7717 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7718 // some content from headers included are not marked as compiler-generated
7719 //
7720 // cout<<(*i)->unparseToString()<<endl;
7721 // ((*i)->get_file_info())->display("debug.......");
7722 Sg_File_Info * fileInfo = (*i)->get_file_info();
7723 // include transformation-generated statements, but not the hidden ones
7724 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7725 if ((fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation() && fileInfo->isOutputInCodeGeneration()))
7726 {
7727 stmt = *i;
7728 break;
7729 }
7730 else
7731 {
7732 i++;
7733 continue;
7734 }
7735 }
7736 }
7737 }
7738 else
7739 {
7740 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7741 SgStatementPtrList & stmtList = scope->getStatementList();
7742 if (includingCompilerGenerated)
7743 {
7744 // DQ (2/17/2013): Fixed evaluation of empty list use SgStatementPtrList::empty() member function for faster performance.
7745 // DQ Note: (stmtList.empty() == false) is a much faster test O(1) than (stmtList.size() > 0), which is O(n).
7746 if (stmtList.empty() == false)
7747 {
7748 stmt = stmtList.front();
7749 }
7750 }
7751 else
7752 {
7753 // skip compiler-generated declarations
7754 SgStatementPtrList::iterator i = stmtList.begin();
7755 while (i!=stmtList.end())
7756 {
7757 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7758 // some content from headers included are not marked as compiler-generated
7759 //
7760 // cout<<(*i)->unparseToString()<<endl;
7761 // ((*i)->get_file_info())->display("debug.......");
7762 Sg_File_Info * fileInfo = (*i)->get_file_info();
7763 // include transformation-generated statements, but not the hidden ones
7764 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7765 if ( (fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration()))
7766 {
7767 stmt=*i;
7768 break;
7769 }
7770 else
7771 {
7772 i++;
7773 continue;
7774 }
7775 }
7776 }
7777 }
7778
7779 return stmt;
7780 }
7781
7782
7784 {
7785 ROSE_ASSERT(scope);
7786 SgFunctionDeclaration* result = NULL;
7787 if (scope->containsOnlyDeclarations())
7788 {
7789 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7790 SgDeclarationStatementPtrList::iterator i=declList.begin();
7791 while (i!=declList.end())
7792 {
7793 Sg_File_Info * fileInfo = (*i)->get_file_info();
7794
7795 if ((fileInfo->isSameFile(scope->get_file_info()))||
7796 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7797 )
7798 {
7799 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7800 if (func)
7801 {
7802 if (func->get_definingDeclaration ()==func)
7803 {
7804 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7805 result=func;
7806 break;
7807 }
7808 }
7809 }
7810 i++;
7811 }//end while
7812 } else
7813 {
7814 SgStatementPtrList stmtList = scope->getStatementList();
7815 SgStatementPtrList::iterator i=stmtList.begin();
7816 while (i!=stmtList.end())
7817 {
7818 Sg_File_Info * fileInfo = (*i)->get_file_info();
7819 if ( (fileInfo->isSameFile(scope->get_file_info()))||
7820 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7821 )
7822 {
7823 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7824 if (func)
7825 {
7826 if (func->get_definingDeclaration ()==func)
7827 {
7828 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7829 result=func;
7830 break;
7831 }// if defining
7832 } // if func
7833 }// if fileInof
7834 i++;
7835 }//while
7836 } // end if
7837 return result;
7838 }
7839
7840
7842{
7843 bool result = false;
7844 // Liao 1/5/2010, handle Fortran main entry: SgProgramHeaderStatement
7846 if (isSgProgramHeaderStatement(n)) {
7847 result = true;
7848 }
7849 }
7850 else {
7851 if (isSgFunctionDeclaration(n) != nullptr) {
7852 bool either = false;
7854 either = true;
7855 }
7856 else {
7857 const SgStatement* stmnt = isSgStatement(n);
7858 ROSE_ASSERT(stmnt != nullptr);
7859 if (isSgGlobal(stmnt->get_scope())) {
7860 either = true;
7861 }
7862 }
7863 if (either) {
7864 const SgFunctionDeclaration* funcDefn = isSgFunctionDeclaration(n);
7865 ROSE_ASSERT(funcDefn != nullptr);
7866 if (funcDefn->get_name() == "main") {
7867 result = true;
7868 }
7869 }
7870 }
7871 }
7872 return result;
7873}
7874
7875// Originally from ompTranslator.C
7876// DQ (1/6/2007): The correct qualified name for "main" is "::main", at least in C++.
7877// however for C is should be "main". Our name qualification is not language specific,
7878// however, for C is makes no sense to as for the qualified name, so the name we
7879// want to search for could be language specific. The test code test2007_07.C
7880// demonstrates that the function "main" can exist in both classes (as member functions)
7881// and in namespaces (as more meaningfully qualified names). Because of this C++
7882// would have to qualify the global main function as "::main", I think.
7883
7884// Revised by Jeremiah,
7885// Added check to see if the scope is global: Liao
7887 if (!n) return 0;
7888 if (isMain(n))
7889 {
7890 return isSgFunctionDeclaration(n);
7891 }
7892 vector<SgNode*> children = n->get_traversalSuccessorContainer();
7893 for (vector<SgNode*>::const_iterator i = children.begin();
7894 i != children.end(); ++i) {
7895
7896 SgFunctionDeclaration* mainDecl = findMain(*i);
7897 if (mainDecl)
7898 if (mainDecl->get_definingDeclaration() == mainDecl) // skip non-defining main() declaration, Liao 8/27/2010
7899 return mainDecl;
7900 }
7901 return 0;
7902}
7903
7905// another declaration statement can be inserted.
7906// This is useful to find a safe place to insert a declaration statement with special requirements about where it can be inserted.
7907// e.g. a variable declaration statement should not be inserted before IMPLICIT none in Fortran
7908// If it returns NULL, a declaration statement should be able to be prepended to the scope
7910{
7911 SgStatement* rt = NULL;
7912 ROSE_ASSERT (scope != NULL);
7913
7914 SgStatementPtrList stmt_list = scope->generateStatementList ();
7915
7916 for (size_t i = 0; i<stmt_list.size(); i++)
7917 {
7918 SgStatement* cur_stmt = stmt_list[i];
7919 // We should exclude pragma decl. We don't want to insert things after pragmas.
7920 if (isSgDeclarationStatement(cur_stmt))
7921 {
7922 if (isSgPragmaDeclaration (cur_stmt))
7923 {
7924 if (includePragma)
7925 rt = cur_stmt;
7926 }
7927 else
7928 rt = cur_stmt;
7929 }
7930 //if (isSgImplicitStatement(cur_stmt)) || isSgFortranIncludeLine(cur_stmt) || isSgDeclarationStatement
7931 }
7932
7933 return rt;
7934}
7935
7937{
7938 SgNode* rt = NULL;
7939 SgTreeCopy g_treeCopy; // should use a copy object each time of usage!
7940 if (n!= NULL)
7941 {
7942 rt = n->copy (g_treeCopy);
7944 }
7945 // return n ? n->copy (g_treeCopy) : 0;
7946 return rt;
7947}
7948
7949// by Jeremiah
7950// Return bool for C++ code, and int for C code
7952 bool isC = TransformationSupport::getSourceFile(n)->get_outputLanguage() == SgFile::e_C_language;
7953 if (isC) {
7954 return SgTypeInt::createType();
7955 } else {
7956 return SgTypeBool::createType();
7957 }
7958}
7959
7960#if 1
7961// Change continue statements in a given block of code to gotos to a label
7963 {
7964#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
7965 std::vector<SgContinueStmt*> continues = SageInterface::findContinueStmts(stmt);
7966 for (std::vector<SgContinueStmt*>::iterator i = continues.begin(); i != continues.end(); ++i)
7967 {
7968 SgGotoStatement* gotoStatement = SageBuilder::buildGotoStatement(label);
7969 // printf ("Building gotoStatement #1 = %p \n",gotoStatement);
7970#ifndef _MSC_VER
7971 LowLevelRewrite::replace(*i, make_unit_list( gotoStatement ) );
7972#else
7973 ROSE_ABORT();
7974#endif
7975 }
7976#else
7977 printf ("Not supported in mode: ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT (LowLevelRewrite::replace() is unavailable)");
7978 ROSE_ABORT();
7979#endif
7980 }
7981
7982#define DEBUG_TEMPLATE_ARG_EQUIVALENCE 0
7983
7985 {
7986 if (arg1 == arg2)
7987 {
7988#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7989 printf ("In templateArgumentEquivalence(): same pointer to template argument: returning true \n");
7990#endif
7991 return true;
7992 }
7993
7994 if (arg1->get_argumentType() != arg2->get_argumentType())
7995 {
7996#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7997 printf ("In templateArgumentEquivalence(): different argumentType(): returning false \n");
7998#endif
7999 return false;
8000 }
8001
8002 switch (arg1->get_argumentType())
8003 {
8005 {
8006 ROSE_ASSERT(arg1->get_type() != NULL);
8007 ROSE_ASSERT(arg2->get_type() != NULL);
8008
8009#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8010 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: arg1->get_type() = %p = %s arg2->get_type() = %p = %s \n",
8011 arg1->get_type(),arg1->get_type()->class_name().c_str(),
8012 arg2->get_type(),arg2->get_type()->class_name().c_str());
8013#endif
8014 // DQ (5/19/2016): Rewrote to support debugging.
8015 // return arg1->get_type() == arg2->get_type();
8016 if (arg1->get_type() == arg2->get_type())
8017 {
8018#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8019 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: returning true \n");
8020#endif
8021 return true;
8022 }
8023 else
8024 {
8025 // ROSE_ASSERT(!"NIY: non-type template argument comparaison."); /// \todo
8026
8027 // DQ (5/19/2016): Use type equivalence mechanism to handle the case where
8028 // these are different pointers to what might still be the same type.
8029 // return false;
8030 bool typesAreEqual = isEquivalentType(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: pointers are different: returning typesAreEqual = %s \n",typesAreEqual ? "true" : "false");
8034#endif
8035 return typesAreEqual;
8036 }
8037 }
8038
8040 {
8041 SgExpression * expr1 = arg1->get_expression();
8042 SgExpression * expr2 = arg2->get_expression();
8043 if (expr1 == expr2) {
8044#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8045 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: checking for the same expression: returning true \n");
8046#endif
8047 return true;
8048 } else if (expr1->variantT() == expr2->variantT() ) {
8049#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8050 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: same variant of expression: %s\n", expr1->class_name().c_str());
8051#endif
8052 switch (expr1->variantT()) {
8053 case V_SgLongIntVal: {
8054 return ((SgLongIntVal *)expr1)->get_value() == ((SgLongIntVal *)expr2)->get_value();
8055 }
8056 // DQ (7/21/2024): Adding support for another type (from processing nlohmann/json.hpp with ROSE)
8057 case V_SgUnsignedLongVal:
8058 {
8059 return ((SgUnsignedLongVal*) expr1)->get_value() == ((SgUnsignedLongVal*) expr2)->get_value();
8060 }
8061 // PP (4/10/2025): Adding support for another type (from processing ROSE with ROSE)
8062 case V_SgBoolValExp:
8063 {
8064 return static_cast<SgBoolValExp*>(expr1)->get_value() == static_cast<SgBoolValExp*>(expr2)->get_value();
8065 }
8066 default: {
8067 mlog[Sawyer::Message::Common::FATAL]
8068 << "FATAL: In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: expression have the same variant "
8069 << expr1->class_name()
8070 << " but comparison is not NIY!"
8071 << std::endl;
8072 ROSE_ABORT();
8073 }
8074 }
8075 } else {
8076#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8077 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: different variant of expression: returning false \n");
8078#endif
8079 return false;
8080 }
8081 }
8082
8084 {
8085 if (arg1->get_templateDeclaration() == arg2->get_templateDeclaration())
8086 {
8087#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8088 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::template_template_argument: checking for the same templateDeclaration: returning true \n");
8089#endif
8090 return true;
8091 }
8092 else
8093 {
8094 ROSE_ASSERT(!"NIY: template template argument comparaison.");
8095 }
8096 }
8097
8099 {
8100 ROSE_ASSERT(!"Try to compare template arguments of unknown type...");
8101 }
8102
8103 // DQ (7/19/2015): Added missing case:
8105 {
8106 // Liao 6/24/2016. Handle the simplest case: both arguments are parameter pack.
8108 return true;
8109 ROSE_ASSERT(!"Try to compare template arguments of unknown type start_of_pack_expansion_argument");
8110 }
8111
8112 // DQ (7/19/2015): Added missing default case: we always want to ahve a default case to catch errors and missing cases.
8113 default:
8114 {
8115 printf ("Error: default case not handled! \n");
8116 ROSE_ABORT();
8117 }
8118 }
8119
8120 ROSE_ABORT(); // unreachable code
8121 }
8122
8123#define DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE 0
8124
8125bool SageInterface::templateArgumentListEquivalence(const SgTemplateArgumentPtrList & list1, const SgTemplateArgumentPtrList & list2)
8126 {
8127 if (list1.size() != list2.size())
8128 {
8129#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8130 printf ("In templateArgumentListEquivalence(): different list sizes: returning false \n");
8131 printf (" --- list1.size() = %zu \n",list1.size());
8132 printf (" --- list2.size() = %zu \n",list2.size());
8133#endif
8134 return false;
8135 }
8136
8137 if (list1 == list2)
8138 {
8139#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8140 printf ("In templateArgumentListEquivalence(): same list using STL equality operator: returning true \n");
8141#endif
8142 return true;
8143 }
8144
8145 // for (unsigned i = 0; i < list1.size(); i++)
8146 for (size_t i = 0; i < list1.size(); i++)
8147 {
8148#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8149 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu \n",i);
8150#endif
8151 // if (!templateArgumentEquivalence(list1[i], list2[i]))
8152 if (templateArgumentEquivalence(list1[i], list2[i]) == false)
8153 {
8154#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8155 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu --- returned false: returning false \n",i);
8156#endif
8157 return false;
8158 }
8159 }
8160
8161#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8162 printf ("In templateArgumentListEquivalence(): reached base of function: returning true \n");
8163#endif
8164
8165 return true;
8166 }
8167
8168// Add a step statement to the end of a loop body
8169// Add a new label to the end of the loop, with the step statement after
8170// it; then change all continue statements in the old loop body into
8171// jumps to the label
8172//
8173// For example:
8174// while (a < 5) {if (a < -3) continue;} (adding "a++" to end) becomes
8175// while (a < 5) {if (a < -3) goto label; label: a++;}
8177 using namespace SageBuilder;
8179 SgStatement* old_body = SageInterface::getLoopBody(loopStmt);
8180 SgBasicBlock* new_body = buildBasicBlock();
8181// printf ("Building IR node #13: new SgBasicBlock = %p \n",new_body);
8182 SgName labelname = "rose_label__";
8183 labelname << ++gensym_counter;
8184 SgLabelStatement* labelstmt = buildLabelStatement(labelname,
8185buildBasicBlock(), proc);
8186 changeContinuesToGotos(old_body, labelstmt);
8187 appendStatement(old_body, new_body);
8188 appendStatement(labelstmt, new_body);
8189 appendStatement(step, new_body);
8190 SageInterface::setLoopBody(loopStmt, new_body);
8191}
8192
8193
8195 if (isSgNullExpression(f->get_increment())) return;
8196 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(f->get_increment());
8197 f->get_increment()->set_parent(incrStmt);
8200 f->set_increment(ne);
8201 ne->set_parent(f);
8202}
8203
8204static
8205bool hasEmptyCondition(SgForStatement* f)
8206{
8207 ROSE_ASSERT(f);
8208
8209 SgStatement* condstmt = f->get_test();
8210 ROSE_ASSERT(condstmt);
8211
8212 if (isSgNullStatement(condstmt)) return true;
8213
8214 SgExprStatement* exprStmt = isSgExprStatement(condstmt);
8215
8216 return isSgNullExpression(exprStmt->get_expression());
8217}
8218
8223 SgStatementPtrList& bbStmts = bb->get_statements();
8224 SgStatementPtrList& initStmts = inits->get_init_stmt();
8225 bbStmts = initStmts;
8226 for (size_t i = 0; i < bbStmts.size(); ++i) {
8227 bbStmts[i]->set_parent(bb);
8228 }
8229
8230 const bool testIsNull = hasEmptyCondition(f);
8232 : f->get_test();
8234
8235 appendStatement(ws, bb);
8236 isSgStatement(f->get_parent())->replace_statement(f, bb);
8237}
8238
8240 Rose_STL_Container<SgNode*> fors = NodeQuery::querySubTree(top,
8241V_SgForStatement);
8242 for (size_t i = 0; i < fors.size(); ++i) {
8243 convertForToWhile(isSgForStatement(fors[i]));
8244 }
8245}
8246
8247 vector<SgGotoStatement*> SageInterface::findGotoStmts(SgStatement* scope, SgLabelStatement* l) {
8248 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8249 // But we still need the copy since the return type is IR node specific.
8250 Rose_STL_Container<SgNode*> allGotos = NodeQuery::querySubTree(scope, V_SgGotoStatement);
8251
8252 vector<SgGotoStatement*> result;
8253 for (Rose_STL_Container<SgNode*>::const_iterator i = allGotos.begin(); i != allGotos.end(); ++i) {
8254 if (isSgGotoStatement(*i)->get_label() == l) {
8255 result.push_back(isSgGotoStatement(*i));
8256 }
8257 }
8258 return result;
8259 }
8260
8261#if 0 // Liao 5/21/2010. This is a bad function in terms of performance
8262 // vectors are created/destroyed multiple times
8263 vector<SgReturnStmt*> SageInterface::findReturnStmts(SgStatement* scope) {
8264 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8265 // But we still need the copy since the return type is IR node specific.
8266 Rose_STL_Container<SgNode*> returns = NodeQuery::querySubTree(scope, V_SgReturnStmt);
8267
8268 vector<SgReturnStmt*> result;
8269 for (Rose_STL_Container<SgNode*>::const_iterator i = returns.begin(); i != returns.end(); ++i) {
8270 result.push_back(isSgReturnStmt(*i));
8271 }
8272 return result;
8273 }
8274
8275#endif
8276static void getSwitchCasesHelper(SgStatement* top, vector<SgStatement*>& result) {
8277 ROSE_ASSERT (top);
8278 if (isSgSwitchStatement(top)) return; // Don't descend into nested switches
8279 if (isSgCaseOptionStmt(top) || isSgDefaultOptionStmt(top)) {
8280 result.push_back(top);
8281 }
8282 vector<SgNode*> children = top->get_traversalSuccessorContainer();
8283 for (unsigned int i = 0; i < children.size(); ++i) {
8284 if (isSgStatement(children[i])) {
8285 getSwitchCasesHelper(isSgStatement(children[i]), result);
8286 }
8287 }
8288 }
8289
8291 vector<SgStatement*> result;
8292 getSwitchCasesHelper(sw->get_body(), result);
8293 return result;
8294 }
8295
8296
8297#endif
8298
8305SgScopeStatement* SageInterface::getEnclosingScope(SgNode* n, const bool includingSelf/* =false*/)
8306{
8307 SgScopeStatement* result = getScope (n);
8308 if (result == n)
8309 {
8310 if (!includingSelf)
8311 result = getScope(n->get_parent());
8312 }
8313 return result;
8314}
8315
8316// from transformationSupport.C
8319 {
8320
8321 // Case 1: directly call get_scope() for some types of nodes
8322 if (const SgSymbol* symbol = isSgSymbol(astNode))
8323 return symbol->get_scope();
8324 else if (const SgInitializedName* initName = isSgInitializedName(astNode))
8325 return initName->get_scope();
8326 else if (const SgTemplateArgument* tempArg = isSgTemplateArgument(astNode))
8327 return tempArg->get_scope();
8328 else if (const SgQualifiedName* qualifiedName = isSgQualifiedName(astNode))
8329 return qualifiedName->get_scope();
8330
8331 // DQ (6/9/2007): This function traverses through the parents to the first scope (used for name qualification support of template arguments)
8332 const SgNode* parentNode = astNode;
8333 while (!isSgScopeStatement(parentNode))
8334 {
8335 //George Vulov (11/29/2010)
8336 //Function parameter lists are siblings of SgFunctionDefinition, so just going up to parents
8337 //produces SgGlobal.
8338 if (isSgFunctionParameterList(parentNode) || isSgCtorInitializerList(parentNode))
8339 {
8340 const SgFunctionDeclaration* funcDeclaration = isSgFunctionDeclaration(parentNode->get_parent());
8341 ROSE_ASSERT(funcDeclaration != NULL);
8342 funcDeclaration = isSgFunctionDeclaration(funcDeclaration->get_definingDeclaration());
8343 if (funcDeclaration != NULL)
8344 {
8345 return funcDeclaration->get_definition();
8346 }
8347 }
8348
8349 parentNode = parentNode->get_parent();
8350 if (parentNode == NULL)
8351 {
8352 break;
8353 }
8354 }
8355
8356 // Check to see if we made it back to the root (current root is SgProject).
8357 // It is also OK to stop at a node for which get_parent() returns NULL (SgType and SgSymbol nodes).
8358 if ( isSgScopeStatement(parentNode) == NULL &&
8359 dynamic_cast<const SgType*>(parentNode) == NULL &&
8360 dynamic_cast<const SgSymbol*>(parentNode) == NULL )
8361 {
8362 printf ("Error: In SageInterface::getScope(): could not trace back to SgScopeStatement node \n");
8363 ROSE_ABORT();
8364 }
8365 else
8366 {
8367 if ( dynamic_cast<const SgType*>(parentNode) != NULL || dynamic_cast<const SgSymbol*>(parentNode) != NULL )
8368 {
8369 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());
8370 return NULL;
8371 }
8372 }
8373
8374 // Make sure we have a SgStatement node
8375 const SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8376 //SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8377 ROSE_ASSERT (scopeStatement != NULL);
8378
8379 // ensure the search is inclusive
8380 if (isSgScopeStatement(astNode))
8381 if (isSgScopeStatement(parentNode))
8382 {
8383 ROSE_ASSERT (astNode == parentNode);
8384 }
8385
8386 // return scopeStatement;
8387 return const_cast<SgScopeStatement*>(scopeStatement);
8388 }
8389
8390
8391// from outliner, ASTtools
8392// ------------------------------------------------
8393
8401static
8402const SgVariableSymbol *
8403getVarSymFromName_const (const SgInitializedName* name)
8404 {
8405 SgVariableSymbol* v_sym = NULL;
8406
8407 if (name != NULL)
8408 {
8409#if 0
8410 printf ("In getVarSymFromName(): name->get_name() = %s \n",name->get_name().str());
8411#endif
8412 SgScopeStatement* scope = name->get_scope();
8413 ROSE_ASSERT (scope != NULL);
8414#if 0
8415 printf ("In getVarSymFromName(): name->get_name() = %s scope = %p = %s \n",name->get_name().str(),scope,scope->class_name().c_str());
8416#endif
8417 v_sym = scope->lookup_var_symbol (name->get_name());
8418
8419 if (!v_sym) // E.g., might be part of an 'extern' declaration.
8420 {
8421 // Try the declaration's scope.
8422 SgDeclarationStatement* decl = name->get_declaration ();
8423 ROSE_ASSERT (decl);
8424
8425 SgScopeStatement* decl_scope = decl->get_scope ();
8426 if (decl_scope != NULL)
8427 v_sym = decl_scope->lookup_var_symbol (name->get_name());
8428
8429 if (!v_sym)
8430 cerr << "\t\t*** WARNING: Can't seem to find a symbol for '"
8431 << name->get_name ().str ()
8432 << "' ***" << endl;
8433 }
8434 }
8435
8436 return v_sym;
8437 }
8438
8439#if 0
8447static
8449getVarSymFromName (SgInitializedName* name)
8450{
8451 const SgVariableSymbol* v_sym = getVarSymFromName_const (name);
8452 return const_cast<SgVariableSymbol *> (v_sym);
8453}
8454#endif
8459static
8460const SgVariableSymbol *
8461getVarSym_const (const SgNode* n)
8462{
8463 const SgVariableSymbol* v_sym = 0;
8464 switch (n->variantT ())
8465 {
8466 case V_SgVarRefExp:
8467 v_sym = isSgVarRefExp (n)->get_symbol ();
8468 break;
8469 case V_SgInitializedName:
8470 v_sym = getVarSymFromName_const (isSgInitializedName (n));
8471 break;
8472 default:
8473 break;
8474 }
8475 return v_sym;
8476}
8477
8478#if 0
8483static
8485getVarSym (SgNode* n)
8486{
8487 const SgVariableSymbol* v_sym = getVarSym_const (n);
8488 return const_cast<SgVariableSymbol *> (v_sym);
8489}
8490#endif
8491
8492static
8493const SgVariableSymbol *
8494getFirstVarSym_const (const SgVariableDeclaration* decl)
8495{
8496 if (!decl) return 0;
8497 const SgInitializedNamePtrList& names = decl->get_variables ();
8498 if (names.begin () != names.end ())
8499 {
8500 const SgInitializedName* name = *(names.begin ());
8501 return getVarSym_const (name);
8502 }
8503 else
8504 return 0;
8505}
8506
8509{
8510 const SgVariableSymbol* sym = getFirstVarSym_const (decl);
8511 return const_cast<SgVariableSymbol *> (sym);
8512}
8513
8514
8517{
8518 ROSE_ASSERT(decl);
8519 SgInitializedNamePtrList& names = decl->get_variables ();
8520 if (names.begin () != names.end ())
8521 return *(names.begin ());
8522 else
8523 return NULL;
8524}
8525
8526
8527static void findBreakStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgBreakStmt*>& breakStmts) {
8528 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code) || isSgSwitchStatement(code)) {
8529 if (fortranLabel == "") {
8530 // Outermost loop only
8531 return;
8532 } else {
8533 // Set this for query on children
8534 inOutermostBody = false;
8535 }
8536 }
8537 if (isSgBreakStmt(code)) {
8538 SgBreakStmt* bs = isSgBreakStmt(code);
8539 bool breakMatchesThisConstruct = false;
8540 if (bs->get_do_string_label() == "") {
8541 // Break matches closest construct
8542 breakMatchesThisConstruct = inOutermostBody;
8543 } else {
8544 breakMatchesThisConstruct = (fortranLabel == bs->get_do_string_label());
8545 }
8546 if (breakMatchesThisConstruct) {
8547 breakStmts.push_back(bs);
8548 }
8549 return;
8550 }
8551 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8552 for (unsigned int i = 0; i < children.size(); ++i) {
8553 if (isSgStatement(children[i])) {
8554 findBreakStmtsHelper(isSgStatement(children[i]), fortranLabel, inOutermostBody, breakStmts);
8555 }
8556 }
8557}
8558
8559vector<SgBreakStmt*> SageInterface::findBreakStmts(SgStatement* code, const std::string& fortranLabel) {
8560 // Run this on the body of a loop or switch, because it stops at any
8561 // construct which defines a new scope for break statements
8562 vector<SgBreakStmt*> result;
8563 findBreakStmtsHelper(code, fortranLabel, true, result);
8564 return result;
8565}
8566
8567
8568static void findContinueStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgContinueStmt*>& continueStmts) {
8569 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code)) {
8570 if (fortranLabel == "") {
8571 // Outermost loop only
8572 return;
8573 } else {
8574 // Set this for query on children
8575 inOutermostBody = false;
8576 }
8577 }
8578 if (isSgContinueStmt(code)) {
8579 SgContinueStmt* cs = isSgContinueStmt(code);
8580 bool continueMatchesThisConstruct = false;
8581 if (cs->get_do_string_label() == "") {
8582 // Continue matches closest construct
8583 continueMatchesThisConstruct = inOutermostBody;
8584 } else {
8585 continueMatchesThisConstruct = (fortranLabel == cs->get_do_string_label());
8586 }
8587 if (continueMatchesThisConstruct) {
8588 continueStmts.push_back(cs);
8589 }
8590 return;
8591 }
8592 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8593 for (unsigned int i = 0; i < children.size(); ++i) {
8594 SgStatement* stmnt = isSgStatement(children[i]);
8595 if (stmnt != NULL) {
8596 findContinueStmtsHelper(stmnt, fortranLabel, inOutermostBody, continueStmts);
8597 }
8598 }
8599}
8600
8601vector<SgContinueStmt*> SageInterface::findContinueStmts(SgStatement* code, const std::string& fortranLabel) {
8602 // Run this on the body of a loop, because it stops at any construct which
8603 // defines a new scope for continue statements
8604 vector<SgContinueStmt*> result;
8605 findContinueStmtsHelper(code, fortranLabel, true, result);
8606 return result;
8607}
8608
8609
8610// Get the initializer containing an expression if it is within an
8611// initializer.
8612// from replaceExpressionWithStatement.C
8614 assert(n);
8615#if 0
8616 std::cout << "Starting getInitializerOfExpression on 0x" << std::hex << (int)n << ", which has type " << n->sage_class_name() << std::endl;
8617#endif
8618 while (!isSgInitializer(n)) {
8619 n = isSgExpression(n->get_parent());
8620#if 0
8621 std::cout << "Continuing getInitializerOfExpression on 0x" << std::hex << (int)n;
8622 if (n) std::cout << ", which has type " << n->sage_class_name();
8623 std::cout << std::endl;
8624#endif
8625 assert(n);
8626 }
8627 return isSgInitializer(n);
8628}
8629
8630#ifndef USE_ROSE
8631// Get all symbols used in a given expression
8633 class GetSymbolsUsedInExpressionVisitor: public AstSimpleProcessing {
8634 public:
8635 std::vector<SgVariableSymbol*> symbols;
8636
8637 virtual void visit(SgNode* n) {
8638 if (isSgVarRefExp(n))
8639 symbols.push_back(isSgVarRefExp(n)->get_symbol());
8640 }
8641 };
8642
8643 GetSymbolsUsedInExpressionVisitor vis;
8644 vis.traverse(expr, preorder);
8645 return vis.symbols;
8646}
8647#endif
8648
8651 return getEnclosingNode<SgSourceFile>(n, includingSelf);
8652}
8653
8654
8656{
8657 return findDeclarationStatement<SgFunctionDeclaration> (root, name, scope, isDefining);
8658}
8659
8660
8662{
8663 return getEnclosingFunctionDefinition(n,includingSelf);
8664}
8665
8668 return getEnclosingNode<SgFunctionDefinition>(n, includingSelf);
8669}
8670
8671
8674 return getEnclosingNode<SgFunctionDeclaration>(astNode, includingSelf);
8675}
8676
8677// #endif
8678
8679// #ifndef USE_ROSE
8680
8681SgGlobal*
8683 // should including itself in this case
8684 return getEnclosingNode<SgGlobal>(astNode, true /*includingSelf*/);
8685}
8686
8688SageInterface::getEnclosingClassDefinition(SgNode* astNode, const bool includingSelf/* =false*/) {
8689 return getEnclosingNode<SgClassDefinition>(astNode, includingSelf);
8690}
8691
8692
8695 // DQ (1/24/2019): This might have to get the SgClassDefinition and then the SgClassDeclaration from that.
8696 // I'm having trouble making this work for a member function declared outside of the class definition.
8697 return getEnclosingNode<SgClassDeclaration>(astNode, true);
8698}
8699
8701SageInterface::getEnclosingExprListExp(SgNode* astNode, const bool includingSelf/* =false*/) {
8702 return getEnclosingNode<SgExprListExp>(astNode, includingSelf);
8703}
8704
8705bool
8707 {
8708 bool returnValue = false;
8709
8710 struct Visitor: public AstSimpleProcessing
8711 {
8712 SgExpression* expression_target;
8713 bool in_subtree;
8714 virtual void visit(SgNode* n)
8715 {
8716 if (n == expression_target)
8717 {
8718 in_subtree = true;
8719 }
8720 }
8721
8722 Visitor(SgExpression* expr) : expression_target(expr), in_subtree(false) {}
8723 };
8724
8725 Visitor traversal(exp);
8726
8727 traversal.traverse(subtree, preorder);
8728
8729 returnValue = traversal.in_subtree;
8730
8731 return returnValue;
8732 }
8733
8734
8737 {
8738 // DQ (2/7/2019): Added more general function to support extraction of the associated function declaration.
8739 // The lower level functions are more robust on the SgFunctionRefExp and SgMemberFunctionRefExp than
8740 // when called on the SgFunctionCallExp for example.
8741
8742 // SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
8743 ROSE_ASSERT (functionCallExp != NULL);
8744
8745 SgExpression* expression = functionCallExp->get_function();
8746 ROSE_ASSERT (expression != NULL);
8747
8748 SgFunctionDeclaration* returnDeclaration = NULL;
8749
8750 SgDotExp* dotExp = isSgDotExp(expression);
8751 if (dotExp != NULL)
8752 {
8753 ROSE_ASSERT (dotExp != NULL);
8754
8755 SgExpression* rhsOperand = dotExp->get_rhs_operand();
8756 ROSE_ASSERT (rhsOperand != NULL);
8757
8758 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8759
8760 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8761 if (memberFunctionRefExp != NULL)
8762 {
8763 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8764 }
8765 }
8766
8767 SgFunctionRefExp* functionReferenceExp = isSgFunctionRefExp(expression);
8768 if (functionReferenceExp != NULL)
8769 {
8770 returnDeclaration = functionReferenceExp->getAssociatedFunctionDeclaration();
8771 }
8772
8773 SgArrowExp* arrowExp = isSgArrowExp(expression);
8774 if ( arrowExp != NULL)
8775 {
8776 ROSE_ASSERT (arrowExp != NULL);
8777
8778 SgExpression* rhsOperand = arrowExp->get_rhs_operand();
8779 ROSE_ASSERT (rhsOperand != NULL);
8780
8781 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8782
8783 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8784 if (memberFunctionRefExp != NULL)
8785 {
8786 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8787 }
8788 }
8789
8790 return returnDeclaration;
8791 }
8792
8793
8794
8795std::list<SgClassType*>
8797 {
8798 // DQ (2/16/2019): This version support for data member name qualification return type chains.
8799
8800#define DEBUG_DATA_MEMBER_TYPE_CHAIN 0
8801
8802 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
8803 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
8804 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
8805
8806 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
8807
8808 std::list<SgClassType*> returnTypeChain;
8809
8810 // Internal list used to filter the class chain generated from chained SgCastExp objects to identify the subset containing an ambiguity.
8811 std::list<SgClassType*> classChain;
8812
8813 // Make sure this is at least a reference to a data or member function member.
8814 // The requirements for these functions are different, however, if they were
8815 // virtual functions it might be a more attractive design.
8816 if (varRefExp != NULL)
8817 {
8818 ROSE_ASSERT(isDataMemberReference(varRefExp) == true);
8819 }
8820 else
8821 {
8822 ROSE_ASSERT(memberFunctionRefExp != NULL);
8823 ROSE_ASSERT(isMemberFunctionMemberReference(memberFunctionRefExp) == true);
8824 }
8825
8826 SgNode* parent = refExp->get_parent();
8827 ROSE_ASSERT(parent != NULL);
8828
8829#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8830 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): parent = %p = %s \n",parent,parent->class_name().c_str());
8831#endif
8832
8833 SgArrowExp* arrowExp = isSgArrowExp(parent);
8834 SgDotExp* dotExp = isSgDotExp(parent);
8835
8836 SgBinaryOp* binaryOperator = NULL;
8837
8838 if (arrowExp != NULL)
8839 {
8840#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8841 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an arrow expression \n");
8842#endif
8843 binaryOperator = arrowExp;
8844 }
8845
8846 if (dotExp != NULL)
8847 {
8848#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8849 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an dot expression \n");
8850#endif
8851 binaryOperator = dotExp;
8852 }
8853
8854 // ROSE_ASSERT(binaryOperator != NULL);
8855 if (binaryOperator != NULL)
8856 {
8857 SgExpression* lhs = binaryOperator->get_lhs_operand();
8858 ROSE_ASSERT(lhs != NULL);
8859
8860#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8861 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs = %p = %s \n",lhs,lhs->class_name().c_str());
8862#endif
8863
8864 // Looking for a chain of SgCastExp expressions.
8865 SgExpression* temp_lhs = lhs;
8866 SgCastExp* cast = NULL;
8867 while (isSgCastExp(temp_lhs) != NULL)
8868 {
8869 cast = isSgCastExp(temp_lhs);
8870 ROSE_ASSERT(cast != NULL);
8871 temp_lhs = cast->get_operand();
8872
8873#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8874 printf ("Top of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8875#endif
8876 ROSE_ASSERT(cast->get_type() != NULL);
8877 SgClassType* classType = isSgClassType(cast->get_type());
8878 if (classType == NULL)
8879 {
8880#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8881 printf (" --- looking for base type: In SageInterface::getClassTypeChainForDataMemberReference(): classType == NULL: cast->get_type() = %p = %s \n",
8882 cast->get_type(),cast->get_type()->class_name().c_str());
8883#endif
8884 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);
8885 ROSE_ASSERT(baseType != NULL);
8886
8887#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8888 printf (" --- baseType = %p = %s name = %s \n",baseType,baseType->class_name().c_str(),get_name(baseType).c_str());
8889#endif
8890 classType = isSgClassType(baseType);
8891 }
8892 // ROSE_ASSERT(classType != NULL);
8893
8894 ROSE_ASSERT(temp_lhs != NULL);
8895
8896#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8897 printf (" --- temp_lhs = %p = %s name = %s \n",temp_lhs,temp_lhs->class_name().c_str(),get_name(temp_lhs).c_str());
8898#endif
8899
8900#if 1
8901 // DQ (1/20/2020): This (original) code works fine.
8902 // returnTypeChain.push_front(classType);
8903 if (classType != NULL)
8904 {
8905 classChain.push_front(classType);
8906 }
8907#else
8908 // DQ (1/20/2020): This (new) code works for Cxx11_tests/test2020_61.C.
8909 if (classType != NULL)
8910 {
8911 // DQ (1/20/2020): We might want to fully resolve the class types associated with this cast here directly
8912 // (see Cxx11_tests/test2020_61.C). The point is that we need a qualified name that will reflect all of
8913 // the class declarations from the temp_lhs to the declarations associated with the classType.
8914 // The steps are:
8915 // 1) Get the target class definition for the type represented by the temp_lhs.
8916 // 2) Get the source class definition for the classType.
8917 // 3) Iterate from the source class definition to the target class definition, and save the associated
8918 // types associated with the class declarations associated with the scopes visited.
8919 SgType* target_type = temp_lhs->get_type();
8920 ROSE_ASSERT(target_type != NULL);
8921 SgClassType* target_classType = isSgClassType(target_type);
8922 // ROSE_ASSERT(target_classType != NULL);
8923 if (target_classType != NULL)
8924 {
8925 SgDeclarationStatement* target_declaration = target_classType->get_declaration();
8926 ROSE_ASSERT(target_declaration != NULL);
8927 SgClassDeclaration* target_classDeclaration = isSgClassDeclaration(target_declaration);
8928 ROSE_ASSERT(target_classDeclaration != NULL);
8929 SgClassDeclaration* target_definingClassDeclaration = isSgClassDeclaration(target_classDeclaration->get_definingDeclaration());
8930 ROSE_ASSERT(target_definingClassDeclaration != NULL);
8931 SgScopeStatement* target_scope = target_definingClassDeclaration->get_definition();
8932 ROSE_ASSERT(target_scope != NULL);
8933
8934#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8935 printf ("target_classDeclaration = %p = %s name = %s target_scope = %p = %s \n",
8936 target_classDeclaration,target_classDeclaration->class_name().c_str(),target_classDeclaration->get_name().str(),target_scope,target_scope->class_name().c_str());
8937#endif
8938 SgClassType* source_classType = classType;
8939 ROSE_ASSERT(source_classType != NULL);
8940 SgDeclarationStatement* source_declaration = source_classType->get_declaration();
8941 ROSE_ASSERT(source_declaration != NULL);
8942 SgClassDeclaration* source_classDeclaration = isSgClassDeclaration(source_declaration);
8943 ROSE_ASSERT(source_classDeclaration != NULL);
8944 SgClassDeclaration* source_definingClassDeclaration = isSgClassDeclaration(source_classDeclaration->get_definingDeclaration());
8945 ROSE_ASSERT(source_definingClassDeclaration != NULL);
8946 SgScopeStatement* source_scope = source_definingClassDeclaration->get_definition();
8947 ROSE_ASSERT(source_scope != NULL);
8948
8949#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8950 printf ("source_classDeclaration = %p = %s name = %s source_scope = %p = %s \n",
8951 source_classDeclaration,source_classDeclaration->class_name().c_str(),source_classDeclaration->get_name().str(),source_scope,source_scope->class_name().c_str());
8952#endif
8953 SgScopeStatement* tmp_scope = source_scope;
8954 while (tmp_scope != NULL && tmp_scope != target_scope)
8955 {
8956#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8957 printf ("tmp_scope = %p = %s \n",tmp_scope,tmp_scope->class_name().c_str());
8958#endif
8959 SgClassDefinition* tmp_classDefinition = isSgClassDefinition(tmp_scope);
8960 ROSE_ASSERT(tmp_classDefinition != NULL);
8961 SgClassDeclaration* tmp_classDeclaration = tmp_classDefinition->get_declaration();
8962 ROSE_ASSERT(tmp_classDeclaration != NULL);
8963
8964#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8965 SgName scope_name = tmp_classDeclaration->get_name();
8966 printf ("scope_name = %s \n",scope_name.str());
8967#endif
8968 SgClassType* tmp_classType = tmp_classDeclaration->get_type();
8969 ROSE_ASSERT(tmp_classType != NULL);
8970
8971 // classChain.push_front(tmp_classDefinition);
8972 classChain.push_front(tmp_classType);
8973
8974 tmp_scope = tmp_scope->get_scope();
8975
8976 if (isSgGlobal(tmp_scope) != NULL)
8977 {
8978 tmp_scope = NULL;
8979 }
8980 }
8981 }
8982 else
8983 {
8984#if 1
8985 printf ("In loop processing cast: target_type = %p = %s \n",target_type,target_type->class_name().c_str());
8986#endif
8987 }
8988 }
8989#endif
8990
8991#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8992 printf ("Bottom of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8993#endif
8994 }
8995
8996 // 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.
8997
8998 ROSE_ASSERT(temp_lhs != NULL);
8999
9000#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9001 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
9002#endif
9003
9004 SgVarRefExp* derivedClassVarRefExp = isSgVarRefExp(temp_lhs);
9005 if (derivedClassVarRefExp != NULL)
9006 {
9007 SgVariableSymbol* derivedClassVariableSymbol = derivedClassVarRefExp->get_symbol();
9008 ROSE_ASSERT(derivedClassVariableSymbol != NULL);
9009
9010 SgName derivedClassVariableName = derivedClassVariableSymbol->get_name();
9011
9012#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9013 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): derivedClassVariableName = %s \n",derivedClassVariableName.str());
9014#endif
9015 // SgType* type = cast->get_type();
9016 SgType* type = temp_lhs->get_type();
9017 ROSE_ASSERT(type != NULL);
9018
9019#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9020 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s \n",type,type->class_name().c_str());
9021#endif
9022
9023 // 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);
9024 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);
9025
9026#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9027 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type = %p = %s \n",stripped_type,stripped_type->class_name().c_str());
9028#endif
9029
9030 // SgClassType* classType = isSgClassType(type);
9031 SgClassType* classType = isSgClassType(stripped_type);
9032
9033 // ROSE_ASSERT(classType != NULL);
9034 if (classType != NULL)
9035 {
9036#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9037 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classType = %p = %s \n",classType,classType->class_name().c_str());
9038 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
9039 ROSE_ASSERT(classDeclaration != NULL);
9040 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classDeclaration = %p = %s name = %s \n",
9041 classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9042#endif
9043 // This is where we want the SgVarRefExp data member qualification to start.
9044 // returnType = classType;
9045 // returnTypeChain.push_front(classType);
9046 classChain.push_front(classType);
9047 }
9048 else
9049 {
9050#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9051 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type is not a SgClassType \n");
9052#endif
9053 }
9054 }
9055 else
9056 {
9057#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9058 printf ("Need to support alternative to SgVarRefExp: temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
9059#endif
9060 SgType* type = temp_lhs->get_type();
9061 ROSE_ASSERT(type != NULL);
9062
9063#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9064 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s name = %s \n",type,type->class_name().c_str(),get_name(type).c_str());
9065#endif
9066
9067 // DQ (1/3/2019): Need to strip the type to get to a possible SgClassType.
9068 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);
9069
9070#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9071 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());
9072#endif
9073 // SgClassType* classType = isSgClassType(type);
9074 SgClassType* classType = isSgClassType(stripped_type);
9075 // returnTypeChain.push_front(classType);
9076 if (classType != NULL)
9077 {
9078 classChain.push_front(classType);
9079 }
9080 }
9081
9082#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9083 printf ("classChain.size() = %zu \n",classChain.size());
9084 std::list<SgClassType*>::iterator iter = classChain.begin();
9085 while(iter != classChain.end())
9086 {
9087 printf (" --- *iter = %p = %s name = %s \n",*iter,(*iter)->class_name().c_str(),(*iter)->get_name().str());
9088
9089 iter++;
9090 }
9091#endif
9092
9093 // Test the first element in the list to see if there is an ambiguity in the associated classDefinition
9094 // for the input variable referenced SgVarRefExp).
9095
9096 // SgVariableSymbol* variableSymbol = varRefExp->get_symbol();
9097 // ROSE_ASSERT(variableSymbol != NULL);
9098 // SgName variableName = variableSymbol->get_name();
9099 SgSymbol* referenceSymbol = NULL;
9100 if (varRefExp != NULL)
9101 {
9102 ROSE_ASSERT(varRefExp != NULL);
9103 ROSE_ASSERT(memberFunctionRefExp == NULL);
9104
9105 referenceSymbol = varRefExp->get_symbol();
9106 }
9107 else
9108 {
9109 ROSE_ASSERT(varRefExp == NULL);
9110 ROSE_ASSERT(memberFunctionRefExp != NULL);
9111
9112 referenceSymbol = memberFunctionRefExp->get_symbol();
9113 }
9114 ROSE_ASSERT(referenceSymbol != NULL);
9115 SgName symbolName = referenceSymbol->get_name();
9116
9117#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9118 printf ("referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9119 printf ("symbolName = %s \n",symbolName.str());
9120#endif
9121
9122 // Generate the name without the template arguments.
9123 SgFunctionSymbol* functionSymbol = isSgFunctionSymbol(referenceSymbol);
9124 if (functionSymbol != NULL)
9125 {
9126 // 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.
9127 // SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(referenceSymbol->get_declaration());
9128 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(functionSymbol->get_declaration());
9129 if (templateInstantiationMemberFunctionDeclaration != NULL)
9130 {
9131#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9132 printf ("This is a template name, we want the name without template arguments \n");
9133 printf ("templateInstantiationMemberFunctionDeclaration = %p \n",templateInstantiationMemberFunctionDeclaration);
9134 printf ("templateInstantiationMemberFunctionDeclaration->get_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_name().str());
9135#endif
9136
9137 // DQ (2/24/2019): This is an error (calls base class function).
9138 // printf ("templateInstantiationMemberFunctionDeclaration->get_template_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_template_name().str());
9139
9140 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration =
9141 isSgTemplateMemberFunctionDeclaration(templateInstantiationMemberFunctionDeclaration->get_templateDeclaration());
9142 if (templateMemberFunctionDeclaration != NULL)
9143 {
9144#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9145 printf ("templateMemberFunctionDeclaration = %p \n",templateMemberFunctionDeclaration);
9146 printf ("templateMemberFunctionDeclaration->get_name() = %s \n",templateMemberFunctionDeclaration->get_name().str());
9147#endif
9148 // We need the template name without template arguments.
9149 symbolName = templateMemberFunctionDeclaration->get_name();
9150 }
9151 else
9152 {
9153#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9154 printf ("templateMemberFunctionDeclaration == NULL: template declaration not available from template instantiation (rare, I think) \n");
9155#endif
9156 }
9157#if 0
9158 printf ("Exiting as a test! \n");
9159 ROSE_ABORT();
9160#endif
9161 }
9162 else
9163 {
9164 // DQ (2/24/2019): This might indicate another case to handle: finding SgMemberFunctionDeclaration (but this is not a template).
9165 SgDeclarationStatement* declarationStatement = functionSymbol->get_declaration();
9166 ROSE_ASSERT(declarationStatement != NULL);
9167#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9168 printf ("functionSymbol != NULL: but declaration is not a member function: declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
9169#endif
9170 }
9171 }
9172 else
9173 {
9174 SgVariableSymbol* variableSymbol = isSgVariableSymbol(referenceSymbol);
9175 if (variableSymbol != NULL)
9176 {
9177 // Nothing to do in this case of a SgVariableSymbol.
9178 }
9179 else
9180 {
9181#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9182 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): NOTE: referenceSymbol is not a SgFunctionSymbol or SgVariableSymbol \n");
9183#endif
9184#if 1
9185 printf ("Exiting as a test! \n");
9186 ROSE_ABORT();
9187#endif
9188 }
9189
9190 }
9191
9192#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9193 printf ("symbolName = %s \n",symbolName.str());
9194#endif
9195
9196 // SgClassType* firstDetectedAmbiguity = NULL;
9197 // SgClassType* lastDetectedAmbiguity = NULL;
9198
9199 // bool nameQualificationRequired = false;
9200
9201 // std::list<SgClassType*> deleteList;
9202 std::list<SgClassType*> saveList;
9203
9204#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9205 printf ("classChain.size() = %zu \n",classChain.size());
9206#endif
9207
9208 std::list<SgClassType*>::iterator i = classChain.begin();
9209 std::list<SgClassType*>::iterator save_iter = i;
9210
9211 // 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.
9212 save_iter++;
9213
9214 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9215 bool ambiguityDetectedSoSaveWholeChain = false;
9216
9217 while(i != classChain.end())
9218 {
9219#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9220 printf ("******** TOP OF WHILE LOOP ******** \n");
9221 printf (" --- *i = %p = %s name = %s \n",*i,(*i)->class_name().c_str(),(*i)->get_name().str());
9222 printf (" --- --- referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9223#endif
9224 bool ambiguityDetected = false;
9225
9226 SgDeclarationStatement* declarationStatement = (*i)->get_declaration();
9227 ROSE_ASSERT(declarationStatement != NULL);
9228 SgDeclarationStatement* definingDeclarationStatement = declarationStatement->get_definingDeclaration();
9229 if (definingDeclarationStatement != NULL)
9230 {
9231 SgClassDeclaration* classDeclaration = isSgClassDeclaration(definingDeclarationStatement);
9232 ROSE_ASSERT(classDeclaration != NULL);
9233 SgClassDefinition* classDefinition = classDeclaration->get_definition();
9234
9235#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9236 printf (" --- classDeclaration = %p = %s name = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9237 printf (" --- classDefinition = %p = %s \n",classDefinition,classDefinition->class_name().c_str());
9238#endif
9239 // This works for any SgName and SgSymbol, so it need not be specific to variables.
9240 ambiguityDetected = classDefinition->hasAmbiguity(symbolName,referenceSymbol);
9241
9242#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9243 printf (" --- ambiguityDetected = %s \n",ambiguityDetected ? "true" : "false");
9244#endif
9245 }
9246
9247 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9248 if (ambiguityDetected == true || ambiguityDetectedSoSaveWholeChain == true)
9249 {
9250 ambiguityDetectedSoSaveWholeChain = true;
9251
9252 if (save_iter != classChain.end())
9253 {
9254#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9255 printf (" --- add to saveList: *save_iter = %p \n",*save_iter);
9256#endif
9257 saveList.push_back(*save_iter);
9258 }
9259 else
9260 {
9261#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9262 printf (" --- save_iter == classChain.end() \n");
9263#endif
9264 }
9265 }
9266
9267#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9268 printf ("******** BOTTOM OF WHILE LOOP ******** \n");
9269#endif
9270 i++;
9271
9272 // Also increment the save_iter.
9273 save_iter++;
9274 }
9275
9276 // Now build a list of class types to use in the name qualification from firstDetectedAmbiguity to lastDetectedAmbiguity (inclusive).
9277
9278#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9279 printf ("saveList.size() = %zu \n",saveList.size());
9280 std::list<SgClassType*>::iterator saveList_iterator = saveList.begin();
9281 while (saveList_iterator != saveList.end())
9282 {
9283 printf (" --- *saveList_iterator = %p = %s name = %s \n",*saveList_iterator,(*saveList_iterator)->class_name().c_str(),(*saveList_iterator)->get_name().str());
9284
9285 saveList_iterator++;
9286 }
9287#endif
9288
9289 returnTypeChain = saveList;
9290
9291 // End of branch for binaryOperator != NULL.
9292 }
9293
9294 return returnTypeChain;
9295 }
9296
9297
9298
9299bool
9301 {
9302 // DQ (2/17/2019): This may share a design in common with isDataMemberReference() below.
9303
9304#define DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE 0
9305
9306 ROSE_ASSERT(memberFunctionRefExp != NULL);
9307
9308 bool returnValue = false;
9309
9310 // 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;")
9311 SgNode* parent = memberFunctionRefExp->get_parent();
9312
9313 SgArrowExp* arrowExp = isSgArrowExp(parent);
9314 SgDotExp* dotExp = isSgDotExp(parent);
9315
9316 // I don't know that the SgAddressOfOp is as relevant for the case of SgMemberFunctionRefExp, but I think
9317 // it is because we would have to support membr pointeds to functions the same a member pointers to data.
9318 // I need some examples test codes to verify that name qualification is important in this case.
9319 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9320
9321 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9322 {
9323 // Use a SgFunctionSymbol instead of a SgMemberFunctionSymbol for generality (I hope this works).
9324 SgFunctionSymbol* symbol = memberFunctionRefExp->get_symbol();
9325 ROSE_ASSERT(symbol != NULL);
9326
9327 SgFunctionDeclaration* functionDeclaration = symbol->get_declaration();
9328 ROSE_ASSERT(functionDeclaration != NULL);
9329
9330 // Check if this is a statically declared variable.
9331 if (functionDeclaration != NULL)
9332 {
9333 bool isStatic = functionDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9334#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9335 printf ("isStatic = %s \n",isStatic ? "true" : "false");
9336#endif
9337 if (isStatic == false)
9338 {
9339 SgScopeStatement* scope = functionDeclaration->get_scope();
9340 ROSE_ASSERT(scope != NULL);
9341
9342 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9343 if (classDefinition != NULL)
9344 {
9345 returnValue = true;
9346 }
9347 }
9348 }
9349 else
9350 {
9351#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9352 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9353#endif
9354 }
9355 }
9356 else
9357 {
9358#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9359 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9360#endif
9361 }
9362
9363#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9364 printf ("Leaving SageInterface::isMemberFunctionMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9365#endif
9366
9367 return returnValue;
9368 }
9369
9370
9371
9372bool
9374 {
9375 // This function is used to support the name qualification of data member references seperate from name qualification
9376 // of variables that might be members (e.g. "X x; x.A::y;" instead of "A::y" (which is just simple name qualification)).
9377
9378 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9379
9380 // DQ (2/17/2019): I think we need to make sure this is not a static data member reference (since those are qualified
9381 // differently (not member data name qualification). Consider changing the name of this function to indicate non-static.
9382
9383#define DEBUG_IS_DATA_MEMBER_REFERENCE 0
9384
9385 ROSE_ASSERT(varRefExp != NULL);
9386
9387 bool returnValue = false;
9388
9389 // 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;")
9390 SgNode* parent = varRefExp->get_parent();
9391
9392 SgArrowExp* arrowExp = isSgArrowExp(parent);
9393 SgDotExp* dotExp = isSgDotExp(parent);
9394
9395 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9396
9397 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9398 {
9399 if (arrowExp != NULL)
9400 {
9401 // DQ (2/17/2019): Check if this is part of a sizeof operand for which is is_objectless_nonstatic_data_member_reference == true.
9402 SgNode* parentOfArrowExp = arrowExp->get_parent();
9403 ROSE_ASSERT(parentOfArrowExp != NULL);
9404 SgSizeOfOp* sizeOfOp = isSgSizeOfOp(parentOfArrowExp);
9405 if (sizeOfOp != NULL && sizeOfOp->get_is_objectless_nonstatic_data_member_reference() == true)
9406 {
9407 // This is not to be qualified using data member name qualification (it should use standard name qualification).
9408#if DEBUG_IS_DATA_MEMBER_REFERENCE
9409 printf ("In SageInterface::isDataMemberReference(): Found case of expression used in sizeof with objectless_nonstatic_data_member_reference \n");
9410#endif
9411 return false;
9412 }
9413 }
9414
9415 SgVariableSymbol* symbol = varRefExp->get_symbol();
9416 ROSE_ASSERT(symbol != NULL);
9417
9418 SgInitializedName* initializedName = symbol->get_declaration();
9419 ROSE_ASSERT(initializedName != NULL);
9420
9421 // Check if this is a statically declared variable.
9422 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(initializedName->get_parent());
9423 if (variableDeclaration != NULL)
9424 {
9425 bool isStatic = variableDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9426 if (isStatic == false)
9427 {
9428 SgScopeStatement* scope = initializedName->get_scope();
9429 ROSE_ASSERT(scope != NULL);
9430
9431 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9432 if (classDefinition != NULL)
9433 {
9434 returnValue = true;
9435 }
9436 }
9437 }
9438 else
9439 {
9440#if DEBUG_IS_DATA_MEMBER_REFERENCE
9441 printf ("In SageInterface::isDataMemberReference(): varRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9442#endif
9443 }
9444 }
9445 else
9446 {
9447#if DEBUG_IS_DATA_MEMBER_REFERENCE
9448 printf ("In SageInterface::isDataMemberReference(): varRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9449#endif
9450 }
9451
9452#if DEBUG_IS_DATA_MEMBER_REFERENCE
9453 printf ("Leaving SageInterface::isDataMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9454#endif
9455
9456 return returnValue;
9457 }
9458
9459
9460#if 0
9461bool
9463 {
9464 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9465 ROSE_ASSERT(varRefExp != NULL);
9466
9467 bool returnValue = false;
9468
9469 SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9470
9471 if (addressOfOp != NULL)
9472 {
9473 returnValue = true;
9474 }
9475
9476 return returnValue;
9477 }
9478#endif
9479
9480bool
9482 {
9483 // DQ (2/17/2019): Need to generalize this function to apply to member functions references as well.
9484
9485 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
9486 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
9487 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
9488
9489 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
9490
9491 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9492 // ROSE_ASSERT(varRefExp != NULL);
9493 ROSE_ASSERT(refExp != NULL);
9494
9495 bool returnValue = false;
9496
9497 // SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9498 SgAddressOfOp* addressOfOp = isSgAddressOfOp(refExp->get_parent());
9499
9500 if (addressOfOp != NULL)
9501 {
9502 returnValue = true;
9503 }
9504
9505 return returnValue;
9506 }
9507
9509 {
9510 // DQ (3/4/2014): This new version of this function supports both C/C++ and also Java.
9511 // If the SgJavaPackageDeclaration is noticed then the previous parent is a
9512 // SgClassDefinition and the previous previous parent is a SgClassDeclaration whose
9513 // name can be used to match the filename in the SgProject's list of files.
9514 // A better implementation usign an attribute (not in place until tomorrow) and
9515 // from the attribute the pointer to the associated file is directly available.
9516 // The later implementation is as fast as possible.
9517
9518 ROSE_ASSERT (astNode != NULL);
9519
9520 // Make sure this is not a project node (since the SgFile exists below
9521 // the project and could not be found by a traversal of the parent list)
9522 ROSE_ASSERT (isSgProject(astNode) == NULL);
9523
9524 SgNode* previous_parent = NULL;
9525 SgNode* previous_previous_parent = NULL;
9526
9527 SgNode* parent = astNode;
9528 // while ( (parent != NULL) && (isSgFile(parent) == NULL) )
9529 while ( (parent != NULL) && (isSgFile(parent) == NULL) && isSgJavaPackageDeclaration(parent) == NULL)
9530 {
9531#if 0
9532 printf ("In getEnclosingFileNode(): parent = %p = %s \n",parent,parent->class_name().c_str());
9533#endif
9534 previous_previous_parent = previous_parent;
9535 previous_parent = parent;
9536
9537 parent = parent->get_parent();
9538 }
9539
9540 if (previous_previous_parent != NULL && previous_parent != NULL && isSgJavaPackageDeclaration(parent) != NULL)
9541 {
9542 // This is for a Java program and is contained within a SgJavaPackageDeclaration
9543#if 0
9544 printf ("parent = %p = %s \n",parent,parent->class_name().c_str());
9545 printf ("previous_parent = %p = %s \n",previous_parent,previous_parent->class_name().c_str());
9546 printf ("previous_previous_parent = %p = %s \n",previous_previous_parent,previous_previous_parent->class_name().c_str());
9547#endif
9548 SgClassDeclaration* classDeclaration = isSgClassDeclaration(previous_previous_parent);
9549 if (classDeclaration != NULL)
9550 {
9551#if 0
9552 printf ("Class name = %p = %s = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9553#endif
9554 // Find the associated Java class file.
9555#if 0
9556 // DQ (3/4/2014): This is the code we want to use until we get Philippe's branch in place with the attribute.
9557 SgProject* project = TransformationSupport::getProject(parent);
9558 ROSE_ASSERT(project != NULL);
9559 SgFileList* fileList = project->get_fileList_ptr();
9560 ROSE_ASSERT(fileList != NULL);
9561 SgFilePtrList & vectorFile = fileList->get_listOfFiles();
9562#if 0
9563 printf ("Output list of files: \n");
9564#endif
9565 SgFilePtrList::iterator i = vectorFile.begin();
9566 while (i != vectorFile.end())
9567 {
9568 SgFile* file = *i;
9569 ROSE_ASSERT(file != NULL);
9570#if 0
9571 printf (" --- filename = %s \n",file->getFileName().c_str());
9572#endif
9573 string filename = file->getFileName();
9574 string filenameWithoutPath = file->get_sourceFileNameWithoutPath();
9575 string classname = classDeclaration->get_name();
9576 string matchingfilename = classname + ".java";
9577#if 0
9578 printf (" --- --- filename = %s \n",filename.c_str());
9579 printf (" --- --- filenameWithoutPath = %s \n",filenameWithoutPath.c_str());
9580 printf (" --- --- classname = %s \n",classname.c_str());
9581 printf (" --- --- matchingfilename = %s \n",matchingfilename.c_str());
9582#endif
9583 if (filenameWithoutPath == matchingfilename)
9584 {
9585#if 0
9586 printf (" return file = %p \n",file);
9587#endif
9588 return file;
9589 }
9590
9591 i++;
9592 }
9593#else
9594 // DQ (3/4/2014): This is the code we want to use when the attribute is in place (philippe's branch).
9595 AstSgNodeAttribute *attribute = (AstSgNodeAttribute *) classDeclaration->getAttribute("sourcefile");
9596
9597 // "This simpler and more efficent code requires the latest work in Java support (3/6/2014)"
9598
9599 if (attribute)
9600 {
9601 // true for all user-specified classes and false for all classes fom libraries
9602 SgSourceFile *sourcefile = isSgSourceFile(attribute->getNode());
9603 ROSE_ASSERT(sourcefile != NULL);
9604 return sourcefile;
9605 }
9606#endif
9607 }
9608 }
9609 else
9610 {
9611 // previous_parent was uninitialized to a non-null value or astNode is a SgJavaPackageDeclaration or SgFile.
9612 if (previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9613 {
9614 // The input was a SgJavaPackageDeclaration (so there is no associated SgFile).
9615 ROSE_ASSERT(isSgJavaPackageDeclaration(astNode) != NULL);
9616 return NULL;
9617 }
9618 else
9619 {
9620 if (previous_previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9621 {
9622 // The input was a SgClassDefinition (so there is no associated SgFile).
9623 ROSE_ASSERT(isSgClassDefinition(astNode) != NULL);
9624 return NULL;
9625 }
9626 else
9627 {
9628 // This could be a C/C++ file (handled below).
9629 }
9630 }
9631 }
9632
9633 // This is where we handle the C/C++ files.
9634 if (parent == nullptr)
9635 {
9636 return nullptr;
9637 }
9638 else
9639 {
9640 return isSgFile(parent);
9641 }
9642 }
9643
9645 struct FrontendSpecificTraversal : public ROSE_VisitTraversal {
9646 std::set<SgNode*> specific;
9647 std::set<SgNode*> non_specific;
9648
9649 static void recursive_collect( SgNode* node , std::set<SgNode *> & collection ) {
9650 // Stop on sinks and loops
9651 if (node == NULL || !collection.insert(node).second) return;
9652
9653 std::vector<std::pair<SgNode*, std::string> > data_members = node->returnDataMemberPointers();
9654 for (std::vector<std::pair<SgNode*, std::string> >::iterator i = data_members.begin(); i != data_members.end(); ++i) {
9655 recursive_collect(i->first, collection);
9656 }
9657 }
9658
9659 void visit (SgNode* n) {
9660 Sg_File_Info * fileInfo = n->get_file_info();
9661
9662 if (fileInfo != NULL) {
9663 if (fileInfo->isFrontendSpecific()) {
9664 specific.insert(n);
9665 recursive_collect(n, specific);
9666 } else {
9667 non_specific.insert(n);
9668 recursive_collect(n, non_specific);
9669 }
9670 } else {
9671 fileInfo = isSg_File_Info(n);
9672 if (fileInfo != NULL) {
9673 if (fileInfo->isFrontendSpecific()) {
9674 specific.insert(n);
9675 } else {
9676 non_specific.insert(n);
9677 }
9678 }
9679 }
9680 }
9681
9682 std::set<SgNode*> apply() {
9683 traverseMemoryPool();
9684
9685 std::set<SgNode*> result;
9686
9687 std::set_difference(
9688 specific.begin(), specific.end(),
9689 non_specific.begin(), non_specific.end(),
9690 std::insert_iterator<set<SgNode*> >(result, result.begin())
9691 );
9692
9693 return result;
9694 }
9695 };
9696
9697 FrontendSpecificTraversal fst;
9698 return fst.apply();
9699}
9700
9701void
9703 {
9704 // DQ (2/17/2019): Display the shared nodes in the AST for debugging.
9705
9706 class OutputSharedNodesTraversal : public SgSimpleProcessing
9707 {
9708 // This traversal collects the includes at the top of a file.
9709 public:
9710 void visit(SgNode *astNode)
9711 {
9712 ROSE_ASSERT(astNode != NULL);
9713 Sg_File_Info* file_info = astNode->get_file_info();
9714 if (file_info != NULL)
9715 {
9716 if (file_info->isShared() == true)
9717 {
9718 printf ("Found shared node: astNode = %p = %s \n",astNode,astNode->class_name().c_str());
9719 }
9720 }
9721 }
9722 };
9723
9724 OutputSharedNodesTraversal tt;
9725 tt.traverse(node,preorder);
9726 }
9727
9728
9729
9730
9731
9733 while (n && !isSgStatement(n)) n = n->get_parent();
9734 return isSgStatement(n);
9735}
9736
9737
9738
9739#if 1
9740// DQ (11/19/2020): We need to expand the use of this to cover deffered transformations of common SageInterface transformations (e.g. replaceStatement).
9741// So I need to move this out of being specific to the outliner and make it more generally data structure in the SageInterface.
9742
9743SageInterface::DeferredTransformation::DeferredTransformation()
9744 : deferredTransformationKind(e_default),
9745 statementToRemove(NULL),
9746 statementToAdd(NULL),
9747 class_definition(NULL),
9748 target_class_member(NULL),
9749 new_function_prototype(NULL),
9750 // DQ (2/28/2021): Added new data member to support deferred transformations.
9751 locationToOverwriteWithTransformation(NULL),
9752 transformationToOverwriteFirstStatementInInterval(NULL),
9753 blockOfStatementsToOutline(NULL)
9754 {
9755 // Default constructor (not particularly useful).
9756#if 0
9757 printf ("In SageInterface::DeferredTransformation default constructor called \n");
9758#endif
9759 }
9760
9761// DQ (2/28/2021): Added new data member to support deferred transformations.
9762// IntervalType statementInterval;
9763// SgStatement* locationToOverwriteWithTransformation;
9764
9765SageInterface::DeferredTransformation::DeferredTransformation(
9766 SgClassDefinition* input_class_definition,
9767 SgDeclarationStatement* input_target_class_member,
9768 SgDeclarationStatement* input_new_function_prototype)
9769 : deferredTransformationKind(e_outliner),
9770 statementToRemove(NULL),
9771 statementToAdd(NULL),
9772 class_definition(input_class_definition),
9773 target_class_member(input_target_class_member),
9774 new_function_prototype(input_new_function_prototype),
9775 // DQ (2/28/2021): Added new data member to support deferred transformations.
9776 locationToOverwriteWithTransformation(NULL),
9777 transformationToOverwriteFirstStatementInInterval(NULL),
9778 blockOfStatementsToOutline(NULL)
9779 {
9780 // This constructor is used by the outliner.
9781#if 0
9782 printf ("In SageInterface::DeferredTransformation constructor for outliner called \n");
9783#endif
9784 }
9785
9788 {
9789#if 0
9790 printf ("In SageInterface::DeferredTransformation constructor for replaceDefiningFunctionDeclarationWithFunctionPrototype called \n");
9791#endif
9792 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9793 // This constructor is used by tool_G and supports the use of the transformation represented
9794 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9796 X.deferredTransformationKind = e_replaceDefiningFunctionDeclarationWithFunctionPrototype;
9797 X.statementToRemove = functionDeclaration;
9798 X.statementToAdd = NULL;
9799 X.class_definition = NULL;
9800 X.target_class_member = NULL;
9801 X.new_function_prototype = NULL;
9802
9803 // DQ (2/28/2021): Added new data member to support deferred transformations.
9804 X.locationToOverwriteWithTransformation = NULL;
9805 X.transformationToOverwriteFirstStatementInInterval = NULL;
9806 X.blockOfStatementsToOutline = NULL;
9807
9808 return X;
9809 }
9810
9812SageInterface::DeferredTransformation::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool /*movePreprocessingInfo = false*/)
9813 {
9814#if 0
9815 printf ("In SageInterface::DeferredTransformation constructor for replaceStatement called \n");
9816#endif
9817 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9818 // This constructor is used by tool_G and supports the use of the transformation represented
9819 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9821 X.deferredTransformationKind = e_replaceStatement;
9822 X.statementToRemove = oldStmt;
9823 X.statementToAdd = newStmt;
9824 X.class_definition = NULL;
9825 X.target_class_member = NULL;
9826 X.new_function_prototype = NULL;
9827
9828 // DQ (2/28/2021): Added new data member to support deferred transformations.
9829 X.locationToOverwriteWithTransformation = NULL;
9830 X.transformationToOverwriteFirstStatementInInterval = NULL;
9831 X.blockOfStatementsToOutline = NULL;
9832
9833 return X;
9834 }
9835
9836SageInterface::DeferredTransformation::DeferredTransformation (const DeferredTransformation& X)
9837#if 0
9838 : deferredTransformationKind(X.deferredTransformationKind),
9839 statementToRemove(X.statementToRemove),
9840 statementToAdd(X.StatementToAdd),
9841 class_definition(X.class_definition),
9842 target_class_member(X.target_class_member),
9843 new_function_prototype(X.new_function_prototype),
9844 targetClasses(X.targetClasses),
9845 targetFriends(X.targetFriends)
9846 {
9847 }
9848#else
9849 {
9850#if 0
9851 printf ("In SageInterface::DeferredTransformation copy constructor called \n");
9852#endif
9853 // DQ (11/19/2020): Leverage the operator=() implementation to reduce complexity (one place to update).
9854 *this = X;
9855 }
9856#endif
9857
9859 {
9860#if 0
9861 printf ("Inside of SageInterface::DeferredTransformation::operator= (const DeferredTransformation& X) \n");
9862#endif
9863
9864#if 0
9865 // Original code.
9866 targetFriends = X.targetFriends;
9867 targetClasses = X.targetClasses;
9868#else
9869
9870 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9871 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9872 // definitions in the dynamic library file with function prototypes.
9873 transformationLabel = X.transformationLabel;
9874
9875 // New code added to support more general usage.
9876 deferredTransformationKind = X.deferredTransformationKind;
9877 statementToRemove = X.statementToRemove;
9878 statementToAdd = X.statementToAdd;
9879
9880 class_definition = X.class_definition;
9881 target_class_member = X.target_class_member;
9882 new_function_prototype = X.new_function_prototype;
9883 targetClasses = X.targetClasses;
9884 targetFriends = X.targetFriends;
9885
9886 // DQ (2/28/2021): Added new data member to support deferred transformations.
9887 statementInterval = X.statementInterval;
9888 locationToOverwriteWithTransformation = X.locationToOverwriteWithTransformation;
9889 transformationToOverwriteFirstStatementInInterval = X.transformationToOverwriteFirstStatementInInterval;
9890
9891 // DQ (3/1/2021): Added new data member to support deferred transformations.
9892 blockOfStatementsToOutline = X.blockOfStatementsToOutline;
9893#endif
9894
9895 return *this;
9896 }
9897
9902
9903std::string SageInterface::DeferredTransformation::outputDeferredTransformationKind(const TransformationKind & kind)
9904 {
9905 string returnValue = "uninitialized";
9906 switch (kind)
9907 {
9908 case e_error: returnValue = "e_error"; break;
9909 case e_default: returnValue = "e_default"; break;
9910 case e_outliner: returnValue = "e_outliner"; break;
9911 case e_replaceStatement: returnValue = "e_replaceStatement"; break;
9912 case e_removeStatement: returnValue = "e_removeStatement"; break;
9913 case e_replaceDefiningFunctionDeclarationWithFunctionPrototype: returnValue = "e_replaceDefiningFunctionDeclarationWithFunctionPrototype"; break;
9914 case e_last: returnValue = "e_last"; break;
9915 default:
9916 {
9917 printf ("Error: SageInterface::DeferredTransformation::get_deferredTransformationKind_string(): default reached \n");
9918 ROSE_ABORT();
9919 }
9920 }
9921
9922 return returnValue;
9923 }
9924
9925void SageInterface::DeferredTransformation::display ( std::string label ) const
9926 {
9927 printf ("SageInterface::DeferredTransformation::display(): label = %s \n",label.c_str());
9928
9929 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9930 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9931 // definitions in the dynamic library file with function prototypes.
9932 printf (" --- transformationLabel = %s \n",transformationLabel.c_str());
9933
9934 printf (" --- deferredTransformationKind = %s \n",outputDeferredTransformationKind(deferredTransformationKind).c_str());
9935 if (statementToRemove != NULL)
9936 {
9937 printf (" --- statementToRemove = %p = %s name = %s \n",statementToRemove,statementToRemove->class_name().c_str(),get_name(statementToRemove).c_str());
9938 }
9939 else
9940 {
9941 printf (" --- statementToRemove == NULL \n");
9942 }
9943
9944 if (statementToAdd != NULL)
9945 {
9946 printf (" --- statementToAdd = %p = %s name = %s \n",statementToAdd,statementToAdd->class_name().c_str(),get_name(statementToAdd).c_str());
9947 }
9948 else
9949 {
9950 printf (" --- statementToAdd == NULL \n");
9951 }
9952
9953 if (class_definition != NULL)
9954 {
9955 // printf (" --- class_definition = %p = %s name = %s \n",class_definition,class_definition->class_name().c_str(),get_name(class_definition).c_str());
9956 printf (" --- class_definition = %p \n",class_definition);
9957 }
9958
9959 if (target_class_member != NULL)
9960 {
9961 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());
9962 }
9963
9964 if (new_function_prototype != NULL)
9965 {
9966 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());
9967 }
9968
9969 // DQ (2/28/2021): Added new data member to support deferred transformations.
9970 if (locationToOverwriteWithTransformation != NULL)
9971 {
9972 // printf (" --- locationToOverwriteWithTransformation = %p = %s name = %s \n",locationToOverwriteWithTransformation,
9973 // locationToOverwriteWithTransformation->class_name().c_str(),get_name(locationToOverwriteWithTransformation).c_str());
9974 printf (" --- locationToOverwriteWithTransformation = %p \n",locationToOverwriteWithTransformation);
9975 }
9976
9977 // DQ (2/28/2021): Added new data member to support deferred transformations.
9978 if (transformationToOverwriteFirstStatementInInterval != NULL)
9979 {
9980 // printf (" --- transformationToOverwriteFirstStatementInInterval = %p = %s name = %s \n",transformationToOverwriteFirstStatementInInterval,
9981 // transformationToOverwriteFirstStatementInInterval->class_name().c_str(),get_name(transformationToOverwriteFirstStatementInInterval).c_str());
9982 printf (" --- transformationToOverwriteFirstStatementInInterval = %p \n",transformationToOverwriteFirstStatementInInterval);
9983 }
9984
9985 // DQ (3/1/2021): Added new data member to support deferred transformations.
9986 if (blockOfStatementsToOutline != NULL)
9987 {
9988 printf (" --- blockOfStatementsToOutline = %p \n",blockOfStatementsToOutline);
9989 }
9990
9991 printf ("targetClasses.size() = %zu \n",targetClasses.size());
9992 printf ("targetFriends.size() = %zu \n",targetFriends.size());
9993
9994 // DQ (2/28/2021): Added new data member to support deferred transformations.
9995 printf ("statementInterval.size() = %zu \n",statementInterval.size());
9996
9997 }
9998#endif
9999
10000
10001
10002
10003
10004// DQ (/20/2010): Control debugging output for SageInterface::removeStatement() function.
10005#define REMOVE_STATEMENT_DEBUG 0
10006
10008void SageInterface::removeStatement(SgStatement* targetStmt, bool autoRelocatePreprocessingInfo /*= true*/)
10009 {
10010#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
10011 // This function removes the input statement.
10012 // If there are comments and/or CPP directives then those comments and/or CPP directives will
10013 // be moved to a new SgStatement. The new SgStatement is selected using the findSurroundingStatementFromSameFile()
10014 // function and if there is not statement found then the SgGlobal IR node will be selected.
10015 // this work is tested by the tests/nonsmoke/functional/roseTests/astInterfaceTests/removeStatementCommentRelocation.C
10016 // translator and a number of input codes that represent a range of contexts which exercise different
10017 // cases in the code below.
10018
10019#ifndef _MSC_VER
10020 // This function only supports the removal of a whole statement (not an expression within a statement)
10021 ASSERT_not_null(targetStmt);
10022
10023 SgStatement * parentStatement = isSgStatement(targetStmt->get_parent());
10024
10025 // Can't assert this since SgFile is the parent of SgGlobal, and SgFile is not a statement.
10026 // Even so SgGlobal can't be removed from SgFile, but isRemovableStatement() takes a SgStatement.
10027 // ROSE_ASSERT (parentStatement != NULL);
10028
10029 bool isRemovable = (parentStatement != NULL) ? LowLevelRewrite::isRemovableStatement(targetStmt) : false;
10030
10031#if REMOVE_STATEMENT_DEBUG || 0
10032 printf ("In SageInterface::removeStatement(): parentStatement = %p = %s remove targetStatement = %p = %s (isRemovable = %s) \n",
10033 parentStatement,parentStatement->class_name().c_str(),targetStmt,targetStmt->class_name().c_str(),isRemovable ? "true" : "false");
10034#endif
10035
10036 if (isRemovable == true)
10037 {
10038 // DQ (9/19/2010): Disable this new (not completely working feature) so that I can checkin the latest UPC/UPC++ work.
10039#if 1
10040 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
10041 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
10042 // Liao 10/28/2010. Sometimes we want remove the statement with all its preprocessing information
10043 if (autoRelocatePreprocessingInfo == true)
10044 {
10045 // WE need to move up inner danglinge #endif or #if directives first.
10047 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
10048 // appear before the statment to be attached to the inserted statement (and marked
10049 // to appear before that statement).
10050 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
10051
10052
10053 if (comments != nullptr && isSgBasicBlock(targetStmt) == nullptr )
10054 {
10055 vector<int> captureList;
10056#if REMOVE_STATEMENT_DEBUG
10057 printf ("Found attached comments (removing %p = %s): comments->size() = %" PRIuPTR " \n",targetStmt,targetStmt->class_name().c_str(),comments->size());
10058#endif
10059
10060 // Liao 10/28/2010. relinking AST statements may be achieved by remove it and attach it to somewhere else.
10061 // In this case, preprocessing information sometimes should go with the statements and not be relocated to the original places.
10062 // Dan: Since this statement will be removed we have to relocate all the associated comments and CPP directives.
10063 int commentIndex = 0;
10064 AttachedPreprocessingInfoType::iterator i;
10065 for (i = comments->begin(); i != comments->end(); i++)
10066 {
10067 ROSE_ASSERT ( (*i) != NULL );
10068#if REMOVE_STATEMENT_DEBUG
10069 printf (" Attached Comment (relativePosition=%s): %s\n",
10070 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
10071 (*i)->getString().c_str());
10072 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
10073 (*i)->get_file_info()->display("comment/directive location debug");
10074#endif
10075 captureList.push_back(commentIndex);
10076 commentIndex++;
10077 }
10078
10079#if REMOVE_STATEMENT_DEBUG
10080 printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
10081#endif
10082
10083 if (captureList.empty() == false)
10084 {
10085 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
10086 // Find the surrounding statement by first looking up in the sequence of statements in this block, then down, we need another
10087 // statement from the same file. SgGlobal may be returned if nothing else is found.
10088 bool surroundingStatementPreceedsTargetStatement = false;
10089 SgStatement* surroundingStatement = findSurroundingStatementFromSameFile(targetStmt,surroundingStatementPreceedsTargetStatement);
10090
10091 if (surroundingStatement != nullptr)
10092 {
10093 // If we have identified a valid surrounding statemen, then move the comments and CPP directives to that statement.
10094#if REMOVE_STATEMENT_DEBUG
10095 printf ("In removeStatement(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10096 printf (" --- moving comments from targetStmt = %p = %s name = %s \n",targetStmt,targetStmt->class_name().c_str(),get_name(targetStmt).c_str());
10097 printf (" --- moving comments to surroundingStatement = %p = %s name = %s \n",surroundingStatement,surroundingStatement->class_name().c_str(),get_name(surroundingStatement).c_str());
10098#endif
10099 moveCommentsToNewStatement(targetStmt,captureList,surroundingStatement,surroundingStatementPreceedsTargetStatement);
10100 }
10101 }
10102 } // end if (comments)
10103 }// end if (autoRelocatePreprocessingInfo)
10104#endif // end #if 1
10105
10106 // DQ (12/1/2015): Adding support for fixup internal data struuctures that have references to statements (e.g. macro expansions).
10108
10109 parentStatement->remove_statement(targetStmt);
10110 }
10111#else
10112 printf ("Error: This is not supported within Microsoft Windows (I forget why). \n");
10113 ROSE_ABORT();
10114#endif
10115
10116#endif
10117 }
10118
10119
10120
10122void
10124 {
10125 // This function allows the modification of the input statement to trigger operations on internal
10126 // data structures that hold references to such statements. An example is the macroExpansion
10127 // data structures that have a reference to the statements that are associated with and macro expansion.
10128 // if a statement assocated with a macro expansion is removed, then the macroExpansion needs to be
10129 // updated to force all of the statements to be marked as transformed (so that the AST will be unparsed
10130 // instead of the tokens representing the macro or some partial representation of the transformed
10131 // statements and the macro call (worse).
10132
10133#if 0
10134 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10135#endif
10136
10137 SgSourceFile* sourceFile = getEnclosingSourceFile(sourceStatement);
10138
10139 // NOTE: if the statment has not yet been added to the AST then it will not return a valid pointer.
10140 // ROSE_ASSERT(sourceFile != NULL);
10141
10142#if 0
10143 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceFile = %p \n",sourceFile);
10144#endif
10145
10146 if (sourceFile != NULL)
10147 {
10148 std::map<SgStatement*,MacroExpansion*> & macroExpansionMap = sourceFile->get_macroExpansionMap();
10149
10150 if (macroExpansionMap.find(sourceStatement) != macroExpansionMap.end())
10151 {
10152 MacroExpansion* macroExpansion = macroExpansionMap[sourceStatement];
10153 ROSE_ASSERT(macroExpansion != NULL);
10154#if 0
10155 printf ("In resetInternalMapsForTargetStatement(): macroExpansion = %p = %s \n",macroExpansion,macroExpansion->macro_name.c_str());
10156#endif
10157 if (macroExpansion->isTransformed == false)
10158 {
10159 // Mark all of the statements in the macro expansion to be transformed.
10160 std::vector<SgStatement*> & associatedStatementVector = macroExpansion->associatedStatementVector;
10161
10162 for (size_t i = 0; i < associatedStatementVector.size(); i++)
10163 {
10164 // I am concerned that some of these statements might have been deleted.
10165 SgStatement* statement = associatedStatementVector[i];
10166#if 0
10167 printf ("Mark as transformation to be output: statement = %p = %s \n",statement,statement->class_name().c_str());
10168#endif
10169 // Note that any new statement might not yet have valid Sg_File_Info objects setup at this point.
10170 // Then again, now did it make it into the associatedStatementVector unless it was via memory
10171 // recycling through the mmory pool.
10172 if (statement->get_file_info() != NULL)
10173 {
10174 // Mark each of the statements as a transformation.
10175 statement->setTransformation();
10176
10177 // This is required, else the statement will not be output in the generated code.
10178 // To understand this, consider that statements in header files could be transformed,
10179 // but we would not want that to cause them to be unparse in the source file.
10180 statement->setOutputInCodeGeneration();
10181
10182 // Not clear if we should also remove the statement from the associatedStatementVector.
10183 // This would be important to do to avoid having the same location in the memory pool
10184 // be reused for another statement. Since we makr the macro expansion as transformed
10185 // we likely don't have to worry about this.
10186 }
10187 }
10188 }
10189
10190 // Mark this macro expansion as having been processed.
10191 macroExpansion->isTransformed = true;
10192 }
10193
10194 // Other data strucutes that may have to be updated include:
10195 // representativeWhitespaceStatementMap (should be required, but only effects whitespace details)
10196 // redundantlyMappedTokensToStatementMultimap (might not be required)
10197
10198 }
10199 }
10200
10201
10203void
10204SageInterface::moveCommentsToNewStatement(SgStatement* sourceStatement, const vector<int> & indexList, SgStatement* destinationStatement , bool destinationStatementProceedsSourceStatement)
10205 {
10206 AttachedPreprocessingInfoType* comments = sourceStatement->getAttachedPreprocessingInfo();
10207
10208#if REMOVE_STATEMENT_DEBUG || 0
10209 printf ("In moveCommentsToNewStatement(): destinationStatementProceedsSourceStatement = %s \n",destinationStatementProceedsSourceStatement ? "true" : "false");
10210 printf (" --- sourceStatement = %p = %s name = %s \n",sourceStatement,sourceStatement->class_name().c_str(),get_name(sourceStatement).c_str());
10211 printf (" --- destinationStatement = %p = %s name = %s \n",destinationStatement,destinationStatement->class_name().c_str(),get_name(destinationStatement).c_str());
10212#endif
10213 // Liao 2024/1/24
10214 // 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.
10215 // A solution : pcounter++ whenever a leading #if #ifdef #ifndef is encountered.
10216 // pcounter -- if #endif is countered
10217 // Normally the final pcounter ==0, if pcounter>=1, a #endif is missing somewhere. We should patch it up.
10218
10219#if REMOVE_STATEMENT_DEBUG
10220 printf ("Output the comments attached to sourceStatement: \n");
10221 printOutComments(sourceStatement);
10222 printf ("Output the comments attached to destinationStatement: \n");
10223 printOutComments(destinationStatement);
10224#endif
10225
10226 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
10227 vector<int>::const_iterator j = indexList.begin();
10228 PreprocessingInfo* prevTargetAnchorComment = NULL;
10229 while (j != indexList.end())
10230 {
10231 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
10232 ROSE_ASSERT(destinationStatement->get_file_info() != NULL);
10233#if REMOVE_STATEMENT_DEBUG || 0
10234 printf ("Attaching comments to destinationStatement = %p = %s on file = %s line %d \n",
10235 destinationStatement,destinationStatement->class_name().c_str(),
10236 destinationStatement->get_file_info()->get_filenameString().c_str(),
10237 destinationStatement->get_file_info()->get_line());
10238
10239 printf ("(*comments)[*j]->getRelativePosition() = %s \n",PreprocessingInfo::relativePositionName((*comments)[*j]->getRelativePosition()).c_str());
10240#endif
10241
10242 // Liao 2024/3/27: special handling when surrounding statement is SgGlobal
10243 // It should not be treated as either before or after the source statement we want to move comments from
10244 // SgGlobal should be treated as the enclosing scope of the source statement
10245 // The comments of the source statements should be attached to inside position of SgGlobal.
10246 // This is a variant of the before position (SgGlobal vs. source statement).
10247 // We do not treate SgGlobal as the same as if sgGlobal is preceeding source
10248 // because the comments of source statement would be attached to ::after of SgGlobal and
10249 // all comments will show up in the end of the file.
10250 // The ::inside location relies on the unparser to properly handle them later.
10251 if (destinationStatementProceedsSourceStatement == true || isSgGlobal(destinationStatement) != NULL )
10252 {
10253 // dest
10254 // src // comments to be moved up: all before positions become after position
10255 // // then append to dest's commments
10256 // adjust relative position one by one
10257 auto commentPosition = (*comments)[*j]->getRelativePosition();
10258 if (commentPosition == PreprocessingInfo::before)
10259 {
10260 // Mark comments that were before the preceeding statement to be after the preceeding statement
10261 (*comments)[*j]->setRelativePosition(PreprocessingInfo::after);
10262 }
10263 else if (commentPosition == PreprocessingInfo::after ||
10264 commentPosition == PreprocessingInfo::end_of)
10265 {
10266 // Leave position alone [Rasmussen 2023.01.09]
10267 }
10268 else
10269 {
10270 ROSE_ASSERT(false && "Comment relative position neither, before, after, nor end_of");
10271 }
10272
10273 // special handling of inside position
10274 // The surrounding statement will accept the comments. It also preceeds the source statement providing the comments.
10275 // If it is an enclosing scope statement, the comments should be attached to inside position, not before nor after.
10276 // if ( isSgGlobal(destinationStatement) || isSgBasicBlock(destinationStatement) )
10277 // Handle all SgScopeStatement variants.
10278 // We do this only for C/C++ language. Otherwise the code may break Jovial and other languages.
10280 {
10281 if (SageInterface::isAncestor(destinationStatement, sourceStatement))
10282 (*comments)[*j]->setRelativePosition(PreprocessingInfo::inside);
10283 }
10284 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10285
10286 }
10287 else // the target statement is after the source statment: we want to move comments from src to target
10288 {
10289 // src : comments : before or after (when moved to dest, it should become before)
10290 // all should be prepend to dest's first comment
10291 // dest: comments
10292 // adjust relative position one by one
10293 if ((*comments)[*j]->getRelativePosition() == PreprocessingInfo::before)
10294 {
10295 // Leave the comments marked as being before the removed statement
10296 // as before the following statement
10297 }
10298 else
10299 {
10300 // If is is not before, I hope it can only be after. Sometimes it is end_of, e.g. gitlab-issue-186.jov
10301 ASSERT_require((*comments)[*j]->getRelativePosition() == PreprocessingInfo::after||
10302 (*comments)[*j]->getRelativePosition() == PreprocessingInfo::end_of);
10303 (*comments)[*j]->setRelativePosition(PreprocessingInfo::before);
10304 }
10305 AttachedPreprocessingInfoType* targetInfoList = destinationStatement->getAttachedPreprocessingInfo();
10306 // source stmt has a list of comments c1, c2, c3
10307 // we want to keep their order and prepend to target stmt's existing comments
10308 // The solution is to define an anchor comment in target stmt
10309 // first time anchor is NULL, we prepend c1 to before the target stmt's first comment
10310 // after that, we insert after the anchor comment (previous anchor)
10311 // all anchor comments must come from source statement
10312 if (targetInfoList==NULL)
10313 {
10314 // we can just use append to the end. the same effect.
10315 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10316 }
10317 else
10318 {
10319 // target stmt has comments
10320 // first time to grab thing
10321 if( prevTargetAnchorComment==NULL)
10322 {
10323 PreprocessingInfo * origFirstTargetComment = *(targetInfoList->begin());
10324 // insert before this original first one
10325 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],origFirstTargetComment,false);
10326 }
10327 else
10328 {
10329 // now we have non null prev comment from target statement. insert after it!
10330 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],prevTargetAnchorComment ,true);
10331 }
10332 }
10333
10334 prevTargetAnchorComment = (*comments)[*j];
10335 }
10336
10337
10338 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
10339#if REMOVE_STATEMENT_DEBUG
10340 printf ("Marking entry from comments list as NULL on sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10341#endif
10342 (*comments)[*j] = nullptr;// Why do we need to make it NULL??
10343
10344 j++;
10345 }
10346
10347 // Now remove each NULL entries in the comments vector.
10348 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
10349 for (size_t n = 0; n < indexList.size(); n++)
10350 {
10351#if REMOVE_STATEMENT_DEBUG || 0
10352 printf ("Erase entry from comments list on comments->size() %" PRIuPTR " \n",comments->size());
10353#endif
10354 bool modifiedList = false;
10355 AttachedPreprocessingInfoType::iterator k = comments->begin();
10356 while (k != comments->end() && modifiedList == false)
10357 {
10358 // Only modify the list once per iteration over the captureList
10359 if (*k == nullptr)
10360 {
10361 k = comments->erase(k);
10362 modifiedList = true;
10363 continue;
10364 }
10365 else
10366 {
10367 k++;
10368 }
10369 }
10370 }
10371 }
10372
10373
10375// This function is a helper function for SageInterface::removeStatement() to handle preprocessing info.
10376// It should find a suitable destination statement to which we can move the current stmt's preprocessing info to.
10377// targetStmt of this function is the source statement to move preprocessing info first, before removing it.
10379SageInterface::findSurroundingStatementFromSameFile(SgStatement* targetStmt, bool & surroundingStatementPreceedsTargetStatement)
10380 {
10381 // Note that if the return value is SgGlobal (global scope), then surroundingStatementPreceedsTargetStatement is false, but meaningless.
10382 // This function can not return a NULL pointer.
10383
10384 ROSE_ASSERT(targetStmt != NULL);
10385
10386 SgStatement* surroundingStatement = targetStmt;
10387 int surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID; // No file id can have this value.
10388
10389#if REMOVE_STATEMENT_DEBUG || 0
10390 printf ("TOP of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10391#endif
10392
10393 std::set<SgStatement*> previousVisitedStatementSet;
10394
10395 // Only handle relocation for statements that exist in the file (at least for now while debugging).
10396 if (targetStmt->get_file_info()->get_file_id() >= 0)
10397 {
10398 surroundingStatementPreceedsTargetStatement = true;
10399
10400#if REMOVE_STATEMENT_DEBUG
10401 printf (" targetStmt->get_file_info()->get_file_id() = %d \n",targetStmt->get_file_info()->get_file_id());
10402#endif
10403#if REMOVE_STATEMENT_DEBUG
10404 printf ("Before loop: surroundingStatement = %p = %s name = %s surroundingStatement_fileId = %d \n",surroundingStatement,
10405 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str(),surroundingStatement_fileId);
10406#endif
10407 bool returningNullSurroundingStatement = false;
10408 // while (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id())
10409 while ((returningNullSurroundingStatement == false) && (surroundingStatement != NULL) && surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id() && surroundingStatement_fileId !=Sg_File_Info::TRANSFORMATION_FILE_ID)
10410 {
10411 // Start by going up in the source sequence.
10412 // This is a declaration from the wrong file so go to the next statement.
10413 // surroundingStatement = (insertBefore == true) ? getNextStatement(surroundingStatement) : getPreviousStatement(surroundingStatement);
10414 // surroundingStatement = (insertBefore == true) ? getPreviousStatement(surroundingStatement) : getNextStatement(surroundingStatement);
10415 // Liao, 12/26/2024. We should not climb out the current scope when finding the previous statement
10416 // Otherwise, preprocessingInfo may be moved from a child stmt to its parent stmt, causing errors in AST.
10417 surroundingStatement = getPreviousStatement(surroundingStatement, false);
10418
10419#if REMOVE_STATEMENT_DEBUG
10420 printf ("In loop: after getPreviousStatement(): surroundingStatement = %p = %s name = %s \n",surroundingStatement,
10421 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str());
10422#endif
10423
10424 if (surroundingStatement == NULL)
10425 {
10426 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10427#if REMOVE_STATEMENT_DEBUG
10428 printf (" surroundingStatement_fileId set to Sg_File_Info::BAD_FILE_ID \n");
10429#endif
10430 }
10431 else
10432 {
10433 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10434#if REMOVE_STATEMENT_DEBUG
10435 printf (" surroundingStatement = %p = %s surroundingStatement->get_file_info()->get_file_id() = %d \n",
10436 surroundingStatement,surroundingStatement->class_name().c_str(),surroundingStatement->get_file_info()->get_file_id());
10437#endif
10438 }
10439
10440#if REMOVE_STATEMENT_DEBUG
10441 if (surroundingStatement != NULL)
10442 {
10443 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",
10444 surroundingStatement,surroundingStatement->class_name().c_str(),
10445 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10446 surroundingStatement->get_file_info()->get_file_id(),
10447 surroundingStatement->get_file_info()->get_line());
10448 }
10449 else
10450 {
10451 printf ("surroundingStatement == NULL \n");
10452 }
10453#endif
10454
10455 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10456 if (previousVisitedStatementSet.find(surroundingStatement) != previousVisitedStatementSet.end())
10457 {
10458 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10459
10460 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10461
10462 surroundingStatement = NULL;
10463 // break;
10464 // return NULL;
10465 }
10466 else
10467 {
10468 previousVisitedStatementSet.insert(surroundingStatement);
10469 }
10470
10471 // As a last resort restart and go down in the statement sequence.
10472 if (surroundingStatement == NULL || isSgGlobal(surroundingStatement) != NULL)
10473 {
10474 // This is triggered by rose_inputloopUnrolling.C
10475#if REMOVE_STATEMENT_DEBUG
10476 printf ("We just ran off the start (top) of the file... targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
10477#endif
10478#if 0
10479 ROSE_ABORT();
10480#endif
10481 // A statement in the same file could not be identified, so this is false.
10482 surroundingStatementPreceedsTargetStatement = false;
10483
10484 // Restart by going the other direction (down in the source sequence)
10485 surroundingStatement = targetStmt;
10486 SgStatement* previousStatement = surroundingStatement;
10487 // surroundingStatement = getNextStatement(surroundingStatement);
10488 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10489
10490 std::set<SgStatement*> forwardVisitedStatementSet;
10491
10492 // while ( (surroundingStatement != NULL) && (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id()) )
10493 while ( (surroundingStatement != NULL) && (surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id()) )
10494 {
10495 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10496 if (forwardVisitedStatementSet.find(surroundingStatement) != forwardVisitedStatementSet.end())
10497 {
10498 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10499
10500 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10501
10502 surroundingStatement = NULL;
10503 break;
10504 // return NULL;
10505 }
10506 else
10507 {
10508 forwardVisitedStatementSet.insert(surroundingStatement);
10509 }
10510
10511 previousStatement = surroundingStatement;
10512 surroundingStatement = getNextStatement(surroundingStatement);
10513
10514 if (surroundingStatement == NULL)
10515 {
10516 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10517#if REMOVE_STATEMENT_DEBUG
10518 printf ("We just ran off the end (bottom) of the file... \n");
10519#endif
10520#if 0
10521 ROSE_ABORT();
10522#endif
10523 returningNullSurroundingStatement = true;
10524 }
10525 else
10526 {
10527 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10528#if REMOVE_STATEMENT_DEBUG
10529 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",
10530 surroundingStatement,surroundingStatement->class_name().c_str(),
10531 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10532 surroundingStatement->get_file_info()->get_file_id(),
10533 surroundingStatement->get_file_info()->get_line());
10534#endif
10535 }
10536 }
10537
10538 if (surroundingStatement == NULL)
10539 {
10540#if REMOVE_STATEMENT_DEBUG
10541 printf ("Resetting the surroundingStatement to the previousStatement = %p = %s \n",previousStatement,previousStatement->class_name().c_str());
10542#endif
10543 surroundingStatement = previousStatement;
10544
10545 // Check if this is the input statement we are removing (since the we have to attach comments to the global scope IR node.
10546 if (surroundingStatement == targetStmt)
10547 {
10548 // This can happen if there was only a single statement in a file and it was removed.
10549 // All associated comments would have to be relocated to the SgGlobal IR node.
10550#if REMOVE_STATEMENT_DEBUG
10551 printf ("Setting the surroundingStatement to be global scope \n");
10552#endif
10553 surroundingStatement = TransformationSupport::getGlobalScope(targetStmt);
10554 }
10555 }
10556 }
10557 }
10558
10559 ROSE_ASSERT(surroundingStatement != NULL);
10560 }
10561 else
10562 {
10563 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());
10564 surroundingStatement = NULL;
10565 }
10566
10567#if REMOVE_STATEMENT_DEBUG
10568 printf ("BOTTOM of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s surroundingStatement = %p \n",surroundingStatementPreceedsTargetStatement ? "true" : "false",surroundingStatement);
10569 if (surroundingStatement != NULL)
10570 {
10571 printf ("surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10572 }
10573#endif
10574
10575 // ROSE_ASSERT(surroundingStatement != NULL);
10576
10577 return surroundingStatement;
10578 }
10579
10580
10581#ifndef USE_ROSE
10584{
10585#if 0
10586 struct Visitor: public AstSimpleProcessing {
10587 virtual void visit(SgNode* n) {
10588 delete (n);
10589 }
10590 };
10591 Visitor().traverse(root, postorder);
10592#else
10593 deleteAST(root);
10594#endif
10595}
10596#endif
10597
10599void SageInterface::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool movePreprocessingInfoValue/* = false*/)
10600 {
10601 ROSE_ASSERT(oldStmt);
10602 ROSE_ASSERT(newStmt);
10603
10604 if (oldStmt == newStmt) return;
10605
10606 SgStatement * p = isSgStatement(oldStmt->get_parent());
10607 ROSE_ASSERT(p);
10608
10609#if 0
10610 // TODO handle replace the body of a C/Fortran function definition with a single statement?
10611 // Liao 2/1/2010, in some case, we want to replace the entire body (SgBasicBlock) for some parent nodes.
10612 // the built-in replace_statement() (insert_child() underneath) may not defined for them.
10613 if (SgFortranDo * f_do = isSgFortranDo (p))
10614 {
10615 ROSE_ASSERT (f_do->get_body() == oldStmt);
10616 if (!isSgBasicBlock(newStmt))
10617 newStmt = buildBasicBlock (newStmt);
10618 f_do->set_body(isSgBasicBlock(newStmt));
10619 newStmt->set_parent(f_do);
10620 }
10621 else
10622 {
10623 p->replace_statement(oldStmt,newStmt);
10624 }
10625#endif
10626 p->replace_statement(oldStmt,newStmt);
10627
10628#if 1
10629 // DQ (7/20/2021): Need to make the physical_file_ids match and the parents.
10630 // Acutally this may be too late in the case of a deferred transformation since
10631 // we run the AST consistancy tests as an intermediate step.
10632 int physical_file_id = oldStmt->get_startOfConstruct()->get_physical_file_id();
10633
10634#if 0
10635 printf ("In SageInterface::replaceStatement(): physical_file_id = %d \n",physical_file_id);
10636#endif
10637
10638 newStmt->get_startOfConstruct()->set_physical_file_id(physical_file_id);
10639 newStmt->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
10640
10641 // DQ (7/20/2021): Do we need this when we set the physical_file_id?
10642 newStmt->set_parent(oldStmt->get_parent());
10643#endif
10644
10645 // Some translators have their own handling for this (e.g. the outliner)
10646 if (movePreprocessingInfoValue)
10647 {
10648 // move inner dangling #endif, #if etc to newStmt's after position, otherwise they got lost
10649//A-B test here
10650 // I think we should move up old statement's inner dangling directives
10651 // later , we move directives from old statement to new statement
10653#if 0
10654 printf ("In SageInterface::replaceStatement(): calling moveUpPreprocessingInfo() changed to movePreprocessingInfo() \n");
10655#endif
10656
10657 // DQ (12/28/2020): I think this should be movePreprocessingInfo instead of moveUpPreprocessingInfo
10658 // (which has a collection of defaults that are not appropriate).
10659 // moveUpPreprocessingInfo(newStmt, oldStmt);
10660#if 1
10661 // 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).
10662 moveUpPreprocessingInfo(newStmt, oldStmt);
10663#else
10664 // void SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
10665 // PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
10666 bool usePrepend = true;
10667 // movePreprocessingInfo ( newStmt, oldStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10668 movePreprocessingInfo ( oldStmt, newStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10669#endif
10670 }
10671 }
10672
10673void
10675 {
10676 // Relocate the declaration to be explicitly represented in its associated namespace (required for some backend compilers to process template instantiations).
10677
10678 // DQ (7/19/2015): This is required to support general unparsing of template instantations for the GNU g++
10679 // compiler which does not permit name qualification to be used to support the expression of the namespace
10680 // where a template instantiatoon would be places. Such name qualification would also sometimes require
10681 // global qualification which is also not allowed by the GNU g++ compiler. These issues appear to be
10682 // specific to the GNU compiler versions, at least versions 4.4 through 4.8.
10683
10684 // Find the previous statement in this scope so that we can close off the namepsace and start a new one.
10685 SgStatement* previousDeclarationStatement = getPreviousStatement(declarationStatement);
10686 SgStatement* nextDeclarationStatement = getNextStatement(declarationStatement);
10687
10688#if 0
10689 printf ("In SageInterface::moveDeclarationToAssociatedNamespace(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
10690 printf (" --- previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement != NULL ? previousDeclarationStatement->class_name().c_str() : "null");
10691 printf (" --- nextDeclarationStatement = %p \n",nextDeclarationStatement);
10692 printf (" --- nextDeclarationStatement = %p = %s \n",nextDeclarationStatement, nextDeclarationStatement != NULL ? nextDeclarationStatement->class_name().c_str() : "null");
10693#endif
10694
10695 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10696 if (previousDeclarationStatement != NULL)
10697 {
10698 // printf ("previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement->class_name().c_str());
10699 }
10700 else
10701 {
10702 printf ("There is no previous statement so there is no namespace to close off! \n");
10703
10704 // Handle this corner case after we have the most general case working!
10705 printf ("Exiting as a test! \n");
10706 ROSE_ABORT();
10707 }
10708
10709 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10710 if (nextDeclarationStatement != NULL)
10711 {
10712 // printf ("nextDeclarationStatement = %p = %s \n",nextDeclarationStatement,nextDeclarationStatement->class_name().c_str());
10713 }
10714 else
10715 {
10716#if 0
10717 printf ("There is no next statement so there is no namespace to reopen! \n");
10718#endif
10719#if 0
10720 // Handle this corner case after we have the most general case working!
10721 printf ("Exiting as a test! \n");
10722 ROSE_ABORT();
10723#endif
10724 }
10725
10726 if (previousDeclarationStatement != NULL && nextDeclarationStatement != NULL)
10727 {
10728 // DQ (7/19/2015): This is the most common case!
10729#if 0
10730 printf ("Identified the most common case... \n");
10731#endif
10732 // Identify the associated namespace
10733 //SgScopeStatement* declarationScope = declarationStatement->get_scope();
10734#if 0
10735 printf ("declarationScope = %p = %s \n",declarationScope,declarationScope->class_name().c_str());
10736#endif
10737#if 0
10738 // Handle this corner case after we have the most general case working!
10739 printf ("Exiting as a test! \n");
10740 ROSE_ABORT();
10741#endif
10742 }
10743 else
10744 {
10745 if (previousDeclarationStatement != NULL && nextDeclarationStatement == NULL)
10746 {
10747 // This is the case for the last template instantiaton in global scope (so it too is a common case)!
10748#if 0
10749 printf ("Found 2nd most common case: previousDeclarationStatement != NULL && nextDeclarationStatement == NULL \n");
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 printf ("This case should require no special handling, unless we are still in the wrong namespace \n");
10762
10763 // Handle this corner case after we have the most general case working!
10764 printf ("Exiting as a test! \n");
10765 ROSE_ABORT();
10766 }
10767 else
10768 {
10769 printf ("This case should have been caught above! \n");
10770
10771 // Handle this corner case after we have the most general case working!
10772 printf ("Exiting as a test! \n");
10773 ROSE_ABORT();
10774 }
10775 }
10776 }
10777
10778 SgScopeStatement* declarationParent = isSgScopeStatement(declarationStatement->get_parent());
10779 if (declarationParent == NULL)
10780 {
10781#if 0
10782 printf ("declarationStatement->get_parent() = %p = %s \n",declarationStatement->get_parent(), (declarationStatement->get_parent() != NULL) ? declarationStatement->get_parent()->class_name().c_str() : "null");
10783#endif
10784 }
10785 // This can be a SgTemplateInstantiationDirectiveStatement (bug we want to skip over this case for now).
10786 // ROSE_ASSERT(declarationParent != NULL);
10787
10788 if (declarationParent != NULL)
10789 {
10790 SgScopeStatement* declarationScope = declarationStatement->get_scope();
10791 ROSE_ASSERT(declarationScope != NULL);
10792
10793 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(declarationScope);
10794 if (namespaceDefinition != NULL)
10795 {
10796 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
10797 ROSE_ASSERT(namespaceDeclaration != NULL);
10798#if 0
10799 printf ("The declaration has been identified to be associuated with a valid namespace = %p = %s \n",namespaceDeclaration,namespaceDeclaration->get_name().str());
10800 printf (" --- declarationParent = %p = %s \n",declarationParent,declarationParent->class_name().c_str());
10801 printf (" --- Move declaration from scope = %p = %s to namespace = %p = %s \n",declarationParent,declarationParent->class_name().c_str(),namespaceDeclaration,namespaceDeclaration->get_name().str());
10802#endif
10803#if 0
10804 printf ("Exiting as a test! \n");
10805 ROSE_ABORT();
10806#endif
10807 }
10808 else
10809 {
10810#if 0
10811 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());
10812#endif
10813 }
10814 }
10815 else
10816 {
10817#if 0
10818 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");
10819#endif
10820 // ROSE_ASSERT(declarationParent != NULL);
10821 }
10822
10823 }
10824
10825
10826bool
10828 {
10829 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10830 if (isSgTemplateInstantiationDefn(node) != NULL)
10831 {
10832#if 0
10833 printf ("Note: In SageInterface::isTemplateInstantiationNode(): skipping SgTemplateInstantiationDefn \n");
10834#endif
10835 }
10836
10837 return isSgTemplateInstantiationDecl(node)
10838 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10839// || isSgTemplateInstantiationDefn(node)
10840 || isSgTemplateInstantiationDefn(node)
10841 || isSgTemplateInstantiationFunctionDecl(node)
10842 || isSgTemplateInstantiationMemberFunctionDecl(node)
10843 || isSgTemplateInstantiationTypedefDeclaration(node)
10844 || isSgTemplateInstantiationDirectiveStatement(node)
10845 ;
10846 }
10847
10848#if 0
10849// DQ (5/23/2021): Added (uncommented, and added to the header file) function to support test for template declaration.
10850// Commented back out, since this is not required for what I am debugging currently.
10851// DQ (6/27/2018): This will be the template declaration test version of the template instantiation test function above.
10852bool
10853SageInterface::isTemplateDeclarationNode(SgNode* node)
10854 {
10855 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10856 if (isSgTemplateDefinition(node) != NULL)
10857 {
10858#if 0
10859 printf ("Note: In SageInterface::isTemplateDeclarationNode(): skipping SgTemplateDefinition \n");
10860#endif
10861 }
10862
10863 return isSgTemplateInstantiationDecl(node)
10864 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10865 // || isSgTemplateInstantiationDefn(node)
10866 || isSgTemplateInstantiationDefn(node)
10867 || isSgTemplateInstantiationFunctionDecl(node)
10868 || isSgTemplateInstantiationMemberFunctionDecl(node)
10869 || isSgTemplateInstantiationTypedefDeclaration(node)
10870 || isSgTemplateInstantiationDirectiveStatement(node)
10871 ;
10872 }
10873#endif
10874
10875void
10877 {
10878 // DQ (8/18/2015): This function is called from the tests/nonsmoke/functional/testTemplates translator.
10879
10880 // DQ (7/19/2015): This function can't use an iterator since it will be
10881 // doing transformations on the AST and will cause iterator invalidation errors.
10882
10883 std::vector<SgDeclarationStatement*> templateInstantiationVector;
10884
10885 // DQ (9/24/2015): This feature is not available yet in CMake (Markus is adding the library support for this feature).
10886#ifndef USE_CMAKEx
10887 RoseAst ast(root);
10888
10889 for (RoseAst::iterator i= ast.begin(); i!= ast.end(); ++i)
10890 {
10892 {
10893 // markNodeToBeUnparsed(*i);
10894 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
10895 if (declaration != NULL)
10896 {
10897 templateInstantiationVector.push_back(declaration);
10898 }
10899 else
10900 {
10901 // I think it is OK that not all are a SgDeclarationStatement.
10902 }
10903 }
10904 }
10905#else
10906 std::cerr << "This feature for now is available with autotools only!" << std::endl;
10907 ROSE_ABORT();
10908#endif
10909
10910 std::vector<SgDeclarationStatement*>::iterator j = templateInstantiationVector.begin();
10911 while (j != templateInstantiationVector.end())
10912 {
10914 j++;
10915 }
10916 }
10917
10918
10919
10921// All SgVariantExpression in the pattern will be replaced with copies of the anchor node.
10923{
10924 SgExpression * anchor_exp = isSgExpression(anchor);
10925 SgExpression * pattern_exp = isSgExpression(new_pattern);
10926 ROSE_ASSERT (anchor_exp != NULL);
10927 ROSE_ASSERT (pattern_exp != NULL);
10928
10929 // we replace all SgExpression within the pattern with copies of anchor
10930 Rose_STL_Container<SgNode*> opaque_exp_list = NodeQuery::querySubTree(pattern_exp,V_SgExpression);
10931 for (size_t i = 0; i<opaque_exp_list.size(); i++)
10932 {
10933 SgExpression* opaque_exp = isSgExpression(opaque_exp_list[i]);
10934 ROSE_ASSERT (opaque_exp != NULL);
10935 if (opaque_exp->variantT() == V_SgVariantExpression)
10936 {
10937 SgExpression * anchor_exp_copy = deepCopy(anchor_exp);
10938 replaceExpression(opaque_exp, anchor_exp_copy);
10939 }
10940 }
10941
10942 // finally we replace anchor_exp with the pattern_exp
10943 replaceExpression(anchor_exp, pattern_exp, false);
10944 return new_pattern;
10945}
10949{
10950 //This implementation tends to generate numbers that are unnecessarily high.
10951 static int counter = 0;
10952
10953 string name;
10954 bool collision = false;
10955 do
10956 {
10957 name = "__" + baseName + boost::lexical_cast<string > (counter++) + "__";
10958
10959 // DQ (8/16/2013): Modified to reflect new API.
10960 // Look up the name in the parent scopes
10961 // SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope);
10962 SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope,NULL,NULL);
10963 collision = (nameSymbol != NULL);
10964
10965 //Look up the name in the children scopes
10966 Rose_STL_Container<SgNode*> childScopes = NodeQuery::querySubTree(scope, V_SgScopeStatement);
10967
10968 BOOST_FOREACH(SgNode* childScope, childScopes)
10969 {
10970 SgScopeStatement* childScopeStatement = isSgScopeStatement(childScope);
10971
10972 // DQ (8/16/2013): Modified to reflect new API.
10973 // nameSymbol = childScopeStatement->lookup_symbol(SgName(name));
10974 nameSymbol = childScopeStatement->lookup_symbol(SgName(name),NULL,NULL);
10975
10976 collision = collision || (nameSymbol != NULL);
10977 }
10978 } while (collision);
10979
10980 return name;
10981}
10982
10983
10984std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableForExpression
10985(SgExpression* expression, SgScopeStatement* scope, bool initializeInDeclaration, SgAssignOp** reEvaluate)
10986{
10987 SgType* expressionType = expression->get_type();
10988 SgType* variableType = expressionType;
10989
10990 //If the expression has a reference type, we need to use a pointer type for the temporary variable.
10991 //Else, re-assigning the variable is not possible
10992 bool isReferenceType = SageInterface::isReferenceType(expressionType);
10993 if (isReferenceType)
10994 {
10995 SgType* expressionBaseType = expressionType->stripType(SgType::STRIP_TYPEDEF_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE);
10996 variableType = SageBuilder::buildPointerType(expressionBaseType);
10997 }
10998
10999 //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.
11000 if (SgArrayType* arrayType=isSgArrayType(expressionType)) {
11001 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
11002 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
11003 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
11004 }
11005 }
11006
11007 // If the expression is a dereferenced pointer, use a reference to hold it.
11008 if (isSgPointerDerefExp(expression))
11009 variableType = SageBuilder::buildReferenceType(variableType);
11010
11011 //Generate a unique variable name
11012 string name = generateUniqueVariableName(scope);
11013
11014 //Initialize the temporary variable to an evaluation of the expression
11015 SgExpression* tempVarInitExpression = SageInterface::copyExpression(expression);
11016 ROSE_ASSERT(tempVarInitExpression != NULL);
11017 if (isReferenceType)
11018 {
11019 //FIXME: the next line is hiding a bug in ROSE. Remove this line and talk to Dan about the resulting assert
11020 tempVarInitExpression->set_lvalue(false);
11021
11022 tempVarInitExpression = SageBuilder::buildAddressOfOp(tempVarInitExpression);
11023 }
11024
11025 //Optionally initialize the variable in its declaration
11026 SgAssignInitializer* initializer = NULL;
11027 if (initializeInDeclaration)
11028 {
11029 SgExpression* initExpressionCopy = SageInterface::copyExpression(tempVarInitExpression);
11030 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11031 }
11032
11033 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11034 ROSE_ASSERT(tempVarDeclaration != NULL);
11035
11036 //Now create the assignment op for reevaluating the expression
11037 if (reEvaluate != NULL)
11038 {
11039 SgVarRefExp* tempVarReference = SageBuilder::buildVarRefExp(tempVarDeclaration);
11040 *reEvaluate = SageBuilder::buildAssignOp(tempVarReference, tempVarInitExpression);
11041 }
11042
11043 //Build the variable reference expression that can be used in place of the original expression
11044 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11045 if (isReferenceType)
11046 {
11047 //The temp variable is a pointer type, so dereference it before using it
11048 varRefExpression = SageBuilder::buildPointerDerefExp(varRefExpression);
11049 }
11050
11051 return std::make_pair(tempVarDeclaration, varRefExpression);
11052}
11053
11054// This function creates a temporary variable for a given expression in the given scope
11055// This is different from SageInterface::createTempVariableForExpression in that it does not
11056// try to be smart to create pointers to reference types and so on. The tempt is initialized to expression.
11057// The caller is responsible for setting the parent of SgVariableDeclaration since buildVariableDeclaration
11058// may not set_parent() when the scope stack is empty. See programTransformation/extractFunctionArgumentsNormalization/ExtractFunctionArguments.C for sample usage.
11059
11060std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableAndReferenceForExpression
11061(SgExpression* expression, SgScopeStatement* scope)
11062{
11063 SgType* expressionType = expression->get_type();
11064 SgType* variableType = expressionType;
11065
11066 //MS 10/24/2018: If the expression has array type, we need to use a pointer type for the temporary variable.
11067 if (SgArrayType* arrayType=isSgArrayType(expressionType))
11068 {
11069 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
11070 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
11071 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
11072 }
11073 }
11074
11075 //Generate a unique variable name
11076 string name = generateUniqueVariableName(scope);
11077
11078 //initialize the variable in its declaration
11079 SgAssignInitializer* initializer = NULL;
11080 SgExpression* initExpressionCopy = SageInterface::copyExpression(expression);
11081 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11082
11083 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11084 ROSE_ASSERT(tempVarDeclaration != NULL);
11085
11086 //Build the variable reference expression that can be used in place of the original expression
11087 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11088 return std::make_pair(tempVarDeclaration, varRefExpression);
11089}
11090
11091
11092namespace
11093{
11094 void
11095 replaceExpressionInSgExpressionPtrList(SgExpression* oldExp, SgExpression* newExp, SgExpressionPtrList& lst, bool replAll = false)
11096 {
11097 SgExpressionPtrList::iterator lim = lst.end();
11098 SgExpressionPtrList::iterator pos = lst.begin();
11099 bool chg = false;
11100
11101 do
11102 {
11103 pos = std::find(pos, lim, oldExp);
11104
11105 if (pos != lim) { *pos = newExp; ++pos; chg = true; }
11106 } while (replAll && (pos != lim));
11107
11108 ROSE_ASSERT(chg);
11109 }
11110}
11111
11112// This code is based on OpenMP translator's ASTtools::replaceVarRefExp() and astInling's replaceExpressionWithExpression()
11113// Motivation: It involves the parent node to replace a VarRefExp with a new node
11114// Used to replace shared variables with the dereference expression of their addresses
11115// e.g. to replace shared1 with (*__pp_shared1)
11116
11117void SageInterface::replaceExpression(SgExpression* oldExp, SgExpression* newExp, bool keepOldExp/*=false*/) {
11118 SgExpression* parentExp;
11119
11120 ROSE_ASSERT(oldExp);
11121 ROSE_ASSERT(newExp);
11122 if (oldExp==newExp) return;
11123
11124 if (isSgVarRefExp(newExp))
11125 newExp->set_need_paren(true); // enclosing new expression with () to be safe
11126
11127 SgNode* parent = oldExp->get_parent();
11128 ROSE_ASSERT(parent!=NULL);
11129 newExp->set_parent(parent);
11130
11131 // set lvalue when necessary
11132 if (oldExp->get_lvalue() == true) newExp->set_lvalue(true);
11133
11134 if (isSgExprStatement(parent)) {
11135 isSgExprStatement(parent)->set_expression(newExp);
11136 } else if (isSgForStatement(parent)) {
11137 ROSE_ASSERT (isSgForStatement(parent)->get_increment() == oldExp);
11138 isSgForStatement(parent)->set_increment(newExp);
11139 // TODO: any other cases here??
11140 } else if(SgMatlabForStatement *matlabFor = isSgMatlabForStatement(parent)) {
11141 if(matlabFor->get_index() == oldExp)
11142 matlabFor->set_index(newExp);
11143 else if(matlabFor->get_range() == oldExp)
11144 matlabFor->set_range(newExp);
11145 else
11146 ROSE_ASSERT(!"sub-expression not found");
11147 } else if(SgJovialForThenStatement *jovFor = isSgJovialForThenStatement(parent)) {
11148 if(jovFor->get_initialization() == oldExp)
11149 jovFor->set_initialization(newExp);
11150 else if(jovFor->get_while_expression() == oldExp)
11151 jovFor->set_while_expression(newExp);
11152 else if(jovFor->get_by_or_then_expression() == oldExp)
11153 jovFor->set_by_or_then_expression(newExp);
11154 else
11155 ROSE_ASSERT(!"sub-expression not found");
11156 } else if (SgRangeExp* rngexp = isSgRangeExp(parent)) {
11157 if (rngexp->get_start() == oldExp)
11158 rngexp->set_start(newExp);
11159 else if (rngexp->get_end() == oldExp)
11160 rngexp->set_end(newExp);
11161 else if (rngexp->get_stride() == oldExp)
11162 rngexp->set_stride(newExp);
11163 else
11164 ROSE_ASSERT(!"sub-expression not found");
11165 } else if (isSgReturnStmt(parent)) {
11166 isSgReturnStmt(parent)->set_expression(newExp);
11167 } else if (isSgBinaryOp(parent)!=NULL) {
11168 if (oldExp==isSgBinaryOp(parent)->get_lhs_operand()) {
11169 isSgBinaryOp(parent)->set_lhs_operand(newExp);
11170 } else if (oldExp==isSgBinaryOp(parent)->get_rhs_operand()) {
11171 isSgBinaryOp(parent)->set_rhs_operand(newExp);
11172 } else {
11173 ROSE_ABORT();
11174 }
11175 } else if (isSgUnaryOp(parent)!=NULL){
11176 if (oldExp==isSgUnaryOp(parent)->get_operand_i())
11177 isSgUnaryOp(parent)->set_operand_i(newExp);
11178 else
11179 ROSE_ABORT();
11180 } else if (isSgConditionalExp(parent) != NULL) {
11181 SgConditionalExp* expparent = isSgConditionalExp(parent); //get explicity type parent
11182 if (oldExp==expparent->get_conditional_exp())
11183 expparent->set_conditional_exp(newExp);
11184 else if (oldExp==expparent->get_true_exp())
11185 expparent->set_true_exp(newExp);
11186 else if (oldExp==expparent->get_false_exp())
11187 expparent->set_false_exp(newExp);
11188 else
11189 ROSE_ABORT();
11190 } else if (isSgExprListExp(parent) != NULL) {
11191 SgExpressionPtrList& explist = isSgExprListExp(parent)->get_expressions();
11192 for (Rose_STL_Container<SgExpression*>::iterator i=explist.begin();i!=explist.end();i++) {
11193 if (isSgExpression(*i)==oldExp) {
11194 SgExprListExp* parentExpListExp = isSgExprListExp(parent);
11195 parentExpListExp->replace_expression(oldExp,newExp);
11196 // break; //replace the first occurrence only??
11197 }
11198 }
11199 } else if (isSgValueExp(parent)) {
11200 // For compiler generated code, this could happen.
11201 // We can just ignore this function call since it will not appear in the final AST.
11202 return;
11203 } else if (SgActualArgumentExpression* actexp = isSgActualArgumentExpression(parent)) {
11204 ROSE_ASSERT(oldExp == actexp->get_expression());
11205 actexp->set_expression(newExp);
11206 } else if (SgAdaAttributeExp* attrexp = isSgAdaAttributeExp(parent)) {
11207 if (oldExp == attrexp->get_object()) {
11208 attrexp->set_object(newExp);
11209 } else if (oldExp == attrexp->get_args()) {
11210 SgExprListExp* newLst = isSgExprListExp(newExp);
11211 ASSERT_not_null(newLst);
11212
11213 attrexp->set_args(newLst);
11214 } else {
11215 ROSE_ABORT();
11216 }
11217 /**** ALL expressions must be handled before the next line *****/
11218 } else if ((parentExp=isSgExpression(parent)) != NULL) {
11219 int worked = parentExp->replace_expression(oldExp, newExp);
11220 // ROSE_DEPRECATED_FUNCTION
11221 ROSE_ASSERT (worked);
11222 } else if (isSgInitializedName(parent)) {
11223 SgInitializedName* initializedNameParent = isSgInitializedName(parent);
11224 if (oldExp == initializedNameParent->get_initializer()) {
11225 //We can only replace an initializer expression with another initializer expression
11226 ROSE_ASSERT(isSgInitializer(newExp));
11227 initializedNameParent->set_initializer(isSgInitializer(newExp));
11228 } else {
11229 //What other expressions can be children of an SgInitializedname?
11230 ROSE_ABORT();
11231 }
11232 } else if (isSgCaseOptionStmt(parent)) {
11233 SgCaseOptionStmt * case_stmt = isSgCaseOptionStmt(parent);
11234 if (oldExp == case_stmt->get_key()) {
11235 case_stmt->set_key(newExp);
11236 } else if(oldExp == case_stmt->get_key_range_end()) {
11237 case_stmt->set_key_range_end(newExp);
11238 } else {
11239 ROSE_ABORT();
11240 }
11241 } else if (isSgProcessControlStatement(parent)) {
11243 if (oldExp == ctrl_stmt->get_quiet()) {
11244 ctrl_stmt->set_quiet(newExp);
11245 } else if (oldExp == ctrl_stmt->get_code()) {
11246 ctrl_stmt->set_code(newExp);
11247 } else {
11248 ROSE_ABORT();
11249 }
11250 } else if (isSgFortranDo(parent)) {
11251 SgFortranDo* fortranDo = isSgFortranDo(parent);
11252 if (oldExp == fortranDo->get_initialization()) {
11253 fortranDo->set_initialization(newExp);
11254 } else if(oldExp == fortranDo->get_bound()) {
11255 fortranDo->set_bound(newExp);
11256 } else if (oldExp == fortranDo->get_increment()) {
11257 fortranDo->set_increment(newExp);
11258 } else {
11259 ROSE_ABORT();
11260 }
11261 }
11262 else if (SgAdaExitStmt* stm = isSgAdaExitStmt(parent)) {
11263 ROSE_ASSERT(oldExp == stm->get_condition());
11264 stm->set_condition(newExp);
11265 }
11266 else if (SgAdaModularType* ptype = isSgAdaModularType(parent)) {
11267 ROSE_ASSERT(oldExp == ptype->get_modexpr());
11268 ptype->set_modexpr(newExp);
11269 }
11270 else if (SgAdaDelayStmt* stm = isSgAdaDelayStmt(parent)) {
11271 ROSE_ASSERT(oldExp == stm->get_time());
11272 stm->set_time(newExp);
11273 } else if (SgAdaAttributeClause* clause = isSgAdaAttributeClause(parent)) {
11274 ROSE_ASSERT(oldExp == clause->get_size());
11275 clause->set_size(newExp);
11276 } else if (SgAdaRenamingDecl* dcl = isSgAdaRenamingDecl(parent)) {
11277 ROSE_ASSERT(oldExp == dcl->get_renamed());
11278 dcl->set_renamed(newExp);
11279 } else if (SgAdaEntryDecl* dcl = isSgAdaEntryDecl(parent)) {
11280 ROSE_ASSERT(oldExp == dcl->get_entryBarrier());
11281 dcl->set_entryBarrier(newExp);
11282 } else if (SgAdaSelectAlternativeStmt* stm = isSgAdaSelectAlternativeStmt(parent)) {
11283 ROSE_ASSERT(oldExp == stm->get_guard());
11284 stm->set_guard(newExp);
11285 } else if (SgAdaDeltaConstraint* delc = isSgAdaDeltaConstraint(parent)) {
11286 ROSE_ASSERT(oldExp == delc->get_delta());
11287 delc->set_delta(newExp);
11288 } else if (SgAdaDigitsConstraint* digc = isSgAdaDigitsConstraint(parent)) {
11289 ROSE_ASSERT(oldExp == digc->get_digits());
11290 digc->set_digits(newExp);
11291 } else if (SgAdaDiscriminantConstraint* disc = isSgAdaDiscriminantConstraint(parent)) {
11292 replaceExpressionInSgExpressionPtrList(oldExp, newExp, disc->get_discriminants());
11293 } else if (SgAdaRangeConstraint* rngc = isSgAdaRangeConstraint(parent)) {
11294 ROSE_ASSERT(oldExp == rngc->get_range());
11295 rngc->set_range(newExp);
11296 } else if (SgAdaIndexConstraint* idxc = isSgAdaIndexConstraint(parent)) {
11297 replaceExpressionInSgExpressionPtrList(oldExp, newExp, idxc->get_indexRanges());
11298 } else if (SgAdaVariantDecl* vtdcl = isSgAdaVariantDecl(parent)) {
11299 ROSE_ASSERT(oldExp == vtdcl->get_discriminant());
11300 vtdcl->set_discriminant(newExp);
11301 } else if (SgAdaRepresentationClause* clause = isSgAdaRepresentationClause(parent)) {
11302 ROSE_ASSERT(oldExp == clause->get_alignment());
11303 clause->set_alignment(newExp);
11304 } else if (SgAdaVariantWhenStmt* vtwhen = isSgAdaVariantWhenStmt(parent)) {
11305 SgExprListExp* newLst = isSgExprListExp(newExp);
11306 if (newLst && (oldExp == vtwhen->get_choices()))
11307 vtwhen->set_choices(newLst);
11308 else
11309 ROSE_ABORT();
11310 } else if (SgAdaComponentClause* clause = isSgAdaComponentClause(parent)) {
11311 if (oldExp == clause->get_offset())
11312 clause->set_offset(newExp);
11313 else if (oldExp == clause->get_range() && isSgRangeExp(newExp))
11314 clause->set_range(isSgRangeExp(newExp));
11315 else if (oldExp == clause->get_component() && isSgVarRefExp(newExp))
11316 clause->set_component(isSgVarRefExp(newExp));
11317 else
11318 ROSE_ABORT();
11319 } else if (SgAdaFunctionRenamingDecl* rendcl = isSgAdaFunctionRenamingDecl(oldExp->get_parent())) {
11320 if (oldExp == rendcl->get_renamed_function())
11321 rendcl->set_renamed_function(newExp);
11322 else
11323 ROSE_ABORT();
11324 } else {
11325 cerr<<"SageInterface::replaceExpression(). Unhandled parent expression type of SageIII enum value: " <<parent->class_name()<<endl;
11326 ROSE_ABORT();
11327 }
11328
11329 if (!keepOldExp) {
11330 deepDelete(oldExp); // avoid dangling node in memory pool
11331 } else {
11332 oldExp->set_parent(NULL);
11333 }
11334
11335} //replaceExpression()
11336
11338 {
11339 // reuse the implementation in ROSE namespace from src/roseSupport/utility_functions.C
11340 return Rose::getNextStatement(currentStmt);
11341 }
11342
11343SgStatement* SageInterface::getPreviousStatement(SgStatement * currentStmt, bool climbOutScope /*= true*/)
11344 {
11345 return Rose::getPreviousStatement(currentStmt, climbOutScope);
11346 }
11347
11349 return isSgIntVal(e) && isSgIntVal(e)->get_value() == value;
11350 }
11351
11353 {
11354 ROSE_ASSERT(func1&& func2);
11355 bool result = false;
11356 if (func1 == func2)
11357 result = true;
11358 else
11359 {
11361 {
11362 if (func1->get_name() == func2->get_name())
11363 result = true;
11364 }
11365 else if (is_Cxx_language() || is_Java_language())
11366 {
11367 if (func1->get_qualified_name().getString() +
11368 func1->get_mangled_name().getString() ==
11369 func2->get_qualified_name().getString() +
11370 func2->get_mangled_name().getString()
11371 )
11372 result = true;
11373 }
11374 else if (is_Fortran_language())
11375 {
11376 if (func1->get_name() == func2->get_name())
11377 result = true;
11378 }
11379 else
11380 {
11381 cout<<"Error: SageInterface::isSameFunction(): unhandled language"<<endl;
11382 ROSE_ABORT();
11383 }
11384
11385 } // not identical
11386 return result;
11387 } // isSameFunction()
11388
11391{
11392 bool result =false;
11393 ROSE_ASSERT(stmt != NULL);
11394 SgScopeStatement* p_scope = stmt->get_scope();
11395 ROSE_ASSERT(p_scope != NULL);
11396#if 0
11397 if (p_scope->containsOnlyDeclarations())
11398 {
11399 SgDeclarationStatementPtrList stmtlist= p_scope->getDeclarationList ()
11400 if (stmtlist[stmtlist.size()-1] == stmt)
11401 result = true;
11402 }
11403 else
11404 {
11405 SgStatementPtrList stmtlist= p_scope->getStatementList ();
11406 if (stmtlist[stmtlist.size()-1] == stmt)
11407 result = true;
11408 }
11409#endif
11410 SgStatementPtrList stmtlist= p_scope->generateStatementList ();
11411 if (stmtlist[stmtlist.size()-1] == stmt)
11412 result = true;
11413
11414 return result;
11415}
11416
11417#ifndef USE_ROSE
11418//-----------------------------------------------
11419// Remove original expression trees from expressions, so you can change
11420// the value and have it unparsed correctly.
11422 struct Visitor: public AstSimpleProcessing {
11423 virtual void visit(SgNode* n) {
11424 SgValueExp* valueExp = isSgValueExp(n);
11425 if (valueExp != NULL) {
11426 valueExp->set_originalExpressionTree(NULL);
11427 }
11428 else {
11429 SgCastExp* cast_exp = isSgCastExp(n);
11430 if (cast_exp != NULL) {
11431 cast_exp->set_originalExpressionTree(NULL);
11432 }
11433 }
11434 }
11435 };
11436 Visitor().traverse(top, preorder);
11437}
11438#endif
11439
11441 while (s && !isSgSwitchStatement(s)) {
11442 s = isSgStatement(s->get_parent());
11443 }
11444 ROSE_ASSERT (s);
11445 return isSgSwitchStatement(s);
11446}
11447
11450 while (s && !isSgOmpClauseBodyStatement(s)) {
11451 s = isSgStatement(s->get_parent());
11452 }
11453 // ROSE_ASSERT (s); // s is allowed to be NULL.
11454 if (s==NULL)
11455 return NULL;
11456 return isSgOmpClauseBodyStatement(s);
11457}
11458
11459
11460SgScopeStatement* SageInterface::findEnclosingLoop(SgStatement* s, const std::string& label, bool stopOnSwitches) {
11461 /* label can represent a fortran label or a java label provided as a label in a continue/break statement */
11462 for (; s; s = isSgStatement(s->get_parent())) {
11463 SgScopeStatement* sc = isSgScopeStatement(s);
11464 // Need to check for empty label as for java we must detect the
11465 // innermost labeled statement and skip everything in between
11466 switch (s->variantT()) {
11467 case V_SgDoWhileStmt: {
11468 if (label.empty()) {
11469 return sc;
11470 }
11471 break;
11472 }
11473 case V_SgForStatement: {
11474 if (label.empty()) {
11475 return sc;
11476 }
11477 break;
11478 }
11479 case V_SgFortranDo:
11480 case V_SgFortranNonblockedDo: {
11481 if (label.empty() ||
11482 label == isSgFortranDo(sc)->get_string_label()) {
11483 return sc;
11484 }
11485 break;
11486 }
11487 case V_SgWhileStmt: {
11488 if (label.empty() ||
11489 label == isSgWhileStmt(sc)->get_string_label()) {
11490 return sc;
11491 }
11492 break;
11493 }
11494 case V_SgSwitchStatement: {
11495 if (stopOnSwitches) return sc;
11496 break;
11497 }
11498 case V_SgJavaForEachStatement: {
11499 if (label.empty()) {
11500 return sc;
11501 }
11502 break;
11503 }
11504 case V_SgJavaLabelStatement: {
11505 if (label.empty() ||
11506 label == isSgJavaLabelStatement(sc)->get_label().getString()) {
11507 return sc;
11508 }
11509 break;
11510 }
11511 default: continue;
11512 }
11513 }
11514 return NULL;
11515}
11516
11517#ifndef USE_ROSE
11519{
11520 class RemoveJumpsToNextStatementVisitor: public AstSimpleProcessing {
11521 public:
11522 virtual void visit(SgNode* n) {
11523 if (isSgBasicBlock(n)) {
11524 SgBasicBlock* bb = isSgBasicBlock(n);
11525 bool changes = true;
11526 while (changes) {
11527 changes = false;
11528 for (SgStatementPtrList::iterator i = bb->get_statements().begin();
11529 i != bb->get_statements().end(); ++i) {
11530 if (isSgGotoStatement(*i)) {
11531 SgGotoStatement* gs = isSgGotoStatement(*i);
11532 SgStatementPtrList::iterator inext = i;
11533 ++inext;
11534 if (inext == bb->get_statements().end())
11535 continue;
11536 if (!isSgLabelStatement(*inext))
11537 continue;
11538 SgLabelStatement* ls = isSgLabelStatement(*inext);
11539 if (gs->get_label() == ls) {
11540 changes = true;
11541 bb->get_statements().erase(i);
11542 break;
11543 }
11544 }
11545 }
11546 }
11547 }
11548 }
11549 };
11550
11551 RemoveJumpsToNextStatementVisitor().traverse(top, postorder);
11552
11553}
11554#endif
11555
11556// special purpose remove for AST transformation/optimization from astInliner, don't use it otherwise.
11558 // assert (LowLevelRewrite::isRemovableStatement(*i));
11559 SgStatement* parent = isSgStatement(stmt->get_parent());
11560 ROSE_ASSERT (parent);
11561 SgBasicBlock* bb = isSgBasicBlock(parent);
11562 SgForInitStatement* fis = isSgForInitStatement(parent);
11563 if (bb || fis) {
11564 ROSE_ASSERT (bb || fis);
11565 SgStatementPtrList& siblings =
11566 (bb ? bb->get_statements() : fis->get_init_stmt());
11567 SgStatementPtrList::iterator j =
11568 std::find(siblings.begin(), siblings.end(), stmt);
11569 ROSE_ASSERT (j != siblings.end());
11570 siblings.erase(j);
11571 // LowLevelRewrite::remove(*i);
11572 } else {
11573 parent->replace_statement(stmt, new SgNullStatement(TRANS_FILE));
11574 }
11575}
11576
11577
11578#ifndef USE_ROSE
11579std::set<SgLabelStatement*> SageInterface::findUnusedLabels (SgNode* top)
11580{
11581 class FindUsedAndAllLabelsVisitor: public AstSimpleProcessing {
11582 SgLabelStatementPtrSet& used;
11583 SgLabelStatementPtrSet& all;
11584
11585 public:
11586 FindUsedAndAllLabelsVisitor(SgLabelStatementPtrSet& used,
11587 SgLabelStatementPtrSet& all):
11588 used(used), all(all) {}
11589
11590 virtual void visit(SgNode* n) {
11591 if (isSgGotoStatement(n)) {
11592 used.insert(isSgGotoStatement(n)->get_label());
11593 }
11594 if (isSgLabelStatement(n)) {
11595 all.insert(isSgLabelStatement(n));
11596 }
11597 }
11598 };
11599
11600 SgLabelStatementPtrSet used;
11601 SgLabelStatementPtrSet unused;
11602 FindUsedAndAllLabelsVisitor(used, unused).traverse(top, preorder);
11603
11604 for (SgLabelStatementPtrSet::iterator i = used.begin();
11605 i != used.end(); ++i) {
11606 assert (unused.find(*i) != unused.end());
11607 // std::cout << "Keeping used label " << (*i)->get_label().str() << std::endl;
11608 unused.erase(*i);
11609 }
11610
11611 return unused;
11612}
11613
11614// Remove all unused labels in a section of code.
11615void SageInterface::removeUnusedLabels(SgNode* top, bool keepChild/* =false */) {
11616
11617 SgLabelStatementPtrSet unused = findUnusedLabels(top);
11618
11619 for (SgLabelStatementPtrSet::iterator i = unused.begin();
11620 i != unused.end(); ++i) {
11621
11622 SgLabelStatement* l_stmt = *i;
11623 // std::cout << "Removing unused label " << (*i)->get_label().str() << std::endl;
11624 if (keepChild)
11625 {
11626 SgStatement* child= l_stmt->get_statement();
11627// l_stmt->set_parent(NULL);
11628 l_stmt->set_statement(NULL);
11629 replaceStatement (l_stmt, child);
11630 }
11631 else
11633 }
11634}
11635#endif
11636
11638 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_body();
11639 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_loop_body();
11640 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_body();
11641
11642 ROSE_ASSERT (!"Bad loop kind");
11643 return NULL;
11644 }
11645
11647 if (isSgWhileStmt(loopStmt)) {
11648 isSgWhileStmt(loopStmt)->set_body(body);
11649 } else if (isSgForStatement(loopStmt)) {
11650 isSgForStatement(loopStmt)->set_loop_body(body);
11651 } else if (isSgDoWhileStmt(loopStmt)) {
11652 isSgDoWhileStmt(loopStmt)->set_body(body);
11653 } else {
11654 ROSE_ASSERT (!"Bad loop kind");
11655 }
11656 body->set_parent(loopStmt);
11657 }
11658
11660 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_condition();
11661 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_test();
11662 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_condition();
11663
11664 ROSE_ASSERT (!"Bad loop kind");
11665 return NULL;
11666 }
11667
11669 if (isSgWhileStmt(loopStmt)) {
11670 isSgWhileStmt(loopStmt)->set_condition(cond);
11671 } else if (isSgForStatement(loopStmt)) {
11672 isSgForStatement(loopStmt)->set_test(cond);
11673 } else if (isSgDoWhileStmt(loopStmt)) {
11674 isSgDoWhileStmt(loopStmt)->set_condition(cond);
11675 } else {
11676 ROSE_ASSERT (!"Bad loop kind");
11677 }
11678 cond->set_parent(loopStmt);
11679 }
11680
11682// usually useful when compare two expressions to see if they actually refer to the same variable
11683static SgExpression* SkipCasting (SgExpression* exp)
11684{
11685 SgCastExp* cast_exp = isSgCastExp(exp);
11686 if (cast_exp != NULL)
11687 {
11688 SgExpression* operand = cast_exp->get_operand();
11689 assert(operand != 0);
11690 return SkipCasting(operand);
11691 }
11692 else
11693 return exp;
11694}
11695
11698{
11699 ROSE_ASSERT(loop!=NULL);
11700
11701 SgStatementPtrList &init = loop ->get_init_stmt();
11702 if (init.size() !=1) // We only handle one statement case
11703 return false;
11704
11705 SgStatement* init1 = init.front();
11706 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
11707 if (decl == NULL) // we only handle for (int i=0; ...)
11708 return true; // the return value is ambiguous: if not int i=0; it is already normalized
11709
11710 SgVariableSymbol* osymbol = getFirstVarSym(decl);
11711 SgInitializedName* ivarname = decl->get_variables().front();
11712 SgExpression* lbast = NULL; // the lower bound, initial state
11713 ROSE_ASSERT(ivarname != NULL);
11714 SgInitializer * initor = ivarname->get_initializer();
11715 if (isSgAssignInitializer(initor))
11716 {
11717 lbast = isSgAssignInitializer(initor)->get_operand();
11718 }
11719 else
11720 { //SgConstructorInitializer etc.
11721 // other complex declaration statements, such as Decomposition::Iterator ditr(&decomp) should be skipped
11722 // they cause a loop to be non-canonical.
11723 return false;
11724 }
11725
11726 // add a new statement like int i; and insert it to the enclosing function
11727 // There are multiple choices about where to insert this statement:
11728 // global scope: max name pollution,
11729 // right before the loop: mess up perfectly nested loops
11730 // So we prepend the statement to the enclosing function's body
11732 ROSE_ASSERT(funcDef!=NULL);
11733 SgBasicBlock* funcBody = funcDef->get_body();
11734 ROSE_ASSERT(funcBody!=NULL);
11735 //TODO a better name
11736 std::ostringstream os;
11737 os<<ivarname->get_name().getString();
11738
11739 // keep the original variable name if possible
11740 SgSymbol * visibleSym = NULL;
11741 visibleSym = lookupVariableSymbolInParentScopes(ivarname->get_name(), funcBody);
11742 if (visibleSym != NULL) // if there is a name collision, add suffix to the variable name
11743 {
11744 os<<"_nom_";
11745 os<<++gensym_counter;
11746 }
11747
11748 SgVariableDeclaration* ndecl = buildVariableDeclaration(os.str(),ivarname->get_type(), NULL, funcBody);
11749 prependStatement(ndecl, funcBody);
11750 SgVariableSymbol* nsymbol = getFirstVarSym(ndecl);
11751
11752 // replace variable ref to the new symbol
11753 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11754 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11755 {
11756 SgVarRefExp *vRef = isSgVarRefExp((*i));
11757 if (vRef->get_symbol()==osymbol)
11758 vRef->set_symbol(nsymbol);
11759 }
11760 // replace for (int i=0;) with for (i=0;)
11762 removeStatement(decl); //any side effect to the symbol? put after symbol replacement anyway
11763 init.push_back(ninit);
11764 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11765 // ninit->set_parent(loop);
11766 ninit->set_parent(loop->get_for_init_stmt ());
11767
11768 // keep record of this normalization
11769 // We may undo it later on.
11770 trans_records.forLoopInitNormalizationTable[loop] = true;
11771 trans_records.forLoopInitNormalizationRecord[loop] = make_pair (decl, ndecl) ;
11772
11773 return true;
11774}
11775
11776/*
11777 int i_norm_1;
11778 for (i_norm_1=0; i_norm_1<upper; i_norm_1 ++ );
11779Becomes:
11780 for (int i=0; i< upper; i++) ;
11781 * */
11783{
11784 ROSE_ASSERT (loop != NULL);
11785 //If not previously normalized, nothing to do and return false.
11786 if (!trans_records.forLoopInitNormalizationTable[loop])
11787 return false;
11788 // retrieve original and new declaration of the previous normalization
11789 SgVariableDeclaration* decl = trans_records.forLoopInitNormalizationRecord[loop].first;
11790 SgVariableDeclaration* ndecl = trans_records.forLoopInitNormalizationRecord[loop].second;
11791 ROSE_ASSERT (decl!= NULL);
11792 ROSE_ASSERT (ndecl!= NULL);
11793
11794
11795 // Sanity check
11796 SgStatementPtrList &init = loop ->get_init_stmt();
11797 ROSE_ASSERT(init.size() ==1); // We only handle one statement case
11798
11799 // remove the current init_stmt
11800 SgStatement* init1 = init.front();
11801 SgExprStatement* exp_stmt = isSgExprStatement(init1);
11802 ROSE_ASSERT (exp_stmt != NULL);
11803 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
11804 ROSE_ASSERT (assign_op != NULL);
11805
11806 // remove the new declaration and the current i_norm=1;
11807 removeStatement(ndecl);
11808 removeStatement (exp_stmt);
11809
11810 // restore the original declaration
11811 init.push_back(decl);
11812 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11813 // ninit->set_parent(loop);
11814 decl->set_parent(loop->get_for_init_stmt ());
11815
11816 // replace variable references
11817 // current symbol in the AST
11818 SgVariableSymbol* osymbol = getFirstVarSym(ndecl);
11819 // new symbol we want to have: the original decl
11820 SgVariableSymbol* nsymbol = getFirstVarSym(decl);
11821 // replace variable ref to the new symbol
11822 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11823 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11824 {
11825 SgVarRefExp *vRef = isSgVarRefExp((*i));
11826 if (vRef->get_symbol()==osymbol)
11827 vRef->set_symbol(nsymbol);
11828 }
11829
11830 // clear record: now the loop is not normalized any more
11831 trans_records.forLoopInitNormalizationTable[loop] = false;
11832 return true;
11833}
11834
11836{
11837 ROSE_ASSERT(loop != NULL);
11838
11839 // Normalized the test expressions
11840 // -------------------------------------
11841#if 0 // this is undecided
11842 // skip for (;;) case
11843 SgStatement* test_stmt = loop->get_test();
11844 if (test_stmt!=NULL)
11845 {
11846 if (isSgNullStatement(test_stmt))
11847 return false;
11848 }
11849#endif
11850 SgExpression* test = loop->get_test_expr();
11851 SgExpression* testlhs=NULL, * testrhs=NULL;
11852 if (isSgBinaryOp(test))
11853 {
11854 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11855 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11856 ROSE_ASSERT(testlhs && testrhs);
11857 }
11858 else
11859 return false;
11860 // keep the variable since test will be removed later on
11861 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11862 if (testlhs_var == NULL )
11863 return false;
11864 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11865 if (var_symbol==NULL)
11866 return false;
11867
11868 switch (test->variantT()) {
11869 case V_SgLessThanOp: // i<x is normalized to i<= (x-1)
11871 buildSubtractOp(deepCopy(testrhs), buildIntVal(1))));
11872 // deepDelete(test);// replaceExpression() does this already by default.
11873 break;
11874 case V_SgGreaterThanOp: // i>x is normalized to i>= (x+1)
11876 buildAddOp(deepCopy(testrhs), buildIntVal(1))));
11877 break;
11878 case V_SgLessOrEqualOp:
11879 case V_SgGreaterOrEqualOp:
11880 case V_SgNotEqualOp: //TODO Do we want to allow this?
11881 break;
11882 default:
11883 return false;
11884 }
11885 return true;
11886}
11888{
11889 ROSE_ASSERT(loop != NULL);
11890
11891 SgExpression* test = loop->get_test_expr();
11892 SgExpression* testlhs=NULL, * testrhs=NULL;
11893 if (isSgBinaryOp(test))
11894 {
11895 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11896 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11897 ROSE_ASSERT(testlhs && testrhs);
11898 }
11899 else
11900 return false;
11901 // keep the variable since test will be removed later on
11902 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11903 if (testlhs_var == NULL )
11904 return false;
11905 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11906 if (var_symbol==NULL)
11907 return false;
11908
11909
11910 // -------------------------------------
11911 SgExpression* incr = loop->get_increment();
11912 ROSE_ASSERT(incr != NULL);
11913 switch (incr->variantT()) {
11914 case V_SgPlusPlusOp: //i++ is normalized to i+=1
11915 {
11916 // check if the variables match
11917 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgPlusPlusOp(incr)->get_operand()));
11918 if (incr_var == NULL) return false;
11919 if ( incr_var->get_symbol() != var_symbol)
11920 return false;
11921 replaceExpression(incr,
11922 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)),buildIntVal(1)));
11923 break;
11924 }
11925 case V_SgMinusMinusOp: //i-- is normalized to i+=-1
11926 {
11927 // check if the variables match
11928 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusMinusOp(incr)->get_operand()));
11929 if (incr_var == NULL) return false;
11930 if ( incr_var->get_symbol() != var_symbol)
11931 return false;
11932 replaceExpression(incr,
11933 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildIntVal(-1)));
11934 break;
11935 }
11936 case V_SgMinusAssignOp: // i-= s is normalized to i+= -s
11937 {
11938 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusAssignOp(incr)->get_lhs_operand()));
11939 SgExpression* rhs = isSgMinusAssignOp(incr)->get_rhs_operand();
11940 ROSE_ASSERT (rhs != NULL);
11941 if (incr_var == NULL) return false;
11942 if ( incr_var->get_symbol() != var_symbol)
11943 return false;
11944 replaceExpression(incr,
11945 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildMultiplyOp(buildIntVal(-1), copyExpression(rhs))));
11946 break;
11947 }
11948 case V_SgAssignOp:
11949 case V_SgPlusAssignOp:
11950 break;
11951 default:
11952 return false;
11953 }
11954
11955 return true;
11956}
11958// Her loop translation does not pass AST consistency tests so we rewrite some of them here
11959// NormalizeCPP.C NormalizeLoopTraverse::ProcessLoop()
11960bool SageInterface::forLoopNormalization(SgForStatement* loop, bool foldConstant /*= true*/)
11961{
11962 ROSE_ASSERT(loop != NULL);
11963 // Normalize initialization statement of the for loop
11964 // -------------------------------------
11965 // for (int i=0;... ) becomes int i; for (i=0;..)
11966 // Only roughly check here, isCanonicalForLoop() should be called to have a stricter check
11968 return false;
11969
11970 // Normalized the test expressions
11971 if (!normalizeForLoopTest(loop))
11972 return false;
11973
11974 // Normalize the increment expression
11975 if (!normalizeForLoopIncrement(loop))
11976 return false;
11977
11978 // Normalize the loop body: ensure there is a basic block
11980 ROSE_ASSERT(body!=NULL);
11981 // Liao, 9/22/2009
11982 // folding entire loop may cause decreased accuracy for floating point operations
11983 // we only want to fold the loop controlling expressions
11984 if (foldConstant)
11985 {
11986 //constantFolding(loop->get_parent());
11987 constantFolding(loop->get_test());
11988 constantFolding(loop->get_increment());
11989 }
11990
11991 return true;
11992}
11993
11996{
11997 // TODO, normalize continue to enddo ?
11998 ROSE_ASSERT (loop != NULL);
11999 SgExpression* e_3 = loop->get_increment();
12000 if (isSgNullExpression(e_3))
12001 {
12002 SgIntVal* iv = buildIntVal(1);
12003 loop->set_increment(iv);
12004 iv->set_parent(loop);
12005 delete (e_3);
12006 }
12007 return true;
12008}
12009
12010#if 0
12011bool SageInterface::loopUnrolling(SgForStatement* loop, size_t unrolling_factor)
12012{
12013 // normalize the loop first
12014 if (!forLoopNormalization(loop))
12015 return false; // input loop cannot be normalized to a canonical form
12016 // prepare Loop transformation environment
12018 ROSE_ASSERT(func!=NULL);
12019 AstInterfaceImpl faImpl(func->get_definition()->get_body());
12020 AstInterface fa(&faImpl);
12021 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
12022 ArrayInterface array_interface (*annot);
12023 array_interface.initialize(fa, AstNodePtrImpl(func->get_definition()));
12024 array_interface.observe(fa);
12025 LoopTransformInterface :: set_astInterface(fa);
12026 LoopTransformInterface :: set_arrayInterface(&array_interface);
12027
12028 // invoke the unrolling defined in Qing's code
12029 // the traversal will skip the input node ptr, so we pass loop's parent ptr instead
12030 AstNodePtr result = AstNodePtrImpl(loop->get_parent()) ;
12031
12032 LoopUnrolling lu(unrolling_factor);
12033 //LoopUnrolling lu(unrolling_factor,LoopUnrolling::COND_LEFTOVER);//works but not a good choice
12034 //if (lu.cmdline_configure()) // this will cause unrolling to be skipped if no -unroll is used in command line
12035 result = lu(lpTrans, result);
12036 return true;
12037}
12038#else
12039
12040// a brand new serious implementation for loop unrolling, Liao, 6/25/2009
12041/* Handle left-over iterations if iteration_count%unrolling_factor != 0
12042 * Handle stride (step) >1
12043 * Assuming loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
12044 *
12045 * iteration_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1
12046 * fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step;
12047 * fringe ==0 if no leftover iterations
12048 * otherwise adjust ub so the leftover iterations will put into the last fringe loop
12049 * unrolled loop's header: for (i=lb;i<=ub - fringe; i+= step*unroll_factor)
12050 * loop body: copy body n times from 0 to factor -1
12051 * stmt(i+ 0*step); ...; stmt (i+ (factor-1)*step);
12052 * fringe loop: the same as the original loop, except for no init statement
12053 *
12054 * e.g:
12055 * // unrolling 3 times for the following loop with stride !=1
12056 * for (i=0; i<=9; i+=3)
12057 * {
12058 * a[i]=i;
12059 * }
12060 * // it becomes
12061 * // iteration count = 10%3=1 -> 10/3+1 = 4
12062 * // fringe = 4%3 =1 --> 3*3
12063 * // ub-fringe = 9-3*3
12064 * for (i=0; i<=9-3*3; i+=3*3)
12065 * {
12066 * a[i+3*0]=i;
12067 * a[i+3*1]=i;
12068 * a[i+3*2]=i;
12069 * }
12070 * // i=9 is the leftover iteration
12071 * for (; i<=9; i+=3)
12072 * {
12073 * a[i]=i;
12074 * }
12075 *
12076 */
12077bool SageInterface::loopUnrolling(SgForStatement* target_loop, size_t unrolling_factor)
12078{
12079#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
12080 //Handle 0 and 1, which means no unrolling at all
12081 if (unrolling_factor <= 1)
12082 return true;
12083
12084 // normalize the target loop first
12085
12086 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12087 if (!forLoopNormalization(target_loop))
12088 {
12089 // the return value is not reliable
12090 // cerr<<"Error in SageInterface::loopUnrolling(): target loop cannot be normalized."<<endl;
12091 // dumpInfo(target_loop);
12092 // return false;
12093 }
12094 // grab the target loop's essential header information
12095 SgInitializedName* ivar = NULL;
12096 SgExpression* lb = NULL;
12097 SgExpression* ub = NULL;
12098 SgExpression* step = NULL;
12099 SgStatement* orig_body = NULL;
12100 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, &orig_body))
12101 {
12102 cerr<<"Error in SageInterface::loopUnrolling(): target loop is not canonical."<<endl;
12103 dumpInfo(target_loop);
12104 return false;
12105 }
12106 ROSE_ASSERT(ivar&& lb && ub && step);
12107 ROSE_ASSERT(isSgBasicBlock(orig_body));
12108
12109 // generate the fringe loop
12110 bool needFringe = true;
12111 SgForStatement* fringe_loop = deepCopy<SgForStatement>(target_loop);
12112 insertStatementAfter(target_loop,fringe_loop);
12113 removeStatement(fringe_loop->get_for_init_stmt());
12114 fringe_loop->set_for_init_stmt(NULL);
12115
12116 // _lu_iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;
12118 copyExpression(lb));
12119 raw_range_exp->set_need_paren(true);
12120 SgExpression* range_d_step_exp = buildDivideOp(raw_range_exp,copyExpression(step));//(ub-lb+1)/step
12121 SgExpression* condition_1 = buildEqualityOp(buildModOp(copyExpression(raw_range_exp),copyExpression(step)),buildIntVal(0)); //(ub-lb+1)%step ==0
12122
12123 SgExpression* iter_count_exp = buildConditionalExp(condition_1,range_d_step_exp, buildAddOp(copyExpression(range_d_step_exp),buildIntVal(1)));
12124 // fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step
12125 SgExpression* condition_2 = buildEqualityOp(buildModOp(iter_count_exp, buildIntVal(unrolling_factor)), buildIntVal(0));
12126 SgExpression* initor = buildConditionalExp(condition_2, buildIntVal(0), buildMultiplyOp(buildIntVal(unrolling_factor),copyExpression(step)));
12127
12128 SgScopeStatement* scope = target_loop->get_scope();
12129 ROSE_ASSERT(scope != NULL);
12130 string fringe_name = "_lu_fringe_"+ StringUtility::numberToString(++gensym_counter);
12131 SgVariableDeclaration* fringe_decl = buildVariableDeclaration(fringe_name, buildIntType(),buildAssignInitializer(initor), scope);
12132 insertStatementBefore(target_loop, fringe_decl);
12133 attachComment(fringe_decl, "iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;");
12134 attachComment(fringe_decl, "fringe = iter_count%unroll_factor==0 ? 0:unroll_factor*step");
12135
12136 // compile-time evaluate to see if index is a constant of value 0
12137 // if so, the iteration count can be divided even by the unrolling factor
12138 // and no fringe loop is needed
12139 // WE have to fold on its parent node to get a possible constant since
12140 // constant folding only folds children nodes, not the current node to a constant
12141 ConstantFolding::constantFoldingOptimization(fringe_decl,false);
12142 SgInitializedName * ivarname = fringe_decl->get_variables().front();
12143 ROSE_ASSERT(ivarname != NULL);
12144 // points to a new address if constant folding happens
12145 SgAssignInitializer * init1 = isSgAssignInitializer(ivarname->get_initializer());
12146 if (init1)
12147 if (isSgIntVal(init1->get_operand_i()))
12148 if (isSgIntVal(init1->get_operand_i())->get_value() == 0)
12149 needFringe = false;
12150
12151 // rewrite loop header ub --> ub -fringe; step --> step *unrolling_factor
12152 SgBinaryOp* ub_bin_op = isSgBinaryOp(ub->get_parent());
12153 ROSE_ASSERT(ub_bin_op);
12154 if (needFringe)
12155 ub_bin_op->set_rhs_operand(buildSubtractOp(copyExpression(ub),buildVarRefExp(fringe_name,scope)));
12156 else
12157 {
12158 ub_bin_op->set_rhs_operand(copyExpression(ub));
12159 removeStatement(fringe_decl);
12160 }
12161
12162 SgBinaryOp* step_bin_op = isSgBinaryOp(step->get_parent());
12163 ROSE_ASSERT(step_bin_op != NULL);
12164 step_bin_op->set_rhs_operand(buildMultiplyOp(copyExpression(step),buildIntVal(unrolling_factor)));
12165
12166 bool isPlus = false;
12167 if (isSgPlusAssignOp(step_bin_op))
12168 isPlus = true;
12169 else if (isSgMinusAssignOp(step_bin_op))
12170 isPlus = false;
12171 else
12172 {
12173 cerr<<"Error in SageInterface::loopUnrolling(): illegal incremental exp of a canonical loop"<<endl;
12174 dumpInfo(step_bin_op);
12175 ROSE_ABORT();
12176 }
12177
12178 // copy loop body factor -1 times, and replace reference to ivar with ivar +/- step*[1 to factor-1]
12179 for (size_t i =1; i<unrolling_factor; i++)
12180 {
12181 SgBasicBlock* body = isSgBasicBlock(deepCopy(fringe_loop->get_loop_body())); // normalized loop has a BB body
12182 ROSE_ASSERT(body);
12183 std::vector<SgVarRefExp*> refs = querySubTree<SgVarRefExp> (body, V_SgVarRefExp);
12184 for (std::vector<SgVarRefExp*>::iterator iter = refs.begin(); iter !=refs.end(); iter++)
12185 {
12186 SgVarRefExp* refexp = *iter;
12187 if (refexp->get_symbol()==ivar->get_symbol_from_symbol_table())
12188 {
12189 // replace reference to ivar with ivar +/- step*i
12190 SgExpression* new_exp = NULL;
12191 //build replacement expression for every appearance
12192 if (isPlus) //ivar +/- step * i
12193 new_exp = buildAddOp(buildVarRefExp(ivar,scope),buildMultiplyOp(copyExpression(step),buildIntVal(i)));
12194 else
12196
12197 // replace it with the right one
12198 replaceExpression(refexp, new_exp);
12199 }
12200 }
12201 // copy body to loop body, this should be a better choice
12202 // to avoid redefinition of variables after unrolling (new scope is introduced to avoid this)
12203 appendStatement(body,isSgBasicBlock(orig_body));
12204 // moveStatementsBetweenBlocks(body,isSgBasicBlock(orig_body));
12205 }
12206
12207 // remove the fringe loop if not needed finally
12208 // it is used to buffering the original loop body before in either cases
12209 if (!needFringe)
12210 removeStatement(fringe_loop);
12211
12212 // constant folding for the transformed AST
12213 ConstantFolding::constantFoldingOptimization(scope,false);
12214 //ConstantFolding::constantFoldingOptimization(getProject(),false);
12215
12216#endif
12217
12218 return true;
12219}
12220#endif
12221
12222// Liao, 6/15/2009
12225static size_t myfactorial (size_t n)
12226{
12227 size_t result=1;
12228 for (size_t i=2; i<=n; i++)
12229 result*=i;
12230 return result;
12231}
12232
12233#endif
12234
12235#ifndef USE_ROSE
12236
12239std::vector<size_t> getPermutationOrder( size_t n, size_t lexicoOrder)
12240{
12241 size_t k = lexicoOrder;
12242 std::vector<size_t> s(n);
12243 // initialize the permutation vector
12244 for (size_t i=0; i<n; i++)
12245 s[i]=i;
12246
12247 //compute (n- 1)!
12248 size_t factorial = myfactorial(n-1);
12249 //check if the number is not in the range of [0, n! - 1]
12250 if (k/n>=factorial)
12251 {
12252 printf("Error: in getPermutationOrder(), lexicoOrder is larger than n!-1\n");
12253 ROSE_ABORT();
12254 }
12255 // Algorithm:
12256 //check each element of the array, excluding the right most one.
12257 //the goal is to find the right element for each s[j] from 0 to n-2
12258 // method: each position is associated a factorial number
12259 // s[0] -> (n-1)!
12260 // s[1] -> (n-2)! ...
12261 // the input number k is divided by the factorial at each position (6, 3, 2, 1 for size =4)
12262 // so only big enough k can have non-zero value after division
12263 // 0 value means no change to the position for the current iteration
12264 // The non-zero value is further modular by the number of the right hand elements of the current element.
12265 // (mode on 4, 3, 2 to get offset 1-2-3, 1-2, 1 from the current position 0, 1, 2)
12266 // choose one of them to be moved to the current position,
12267 // shift elements between the current and the moved element to the right direction for one position
12268 for (size_t j=0; j<n-1; j++)
12269 {
12270 //calculates the next cell from the cells left
12271 //(the cells in the range [j, s.length - 1])
12272 int tempj = (k/factorial) % (n - j);
12273 //Temporarily saves the value of the cell needed
12274 // to add to the permutation this time
12275 int temps = s[j+tempj];
12276 //shift all elements to "cover" the "missing" cell
12277 //shift them to the right
12278 for (size_t i=j+tempj; i>j; i--)
12279 {
12280 s[i] = s[i-1]; //shift the chain right
12281 }
12282 // put the chosen cell in the correct spot
12283 s[j]= temps;
12284 // updates the factorial
12285 factorial = factorial /(n-(j+1));
12286 }
12287#if 0
12288 for (size_t i = 0; i<n; i++)
12289 cout<<" "<<s[i];
12290 cout<<endl;
12291#endif
12292 return s;
12293}
12294
12296/* Translation
12297 Before:
12298 for (i = 0; i < 100; i++)
12299 for (j = 0; j < 100; j++)
12300 for (k = 0; k < 100; k++)
12301 c[i][j]= c[i][j]+a[i][k]*b[k][j];
12302
12303 After tiling i loop nest's level 3 (k-loop) with size 5, it becomes
12304
12305// added a new controlling loop at the outer most level
12306 int _lt_var_k;
12307 for (_lt_var_k = 0; _lt_var_k <= 99; _lt_var_k += 1 * 5) {
12308 for (i = 0; i < 100; i++)
12309 for (j = 0; j < 100; j++)
12310 // rewritten loop header , normalized also
12311 for (k = _lt_var_k; k <= (99 < (_lt_var_k + 5 - 1))?99 : (_lt_var_k + 5 - 1); k += 1) {
12312 c[i][j] = c[i][j] + a[i][k] * b[k][j];
12313 }
12314 }
12315// finally run constant folding
12316
12317 */
12318bool SageInterface::loopTiling(SgForStatement* loopNest, size_t targetLevel, size_t tileSize)
12319{
12320 ROSE_ASSERT(loopNest != NULL);
12321 ROSE_ASSERT(targetLevel >0);
12322 // ROSE_ASSERT(tileSize>0);// 1 is allowed
12323 // skip tiling if tiling size is 0 (no tiling), we allow 0 to get a reference value for the original code being tuned
12324 // 1 (no need to tile)
12325 if (tileSize<=1)
12326 return true;
12327 // Locate the target loop at level n
12328 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(loopNest,V_SgForStatement);
12329 ROSE_ASSERT(loops.size()>=targetLevel);
12330 SgForStatement* target_loop = loops[targetLevel -1]; // adjust to numbering starting from 0
12331
12332 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12333 // normalize the target loop first
12334 if (!forLoopNormalization(target_loop))
12335 {// the return value is not reliable
12336// cerr<<"Error in SageInterface::loopTiling(): target loop cannot be normalized."<<endl;
12337// dumpInfo(target_loop);
12338// return false;
12339 }
12340 // grab the target loop's essential header information
12341 SgInitializedName* ivar = NULL;
12342 SgExpression* lb = NULL;
12343 SgExpression* ub = NULL;
12344 SgExpression* step = NULL;
12345 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, NULL))
12346 {
12347 cerr<<"Error in SageInterface::loopTiling(): target loop is not canonical."<<endl;
12348 dumpInfo(target_loop);
12349 return false;
12350 }
12351 ROSE_ASSERT(ivar&& lb && ub && step);
12352
12353 // Add a controlling loop around the top loop nest
12354 // Ensure the parent can hold more than one children
12355 SgLocatedNode* parent = NULL; //SageInterface::ensureBasicBlockAsParent(loopNest)
12356 if (isBodyStatement(loopNest)) // if it is a single body statement (Already a for statement, not a basic block)
12357 parent = makeSingleStatementBodyToBlock (loopNest);
12358 else
12359 parent = isSgLocatedNode(loopNest ->get_parent());
12360
12361 ROSE_ASSERT(parent!= NULL);
12362 // Now we can prepend a controlling loop index variable: __lt_var_originalIndex
12363 string ivar2_name = "_lt_var_"+ivar->get_name().getString();
12364 SgScopeStatement* scope = loopNest->get_scope();
12366 (ivar2_name, buildIntType(),NULL, scope);
12367 insertStatementBefore(loopNest, loop_index_decl);
12368 // init statement of the loop header, copy the lower bound
12369 SgStatement* init_stmt = buildAssignStatement(buildVarRefExp(ivar2_name,scope), copyExpression(lb));
12370 //two cases <= or >= for a normalized loop
12371 SgExprStatement* cond_stmt = NULL;
12372 SgExpression* orig_test = target_loop->get_test_expr();
12373 if (isSgBinaryOp(orig_test))
12374 {
12375 if (isSgLessOrEqualOp(orig_test))
12376 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12377 else if (isSgGreaterOrEqualOp(orig_test))
12378 {
12379 cond_stmt = buildExprStatement(buildGreaterOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12380 }
12381 else
12382 {
12383 cerr<<"Error: illegal condition operator for a canonical loop"<<endl;
12384 dumpInfo(orig_test);
12385 ROSE_ABORT();
12386 }
12387 }
12388 else
12389 {
12390 cerr<<"Error: illegal condition expression for a canonical loop"<<endl;
12391 dumpInfo(orig_test);
12392 ROSE_ABORT();
12393 }
12394 ROSE_ASSERT(cond_stmt != NULL);
12395
12396 // build loop incremental I
12397 // expression var+=up*tilesize or var-=upper * tilesize
12398 SgExpression* incr_exp = NULL;
12399 SgExpression* orig_incr_exp = target_loop->get_increment();
12400 if( isSgPlusAssignOp(orig_incr_exp))
12401 {
12402 incr_exp = buildPlusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12403 }
12404 else if (isSgMinusAssignOp(orig_incr_exp))
12405 {
12406 incr_exp = buildMinusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12407 }
12408 else
12409 {
12410 cerr<<"Error: illegal increment expression for a canonical loop"<<endl;
12411 dumpInfo(orig_incr_exp);
12412 ROSE_ABORT();
12413 }
12414 SgForStatement* control_loop = buildForStatement(init_stmt, cond_stmt,incr_exp, buildBasicBlock());
12415 insertStatementBefore(loopNest, control_loop);
12416 // move loopNest into the control loop
12417 removeStatement(loopNest);
12418 appendStatement(loopNest,isSgBasicBlock(control_loop->get_loop_body()));
12419
12420 // rewrite the lower (i=lb), upper bounds (i<=/>= ub) of the target loop
12421 SgAssignOp* assign_op = isSgAssignOp(lb->get_parent());
12422 ROSE_ASSERT(assign_op);
12423 assign_op->set_rhs_operand(buildVarRefExp(ivar2_name,scope));
12424 // ub< var_i+tileSize-1? ub:var_i+tileSize-1
12425 SgBinaryOp* bin_op = isSgBinaryOp(ub->get_parent());
12426 ROSE_ASSERT(bin_op);
12427 SgExpression* ub2 = buildSubtractOp(buildAddOp(buildVarRefExp(ivar2_name,scope), buildIntVal(tileSize)), buildIntVal(1));
12428 SgExpression* test_exp = buildLessThanOp(copyExpression(ub),ub2);
12429 test_exp->set_need_paren(true);
12430 ub->set_need_paren(true);
12431 ub2->set_need_paren(true);
12432 SgConditionalExp * triple_exp = buildConditionalExp(test_exp,copyExpression(ub), copyExpression(ub2));
12433 bin_op->set_rhs_operand(triple_exp);
12434 // constant folding
12435 // folding entire loop may decrease the accuracy of floating point calculation
12436 // we fold loop control expressions only
12437 //constantFolding(control_loop->get_scope());
12438 constantFolding(control_loop->get_test());
12439 constantFolding(control_loop->get_increment());
12440 return true;
12441}
12442
12444bool SageInterface::loopInterchange(SgForStatement* loop, size_t depth, size_t lexicoOrder)
12445{
12446 if (lexicoOrder == 0) // allow 0 to mean no interchange at all
12447 return true;
12448 // parameter verification
12449 ROSE_ASSERT(loop != NULL);
12450 //must have at least two levels
12451 ROSE_ASSERT (depth >1);
12452 ROSE_ASSERT(lexicoOrder<myfactorial(depth));
12453 //TODO need to verify the input loop has n perfectly-nested children loops inside
12454 // save the loop nest's headers: init, test, and increment
12455 std::vector<SgForStatement* > loopNest = SageInterface::querySubTree<SgForStatement>(loop,V_SgForStatement);
12456 ROSE_ASSERT(loopNest.size()>=depth);
12457 std::vector<std::vector<SgNode*> > loopHeads;
12458 for (std::vector<SgForStatement* > ::iterator i = loopNest.begin(); i!= loopNest.end(); i++)
12459 {
12460 SgForStatement* cur_loop = *i;
12461 std::vector<SgNode*> head;
12462 head.push_back(cur_loop->get_for_init_stmt());
12463 head.push_back(cur_loop->get_test());
12464 head.push_back(cur_loop->get_increment());
12465 loopHeads.push_back(head);
12466 }
12467
12468 // convert the lexicographical number to a permutation order array permutation[depth]
12469 std::vector<size_t> changedOrder = getPermutationOrder (depth, lexicoOrder);
12470 // rewrite the loop nest to reflect the permutation
12471 // set the header to the new header based on the permutation array
12472 for (size_t i=0; i<depth; i++)
12473 {
12474 // only rewrite if necessary
12475 if (i != changedOrder[i])
12476 {
12477 SgForStatement* cur_loop = loopNest[i];
12478 std::vector<SgNode*> newhead = loopHeads[changedOrder[i]];
12479
12480 SgForInitStatement* init = isSgForInitStatement(newhead[0]);
12481 //ROSE_ASSERT(init != NULL) // could be NULL?
12482 ROSE_ASSERT(init != cur_loop->get_for_init_stmt());
12483 cur_loop->set_for_init_stmt(init);
12484 if (init)
12485 {
12486 init->set_parent(cur_loop);
12488 }
12489
12490 SgStatement* test = isSgStatement(newhead[1]);
12491 cur_loop->set_test(test);
12492 if (test)
12493 {
12494 test->set_parent(cur_loop);
12496 }
12497
12498 SgExpression* incr = isSgExpression(newhead[2]);
12499 cur_loop->set_increment(incr);
12500 if (incr)
12501 {
12502 incr->set_parent(cur_loop);
12504 }
12505 }
12506 }
12507 return true;
12508}
12509
12512{
12513 ROSE_ASSERT(loop != NULL);
12514 SgInitializedName* ivarname=NULL;
12515
12516 // Fortran case ------------------
12517 if (SgFortranDo * do_loop = isSgFortranDo(loop))
12518 {
12519 SgAssignOp* assign_op = isSgAssignOp (do_loop->get_initialization());
12520 ROSE_ASSERT (assign_op != NULL);
12521 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12522 ROSE_ASSERT (var != NULL);
12523 ivarname = var->get_symbol()->get_declaration();
12524 ROSE_ASSERT (ivarname != NULL);
12525 return ivarname;
12526 }
12527 // C/C++ case ------------------------------
12528 SgForStatement* fs = isSgForStatement(loop);
12529 if (fs == NULL)
12530 {
12531 return NULL;
12532 }
12533 // we only handle C/C++ for loops and Fortran Do loops.
12534 // Any other kinds of loops (while, do-while,etc.) are skipped and return NULL;
12535 // ROSE_ASSERT (fs != NULL);
12536
12537 //Check initialization statement is something like i=xx;
12538 SgStatementPtrList & init = fs->get_init_stmt();
12539 if (init.size() !=1)
12540 {
12541 cerr<<"SageInterface::getLoopIndexVariable(), no or more than one initialization statements are encountered. Not supported yet "<<endl;
12542 //ROSE_ASSERT(false);
12543 return NULL;
12544 }
12545 SgStatement* init1 = init.front();
12546 SgExpression* ivarast=NULL;
12547
12548 // DQ (3/20/2016): Note that GNU compiler reports these variables are set but not used.
12549 //bool isCase1=false, isCase2=false;
12550
12551 //consider C99 style: for (int i=0;...)
12552 if (isSgVariableDeclaration(init1))
12553 {
12554 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12555 ivarname = decl->get_variables().front();
12556 ROSE_ASSERT(ivarname != NULL);
12557 //SgInitializer * initor = ivarname->get_initializer();
12558 // if (isSgAssignInitializer(initor))
12559 // isCase1 = true;
12560 }// other regular case: for (i=0;..)
12561 else if (isAssignmentStatement(init1, &ivarast))
12562 {
12563 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12564 if (var)
12565 {
12566 ivarname = var->get_symbol()->get_declaration();
12567 //isCase2 = true;
12568 }
12569 }
12570 else if (SgExprStatement* exp_stmt = isSgExprStatement(init1))
12571 { //case like: for (i = 1, len1 = 0, len2=0; i <= n; i++)
12572 // AST is: SgCommaOpExp -> SgAssignOp -> SgVarRefExp
12573 if (SgCommaOpExp* comma_exp = isSgCommaOpExp(exp_stmt->get_expression()))
12574 {
12575 SgCommaOpExp* leaf_exp = comma_exp;
12576 while (isSgCommaOpExp(leaf_exp->get_lhs_operand()))
12577 leaf_exp = isSgCommaOpExp(leaf_exp->get_lhs_operand());
12578 if (SgAssignOp* assign_op = isSgAssignOp(leaf_exp->get_lhs_operand()))
12579 {
12580 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12581 if (var)
12582 {
12583 ivarname = var->get_symbol()->get_declaration();
12584 }
12585 }
12586 }
12587 }
12588 else
12589 {
12590
12591 mlog[Sawyer::Message::Common::WARN] <<"Warning: SageInterface::getLoopIndexVariable(). Unhandled init_stmt type of SgForStatement"<<endl;
12592 mlog[Sawyer::Message::Common::WARN] <<"Init statement is :"<<init1->class_name() <<" " <<init1->unparseToString()<<endl;
12593 init1->get_file_info()->display("Debug");
12594
12595 return NULL;
12596 //ROSE_ASSERT (false);
12597 }
12598 // Cannot be both true
12599 // ROSE_ASSERT(!(isCase1&&isCase2));
12600
12601 //Check loop index's type
12602 //ROSE_ASSERT(isStrictIntegerType(ivarname->get_type()));
12603 return ivarname;
12604}
12605
12609{
12610 ROSE_ASSERT (ivar != NULL);
12611 ROSE_ASSERT (subtree_root != NULL);
12612 bool result = false;
12613 SgScopeStatement * cur_loop = findEnclosingLoop (getEnclosingStatement(subtree_root));
12614 while (cur_loop)
12615 {
12616 SgInitializedName * i_index = getLoopIndexVariable (cur_loop);
12617 if (i_index == ivar)
12618 {
12619 result = true;
12620 break;
12621 }
12622 else
12623 { // findEnclosingLoop() is inclusive.
12624 cur_loop = findEnclosingLoop (getEnclosingStatement(cur_loop->get_parent()));
12625 }
12626 }
12627 return result;
12628}
12629
12631
12636{
12637 ROSE_ASSERT (loop !=NULL);
12638 SgStatementPtrList& stmt_list = loop->get_init_stmt();
12639 if (stmt_list.size() >1) return true; // two var decl statements
12640 if (stmt_list.size() == 0) return false;
12641
12642// generateDOTforMultipleFile(*getProject());
12643 //single variable declaration statement, like int i;
12644 SgVariableDeclaration* decl_stmt = isSgVariableDeclaration(stmt_list[0]);
12645 if (decl_stmt != NULL)
12646 return false;
12647
12648 // single statement, but with comma expression (i=0, j=0)
12649 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
12650 ROSE_ASSERT (exp_stmt != NULL);
12651 if (isSgCommaOpExp (exp_stmt->get_expression()) )
12652 {
12653 return true;
12654 }
12655
12656 return false;
12657}
12659bool 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*/)
12660{
12661 ROSE_ASSERT(loop != NULL);
12662 SgFortranDo* fs = isSgFortranDo(loop);
12663 if (fs == NULL)
12664 return false;
12665 // 1. Check initialization statement is something like i=xx;
12666 SgExpression * init = fs->get_initialization();
12667 if (init == NULL)
12668 return false;
12669 SgAssignOp* init_assign = isSgAssignOp (init);
12670 SgExpression *lbast=NULL, *ubast=NULL;
12671 // SgExpression* ivarast=NULL, *stepast=NULL;
12672 SgInitializedName* ivarname=NULL;
12673
12674 bool isCase1=false;
12675 if (init_assign)
12676 {
12677 SgVarRefExp* var = isSgVarRefExp(init_assign->get_lhs_operand());
12678 if (var)
12679 ivarname = var->get_symbol()->get_declaration();
12680 lbast = init_assign->get_rhs_operand();
12681 if (ivarname && lbast )
12682 isCase1 = true;
12683 }
12684 // if not i=1
12685 if (!isCase1)
12686 return false;
12687
12688 //Check loop index's type
12689 if (!SageInterface::isStrictIntegerType(ivarname->get_type()))
12690 return false;
12691#if 0
12692 //2. Check test expression i [<=, >=, <, > ,!=] bound
12693 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12694 if (test == NULL)
12695 return false;
12696 switch (test->variantT()) {
12697 case V_SgLessOrEqualOp:
12698 if (isInclusiveUpperBound != NULL)
12699 *isInclusiveUpperBound = true;
12700 if (hasIncrementalIterationSpace != NULL)
12701 *hasIncrementalIterationSpace = true;
12702 break;
12703 case V_SgLessThanOp:
12704 if (isInclusiveUpperBound != NULL)
12705 *isInclusiveUpperBound = false;
12706 if (hasIncrementalIterationSpace != NULL)
12707 *hasIncrementalIterationSpace = true;
12708 break;
12709 case V_SgGreaterOrEqualOp:
12710 if (isInclusiveUpperBound != NULL)
12711 *isInclusiveUpperBound = true;
12712 if (hasIncrementalIterationSpace != NULL)
12713 *hasIncrementalIterationSpace = false;
12714 break;
12715 case V_SgGreaterThanOp:
12716 if (isInclusiveUpperBound != NULL)
12717 *isInclusiveUpperBound = false;
12718 if (hasIncrementalIterationSpace != NULL)
12719 *hasIncrementalIterationSpace = false;
12720 break;
12721// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12722 break;
12723 default:
12724 return false;
12725 }
12726 // check the tested variable is the same as the loop index
12727 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12728 if (testvar == NULL)
12729 return false;
12730 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12731 return false;
12732#endif
12733 //grab the upper bound
12734 ubast = loop->get_bound();
12735 // Fortran Do loops always have inclusive upper bound
12736 if (isInclusiveUpperBound != NULL)
12737 *isInclusiveUpperBound = true;
12738 //3. Check the increment expression
12739 SgExpression* incr = fs->get_increment();
12740 ROSE_ASSERT (incr != NULL);
12741 if (isSgNullExpression(incr))
12742 {
12743 cerr<<"Error:isCanonicalDoLoop() found NULL increment expression. Please call doLoopNormalization() first!"<<endl;
12744 ROSE_ASSERT (false);
12745 }
12746 if (hasIncrementalIterationSpace != NULL)
12747 {
12748 *hasIncrementalIterationSpace = true;
12749 // We can only tell a few cases
12750 if (SgIntVal* i_v = isSgIntVal(incr))
12751 {
12752 if (i_v->get_value()<0)
12753 *hasIncrementalIterationSpace = false;
12754 }
12755 }
12756#if 0
12757 SgVarRefExp* incr_var = NULL;
12758 switch (incr->variantT()) {
12759 case V_SgPlusAssignOp: //+=
12760 case V_SgMinusAssignOp://-=
12761 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12762 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12763 break;
12764 case V_SgPlusPlusOp: //++
12765 case V_SgMinusMinusOp: //--
12766 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12767 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12768 break;
12769 default:
12770 return false;
12771 }
12772 if (incr_var == NULL)
12773 return false;
12774 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12775 return false;
12776#endif
12777 // return loop information if requested
12778 if (ivar != NULL)
12779 *ivar = ivarname;
12780 if (lb != NULL)
12781 *lb = lbast;
12782 if (ub != NULL)
12783 *ub = ubast;
12784 if (step != NULL)
12785 *step = incr;
12786 if (body != NULL) {
12787 *body = fs->get_body();
12788 }
12789 return true;
12790}
12791//TODO: expose it to the namespace once it matures.
12793// with a single entry at the top and a single exit at the bottom, or an OpenMP construct.
12794/*
12795From OpenMP 4.5 Specification
12796
127971.2.2 OpenMP Language Terminology
12798
12799For C/C++, an executable statement, possibly compound, with a single entry at the
12800top and a single exit at the bottom, or an OpenMP construct.
12801
12802For Fortran, a block of executable statements with a single entry at the top and a
12803single exit at the bottom, or an OpenMP construct.
12804
12805COMMENTS:
12806
12807For all base languages:
12808* Access to the structured block must not be the result of a branch; and
12809* The point of exit cannot be a branch out of the structured block.
12810
12811 For C/C++:
12812* The point of entry must not be a call to setjmp();
12813* longjmp() and throw() must not violate the entry/exit criteria;
12814* Calls to exit() are allowed in a structured block; and
12815* 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.
12816
12817For Fortran:
12818* STOP statements are allowed in a structured block.
12819
12820*/
12821bool isStructuredBlock(SgStatement* s)
12822{
12823 bool rt = true;
12824 ROSE_ASSERT (s != NULL);
12825
12826 // contain break;
12827 std::set<SgNode*> bset = SgNodeHelper::loopRelevantBreakStmtNodes (s);
12828 if (bset.size()!=0 )
12829 rt = false;
12830 //TODO: contain goto statement, jumping to outside targets
12831 // longjump(), throw(),
12832 // calls to exit() are allowed.
12833
12834 return rt;
12835
12836}
12837
12839//TODO check the loop index is not being written in the loop body
12840bool 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*/)
12841{
12842 ROSE_ASSERT(loop != NULL);
12843 SgForStatement* fs = isSgForStatement(loop);
12844 //SgFortranDo* fs2 = isSgFortranDo(loop);
12845 if (fs == NULL)
12846 {
12847 // if (fs2)
12848 // return isCanonicalDoLoop (fs2, ivar, lb, ub, step, body, hasIncrementalIterationSpace, isInclusiveUpperBound);
12849 // else
12850 return false;
12851 }
12852 // 1. Check initialization statement is something like i=xx;
12853 SgStatementPtrList & init = fs->get_init_stmt();
12854 if (init.size() !=1)
12855 return false;
12856 SgStatement* init1 = init.front();
12857 SgExpression* ivarast=NULL, *lbast=NULL, *ubast=NULL, *stepast=NULL;
12858 SgInitializedName* ivarname=NULL;
12859
12860 bool isCase1=false, isCase2=false;
12861 //consider C99 style: for (int i=0;...)
12862 if (isSgVariableDeclaration(init1))
12863 {
12864 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12865 ivarname = decl->get_variables().front();
12866 ROSE_ASSERT(ivarname != NULL);
12867 SgInitializer * initor = ivarname->get_initializer();
12868 if (isSgAssignInitializer(initor))
12869 {
12870 lbast = isSgAssignInitializer(initor)->get_operand();
12871 isCase1 = true;
12872 }
12873 }// other regular case: for (i=0;..)
12874 else if (isAssignmentStatement(init1, &ivarast, &lbast))
12875 {
12876 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12877 if (var)
12878 {
12879 ivarname = var->get_symbol()->get_declaration();
12880 isCase2 = true;
12881 }
12882 }
12883 // Cannot be both true
12884 ROSE_ASSERT(!(isCase1&&isCase2));
12885 // if not either case is true
12886 if (!(isCase1||isCase2))
12887 return false;
12888
12889 //Check loop index's type
12890 if (!isStrictIntegerType(ivarname->get_type()))
12891 return false;
12892
12893 //2. Check test expression i [<=, >=, <, > ,!=] bound
12894 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12895 if (test == NULL)
12896 return false;
12897 switch (test->variantT()) {
12898 case V_SgLessOrEqualOp:
12899 if (isInclusiveUpperBound != NULL)
12900 *isInclusiveUpperBound = true;
12901 if (hasIncrementalIterationSpace != NULL)
12902 *hasIncrementalIterationSpace = true;
12903 break;
12904 case V_SgLessThanOp:
12905 if (isInclusiveUpperBound != NULL)
12906 *isInclusiveUpperBound = false;
12907 if (hasIncrementalIterationSpace != NULL)
12908 *hasIncrementalIterationSpace = true;
12909 break;
12910 case V_SgGreaterOrEqualOp:
12911 if (isInclusiveUpperBound != NULL)
12912 *isInclusiveUpperBound = true;
12913 if (hasIncrementalIterationSpace != NULL)
12914 *hasIncrementalIterationSpace = false;
12915 break;
12916 case V_SgGreaterThanOp:
12917 if (isInclusiveUpperBound != NULL)
12918 *isInclusiveUpperBound = false;
12919 if (hasIncrementalIterationSpace != NULL)
12920 *hasIncrementalIterationSpace = false;
12921 break;
12922// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12923 break;
12924 default:
12925 return false;
12926 }
12927 // check the tested variable is the same as the loop index
12928 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12929 if (testvar == NULL)
12930 return false;
12931 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12932 return false;
12933 //grab the upper bound
12934 ubast = test->get_rhs_operand();
12935
12936 //3. Check the increment expression
12937 /* Allowed forms
12938 ++var
12939 var++
12940 --var
12941 var--
12942
12943 var += incr
12944 var -= incr
12945
12946 var = var + incr
12947 var = incr + var
12948 var = var - incr
12949 */
12950 SgExpression* incr = fs->get_increment();
12951 SgVarRefExp* incr_var = NULL;
12952 switch (incr->variantT()) {
12953 case V_SgPlusAssignOp: //+=
12954 case V_SgMinusAssignOp://-=
12955 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12956 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12957 break;
12958 case V_SgPlusPlusOp: //++
12959 case V_SgMinusMinusOp: //--
12960 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12961 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12962 break;
12963 case V_SgAssignOp: { // cases : var + incr, var - incr, incr + var (not allowed: incr-var)
12964 incr_var=isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12965 if(incr_var == NULL)
12966 return false;
12967 SgAddOp* addOp=isSgAddOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
12968 SgSubtractOp* subtractOp=isSgSubtractOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
12969 SgBinaryOp* arithOp=0;
12970 if(addOp)
12971 arithOp=addOp;
12972 else if(subtractOp)
12973 arithOp=subtractOp;
12974 else
12975 return false;
12976 ROSE_ASSERT(arithOp!=0);
12977 if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_lhs_operand()))) {
12978 // cases : var + incr, var - incr
12979 incr_var=varRefExp;
12980 stepast=isSgBinaryOp(arithOp)->get_rhs_operand();
12981 } else if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_rhs_operand()))) {
12982 if(isSgAddOp(arithOp)) {
12983 // case : incr + var (not allowed: incr-var)
12984 incr_var=varRefExp;
12985 stepast=isSgBinaryOp(arithOp)->get_lhs_operand();
12986 }
12987 }
12988 break;
12989 } // end of V_AssignOp
12990 default:
12991 return false;
12992 }
12993
12994 if (incr_var == NULL)
12995 return false;
12996 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12997 return false;
12998
12999
13000 // single entry and single exit?
13001 // only for C for loop for now
13002 // TODO: Fortran support later
13003 if (fs && !isStructuredBlock(fs->get_loop_body()) )
13004 return false;
13005
13006 // return loop information if requested
13007 if (ivar != NULL)
13008 *ivar = ivarname;
13009 if (lb != NULL)
13010 *lb = lbast;
13011 if (ub != NULL)
13012 *ub = ubast;
13013 if (step != NULL)
13014 *step = stepast;
13015 if (body != NULL) {
13016 *body = fs->get_loop_body();
13017 }
13018 return true;
13019}
13020
13023{
13024 ROSE_ASSERT(loop != NULL);
13025 ROSE_ASSERT(lb != NULL);
13026 SgForStatement* forstmt = isSgForStatement(loop);
13027 SgFortranDo* dostmt = isSgFortranDo(loop);
13028 // ROSE_ASSERT(forstmt!= NULL);
13029
13030 if (forstmt != NULL)
13031 {
13032 // two cases: init_stmt is
13033 // SgExprStatement (assignment) like i=0;
13034 // SgVariableDeclaration int i =0 or
13035 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignOp);
13036 if (testList.size()>0) // assignment statement
13037 {
13038 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13039 SgAssignOp * assignop = isSgAssignOp((*testList.begin()));
13040 ROSE_ASSERT(assignop);
13041 if( assignop->get_rhs_operand()->get_lvalue())
13042 lb->set_lvalue(true);
13043 assignop->set_rhs_operand(lb);
13044 lb->set_parent(assignop);
13045 //TODO what happens to the original rhs operand?
13046 }
13047 else // variable declaration case
13048 {
13049 // SgVariableDeclaration
13050 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignInitializer );
13051 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13052 SgAssignInitializer* init = isSgAssignInitializer((*testList.begin()));
13053 ROSE_ASSERT(init != NULL);
13054 init->set_operand(lb);
13055 lb->set_parent(init);
13056 //TODO what happens to the original rhs operand?
13057 }
13058 }
13059 else if (dostmt != NULL)
13060 {
13061 SgExpression* init = dostmt->get_initialization();
13062 ROSE_ASSERT (init != NULL);
13063 SgAssignOp * a_op = isSgAssignOp (init);
13064 ROSE_ASSERT (a_op!=NULL);
13065 a_op->set_rhs_operand(lb);
13066 lb->set_parent(a_op);
13067 //TODO delete the previous operand?
13068 }
13069 else
13070 {
13071 cerr<<"Error. SageInterface::setLoopLowerBound(), illegal loop type:"<< loop->class_name()<<endl;
13072 ROSE_ASSERT (false);
13073 }
13074}
13075
13078{
13079 ROSE_ASSERT(loop != NULL);
13080 ROSE_ASSERT(ub != NULL);
13081 SgForStatement* forstmt = isSgForStatement(loop);
13082 // ROSE_ASSERT(forstmt!= NULL);
13083 SgFortranDo* dostmt = isSgFortranDo(loop);
13084 if (forstmt != NULL)
13085 {
13086 // set upper bound expression
13087 SgBinaryOp * binop= isSgBinaryOp(isSgExprStatement(forstmt->get_test())->get_expression());
13088 ROSE_ASSERT(binop != NULL);
13089 binop->set_rhs_operand(ub);
13090 ub->set_parent(binop);
13091 }
13092 else if (dostmt != NULL)
13093 {
13094 dostmt->set_bound(ub);
13095 ub->set_parent(dostmt);
13096 //TODO delete the original bound expression
13097 }
13098 else
13099 {
13100 cerr<<"Error. SageInterface::setLoopUpperBound(), illegal loop type:"<< loop->class_name()<<endl;
13101 ROSE_ASSERT (false);
13102 }
13103
13104}
13105
13108{
13109 ROSE_ASSERT(loop != NULL);
13110 ROSE_ASSERT(stride != NULL);
13111 SgForStatement* forstmt = isSgForStatement(loop);
13112 SgFortranDo * dostmt = isSgFortranDo (loop);
13113 // ROSE_ASSERT(forstmt!= NULL);
13114 if (dostmt != NULL)
13115 {
13116 dostmt->set_increment(stride);
13117 stride->set_parent(dostmt);
13118 //TODO delete original increment expression
13119 }
13120 else if (forstmt != NULL)
13121 {
13122 // set stride expression
13123 // case 1: i++ change to i+=stride
13124 Rose_STL_Container<SgNode*> testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusPlusOp);
13125 if (testList.size()>0)
13126 {
13127 ROSE_ASSERT(testList.size() == 1); // should have only one
13128 SgVarRefExp *loopvarexp = isSgVarRefExp(SageInterface::deepCopy
13129 (isSgPlusPlusOp( *testList.begin())->get_operand()));
13130 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13131 forstmt->set_increment(plusassignop);
13132 }
13133
13134 // case 1.5: i-- also changed to i+=stride
13135 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusMinusOp);
13136 if (testList.size()>0)
13137 {
13138 ROSE_ASSERT(testList.size()==1);// should have only one
13139 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13140 (isSgMinusMinusOp(*testList.begin())->get_operand()));
13141 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13142 forstmt->set_increment(plusassignop);
13143 }
13144
13145 // case 2: i+=X
13146 testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusAssignOp);
13147 if (testList.size()>0)
13148 {
13149 ROSE_ASSERT(testList.size()==1);// should have only one
13150 SgPlusAssignOp * assignop = isSgPlusAssignOp(*(testList.begin()));
13151 ROSE_ASSERT(assignop!=NULL);
13152 assignop->set_rhs_operand(stride);
13153 }
13154
13155 // case 2.5: i-=X changed to i+=stride
13156 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusAssignOp);
13157 if (testList.size()>0)
13158 {
13159 ROSE_ASSERT(testList.size()==1);// should have only one
13160 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13161 (isSgMinusAssignOp(*testList.begin())->get_lhs_operand()));
13162 SgExprStatement* exprstmt = isSgExprStatement((*testList.begin())->get_parent());
13163 ROSE_ASSERT(exprstmt !=NULL);
13164 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13165 exprstmt->set_expression(plusassignop);
13166 }
13167
13168#if 0 // [Robb Matzke 2021-03-17]
13169 // DQ (1/3/2007): I think this is a meaningless statement.
13170 testList.empty();
13171#endif
13172 // case 3: i=i + X or i =X +i i
13173 // TODO; what if users use i*=,etc ??
13174 // send out a warning: not canonical FOR/DO loop
13175 // or do this in the real frontend. MUST conform to canonical form
13176 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgAddOp);
13177 if (testList.size()>0)
13178 {
13179 ROSE_ASSERT(testList.size()==1);// should have only one ??
13180 // consider only the top first one
13181 SgAddOp * addop = isSgAddOp(*(testList.begin()));
13182 ROSE_ASSERT(addop!=NULL);
13183 string loopvar= (isSgVarRefExp(isSgAssignOp(addop->get_parent())->get_lhs_operand())->get_symbol()->get_name()).getString();
13184 if (isSgVarRefExp(addop->get_rhs_operand())!=NULL)
13185 {
13186 if ((isSgVarRefExp(addop->get_rhs_operand())->get_symbol()->get_name()).getString() ==loopvar)
13187 addop->set_lhs_operand(stride);
13188 else
13189 addop->set_rhs_operand(stride);
13190 }
13191 else
13192 addop->set_rhs_operand(stride);
13193 }
13194
13195 // case 3.5: i=i - X
13196 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgSubtractOp);
13197 if (testList.size()>0)
13198 {
13199 ROSE_ASSERT(testList.size()==1);// should have only one ??
13200 // consider only the top first one
13201 SgSubtractOp * subtractop = isSgSubtractOp(*(testList.begin()));
13202 ROSE_ASSERT(subtractop!=NULL);
13203 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13204 (isSgSubtractOp(*testList.begin())->get_lhs_operand()));
13205 SgAssignOp *assignop = isSgAssignOp((*testList.begin())->get_parent());
13206 ROSE_ASSERT(assignop !=NULL);
13207 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13208 assignop->set_rhs_operand(plusassignop);
13209 }
13210 }
13211 else
13212 {
13213 cerr<<"Error. SageInterface::setLoopStride(), illegal loop type:"<< loop->class_name()<<endl;
13214 ROSE_ASSERT (false);
13215
13216 }
13217}
13218
13222bool SageInterface::isAssignmentStatement(SgNode* s, SgExpression** lhs/*=NULL*/, SgExpression** rhs/*=NULL*/, bool* readlhs/*=NULL*/)
13223{
13224 SgExprStatement *n = isSgExprStatement(s);
13225 SgExpression *exp = (n != 0)? n->get_expression() : isSgExpression(s);
13226 if (exp != 0) {
13227 switch (exp->variantT()) {
13228 case V_SgPlusAssignOp:
13229 case V_SgMinusAssignOp:
13230 case V_SgAndAssignOp:
13231 case V_SgIorAssignOp:
13232 case V_SgMultAssignOp:
13233 case V_SgDivAssignOp:
13234 case V_SgModAssignOp:
13235 case V_SgXorAssignOp:
13236 case V_SgAssignOp:
13237 {
13238 SgBinaryOp* s2 = isSgBinaryOp(exp);
13239 if (lhs != 0)
13240 *lhs = s2->get_lhs_operand();
13241 if (rhs != 0) {
13242 SgExpression* init = s2->get_rhs_operand();
13243 if ( init->variantT() == V_SgAssignInitializer)
13244 init = isSgAssignInitializer(init)->get_operand();
13245 *rhs = init;
13246 }
13247 if (readlhs != 0)
13248 *readlhs = (exp->variantT() != V_SgAssignOp);
13249 return true;
13250 }
13251 default:
13252 return false;
13253 }
13254 }
13255 return false;
13256}
13257
13258
13259void
13261 {
13262 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,V_SgGotoStatement);
13263 for (size_t i = 0; i < gotos.size(); ++i)
13264 {
13265 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13266 SgLabelStatement* ls = gs->get_label();
13267 SgBasicBlock* lsParent = isSgBasicBlock(ls->get_parent());
13268 if (!lsParent) continue;
13269 SgStatementPtrList& bbStatements = lsParent->get_statements();
13270
13271 size_t j = std::find(bbStatements.begin(), bbStatements.end(), ls) - bbStatements.begin();
13272
13273 ROSE_ASSERT (j != bbStatements.size());
13274
13275 while (j < bbStatements.size() - 1 && isSgLabelStatement(bbStatements[j + 1]))
13276 {
13277 ++j;
13278 }
13279 gs->set_label(isSgLabelStatement(bbStatements[j]));
13280 }
13281 }
13282
13283bool SageInterface::mergeDeclarationAndAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt, bool removeAssignStmt /*= true*/)
13284{
13285 return mergeAssignmentWithDeclaration (assign_stmt, decl, removeAssignStmt);
13286}
13288
13292bool SageInterface::mergeAssignmentWithDeclaration(SgExprStatement* assign_stmt, SgVariableDeclaration* decl, bool removeAssignStmt /*= true*/)
13293{
13294 bool rt= true;
13295 ROSE_ASSERT(decl != NULL);
13296 ROSE_ASSERT(assign_stmt != NULL);
13297
13298 // Sanity check of assign statement: must be a form of var = xxx;
13299 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13300 if (assign_op == NULL)
13301 return false;
13302 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13303 if (assign_op_var == NULL) return false;
13304
13305 // Sanity check of the variable declaration: it should not have an existing initializer
13307 if (decl_var->get_initptr()!= NULL ) return false;
13308
13309 // check if two variables match
13310 // In translation, it is possible the declaration has not yet been inserted into its scope.
13311 // finding its symbol can return NULL.
13312 // But we still want to do the merge.
13313 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13314 if (decl_var_symbol!=NULL)
13315 {
13316 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13317 if (assign_op_var->get_symbol() != decl_var_symbol) return false;
13318 }
13319 else
13320 { // fallback to comparing variable names instead
13321 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13322 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name()) return false;
13323 }
13324
13325 // Everything looks fine now. Do the merge.
13327
13328 // Must preserve the proprecessing information of the original assign_stmt
13329 // use appending (not prepending) so the order of decl's comments and assign_stmt's comments can be preserved
13330 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13331
13332 // removeStatement() does not support removing a statement which is not inside a container.
13333 // But sometimes we do need to remove such a statement and replace it with a new one.
13334 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13335 // TODO: improve removeStatement() which uses low level rewritting.
13336 if (removeAssignStmt)
13337 SageInterface::removeStatement (assign_stmt);
13338// SageInterface::deepDelete (assign_stmt);
13340 decl_var->set_initptr(initor);
13341 initor->set_parent(decl_var);
13342
13343 return rt;
13344}
13345
13347{
13348 bool rt= true;
13349
13350 // Sanity check of assign statement: must be a form of var = xxx;
13351 ROSE_ASSERT(assign_stmt != NULL);
13352 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13353 if (assign_op == NULL)
13354 return false;
13355 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13356 if (assign_op_var == NULL)
13357 return false;
13358
13359 // Sanity check of the variable declaration: it should not have an existing initializer
13360 ROSE_ASSERT(decl != NULL);
13362 if (decl_var->get_initptr()!= NULL)
13363 return false;
13364
13365 // check if two variables match
13366 // In translation, it is possible the declaration has not yet been inserted into its scope.
13367 // finding its symbol can return NULL.
13368 // But we still want to do the merge.
13369 ROSE_ASSERT(decl_var != NULL);
13370 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13371 if (decl_var_symbol != NULL) {
13372 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13373 if (assign_op_var->get_symbol() != decl_var_symbol)
13374 return false;
13375 }
13376 else
13377 { // fallback to comparing variable names instead
13378 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13379 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name())
13380 return false;
13381 }
13382
13383 // Everything looks fine now. Do the merge.
13384 // It is implemented by
13385 // 1. copy rhs to the decl's rhs,
13386 // 2. then move the decl to the place of the assignment,
13387 // 3. then remove the assignment
13388 //
13389 // Copy rhs to be initializer
13392 decl_var->set_initptr(initor);
13393 initor->set_parent(decl_var);
13394
13395 // move proprocessing info. attached before decl to its next statement's front, using prepending to preserve the original order
13396 SgStatement* next_stmt = SageInterface::getNextStatement (decl);
13397 SageInterface::movePreprocessingInfo(decl, next_stmt, PreprocessingInfo::before, PreprocessingInfo::before, true);
13398
13399 // removeStatement() does not support removing a statement which is not inside a container.
13400 // But sometimes we do need to remove such a statement and replace it with a new one.
13401 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13402 // TODO: improve removeStatement() which uses low level rewritting.
13403
13404 // Now move the declaration to a new position, right before the assignment statement
13406 SageInterface::insertStatementBefore(assign_stmt, decl, false);
13407
13408 // preserve preprocessing info. attached to assign_stmt before removing it , using append (last false)
13409 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13410
13411 // Original assignment statement should be removed
13412 SageInterface::removeStatement (assign_stmt);
13413 // SageInterface::deepDelete (decl);
13414
13415 return rt;
13416}
13417// Split a variable declaration with an rhs assignment into two statements: a declaration and an assignment.
13418// Return the generated assignment statement, if any
13420{
13421 SgExprStatement* rt = NULL;
13422 ROSE_ASSERT (decl != NULL);
13423
13425 SgInitializer* initor = decl_var ->get_initptr();
13426 if (initor == NULL)
13427 rt = NULL;
13428 else
13429 {
13430 // Liao, 2021/10/21, we have to support all sorts of initializers, including aggregate initializer
13431 SgExpression * rhs=NULL;
13432 if (SgAssignInitializer * ainitor = isSgAssignInitializer (initor))
13433 rhs = ainitor->get_operand();
13434 else
13435 rhs = initor;
13436
13437 // we deep copy the rhs operand
13438 rt = buildAssignStatement (buildVarRefExp(decl_var) , deepCopy(rhs));
13439 decl_var->set_initptr(NULL);
13440 //TODO clean up initor
13441 insertStatementAfter ( decl, rt );
13442 }
13443 return rt;
13444}
13446ROSE_DLL_API int SageInterface::splitVariableDeclaration (SgScopeStatement* scope, bool topLevelOnly /* = true */)
13447{
13448 int count = 0;
13449 if (!topLevelOnly)
13450 {
13451 cerr<<"SageInterface::splitVariableDeclaration() topLevelOnly == false is not yet implemented."<<endl;
13452 ROSE_ASSERT (false);
13453 }
13454
13455 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVariableDeclaration);
13456 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13457 {
13458 SgVariableDeclaration *decl= isSgVariableDeclaration(*i);
13459 if (topLevelOnly)
13460 {
13461 ROSE_ASSERT(decl != NULL);
13462 if (decl->get_scope() == scope)
13463 {
13465 count ++;
13466 }
13467 }
13468 }
13469 return count;
13470}
13471
13472void SageInterface::collectVarRefs(SgLocatedNode* root, std::vector<SgVarRefExp* > & result)
13473{
13474 ROSE_ASSERT (root != NULL);
13475// std::vector<SgVarRefExp* > result;
13476
13477 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgVarRefExp);
13478 // AST query won't find variables used in types
13480
13481 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13482 {
13483 SgVarRefExp *vRef = isSgVarRefExp(*i);
13484 ROSE_ASSERT (vRef != NULL);
13485 result.push_back(vRef);
13486 }
13487}
13488
13489int SageInterface::collectVariableReferencesInArrayTypes(SgLocatedNode* root, Rose_STL_Container<SgNode*> & currentVarRefList)
13490{
13491 int rt = 0;
13492 ROSE_ASSERT (root != NULL);
13493 Rose_STL_Container<SgNode*> constructorList= NodeQuery::querySubTree(root, V_SgConstructorInitializer);
13494 for (size_t i =0; i< constructorList.size(); i++)
13495 {
13496 SgConstructorInitializer * c_init = isSgConstructorInitializer (constructorList[i]);
13497 if (SgArrayType* a_type = isSgArrayType(c_init->get_expression_type()))
13498 {
13499 Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree (a_type->get_index(),V_SgVarRefExp);
13500 for (size_t j =0 ; j< varList.size(); j++)
13501 {
13502 SgVarRefExp* var_exp = isSgVarRefExp(varList[j]) ;
13503 currentVarRefList.push_back(var_exp);
13504//TODO: these variable references do have special scopes, how to communicate to users?
13505// specialVarRefScopeExp[var_exp] = c_init ;
13506 rt ++;
13507 }
13508 }
13509 }
13510 return rt;
13511}
13512
13513namespace SageInterface { // A few internal helper classes
13514
13516 {
13517 SgAndOp* op;
13518
13519 public:
13520 AndOpGenerator(SgAndOp* op): op(op) {}
13521
13522 virtual SgStatement* generate(SgExpression* lhs)
13523 {
13524 if (lhs==NULL)
13525 return NULL;
13526 SgTreeCopy treeCopy;
13527 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13528 ROSE_ASSERT (lhsCopy);
13529 SgIfStmt* tree =
13536 return tree;
13537 }
13538 };
13539
13541 {
13542 SgOrOp* op;
13543
13544 public:
13545 OrOpGenerator(SgOrOp* op): op(op) {}
13546
13547 virtual SgStatement* generate(SgExpression* lhs)
13548 {
13549 if (lhs==NULL)
13550 return NULL;
13551 SgTreeCopy treeCopy;
13552 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13553 ROSE_ASSERT (lhsCopy);
13554 SgIfStmt* tree =
13561 return tree;
13562 }
13563 };
13564
13566 {
13567 SgConditionalExp* op;
13568
13569 public:
13571
13572 virtual SgStatement* generate(SgExpression* lhs)
13573 {
13574 if (lhs==NULL)
13575 return NULL;
13576 SgTreeCopy treeCopy;
13577 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13578 ROSE_ASSERT (lhsCopy);
13579 SgIfStmt* tree =
13586 return tree;
13587 }
13588 };
13589
13590} // end of namespace for the helper classes
13591
13594{
13595 ROSE_ASSERT(from != NULL);
13596
13597#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
13598#if 0 // This is not accurate for template class specializations. We disable this assertion for now. The worst case is compilation error later.
13600 std::cerr << "Type " << from->get_type()->unparseToString() << " of expression " << from->unparseToString() << " is not copy constructible" << std::endl;
13601 ROSE_ASSERT (false);
13602 }
13603
13604 assert (SageInterface::isCopyConstructible(from->get_type())); // How do we report errors?
13605#endif
13606 SgStatement* stmt = getStatementOfExpression(from);
13607 assert (stmt);
13608 if (!isSgForInitStatement(stmt->get_parent())) {
13609 //SageInterface::ensureBasicBlockAsParent(stmt);
13610 // no return value is accepted. Only the optional transformation matters
13611 if (isBodyStatement(stmt) && !isSgBasicBlock(stmt))
13613 }
13614
13615 SgScopeStatement* parent = isSgScopeStatement(stmt->get_parent());
13616 // cout << "parent is a " << (parent ? parent->sage_class_name() : "NULL") << endl;
13617 if (!parent && isSgForInitStatement(stmt->get_parent()))
13618 parent = isSgScopeStatement(stmt->get_parent()->get_parent()->get_parent());
13619 assert (parent);
13620 // cout << "parent is a " << parent->sage_class_name() << endl;
13621 // cout << "parent is " << parent->unparseToString() << endl;
13622 // cout << "stmt is " << stmt->unparseToString() << endl;
13623 SgName varname = "rose_temp__";
13624 if (newName == "") {
13625 varname << ++SageInterface::gensym_counter;
13626 } else {
13627 varname = newName;
13628 }
13629
13630 SgType* vartype = from->get_type();
13631 SgNode* fromparent = from->get_parent();
13632 vector<SgExpression*> ancestors;
13633 for (SgExpression *expr = from, *anc = isSgExpression(fromparent); anc != 0;
13634 expr = anc, anc = isSgExpression(anc->get_parent()))
13635 {
13636 if ((isSgAndOp(anc) && expr != isSgAndOp(anc)->get_lhs_operand()) ||
13637 (isSgOrOp(anc) && expr != isSgOrOp(anc)->get_lhs_operand()) ||
13638 (isSgConditionalExp(anc) && expr != isSgConditionalExp(anc)->get_conditional_exp()))
13639 ancestors.push_back(anc); // Closest first
13640 }
13641 // cout << "This expression to split has " << ancestors.size() << " ancestor(s)" << endl;
13642 for (vector<SgExpression*>::reverse_iterator ai = ancestors.rbegin(); ai != ancestors.rend(); ++ai)
13643 {
13644 StatementGenerator* gen;
13645 switch ((*ai)->variantT()) {
13646 case V_SgAndOp:
13647 gen = new AndOpGenerator(isSgAndOp(*ai)); break;
13648 case V_SgOrOp:
13649 gen = new OrOpGenerator(isSgOrOp(*ai)); break;
13650 case V_SgConditionalExp:
13651 gen = new ConditionalExpGenerator(isSgConditionalExp(*ai)); break;
13652 default: assert (!"Should not happen"); abort();
13653 }
13655 delete gen;
13656 } // for
13657 if (ancestors.size() != 0) {
13658 return splitExpression(from);
13659 // Need to recompute everything if there were ancestors
13660 }
13661 SgVariableDeclaration* vardecl = SageBuilder::buildVariableDeclaration(varname, vartype, NULL, parent);
13663 ROSE_ASSERT (sym);
13664 SgInitializedName* initname = sym->get_declaration();
13665 ROSE_ASSERT (initname);
13667 replaceExpressionWithExpression(from, varref);
13668 // std::cout << "Unparsed 3: " << fromparent->sage_class_name() << " --- " << fromparent->unparseToString() << endl;
13669 // cout << "From is a " << from->sage_class_name() << endl;
13671 initname->set_initializer(ai);
13672 ai->set_parent(initname);
13673 myStatementInsert(stmt, vardecl, true);
13674 // vardecl->set_parent(stmt->get_parent());
13675 // FixSgTree(vardecl);
13676 // FixSgTree(parent);
13677 return ai;
13678
13679#else
13680 return NULL;
13681#endif
13682
13683} //splitExpression()
13684
13687 struct SplitStatementGenerator: public StatementGenerator {
13688 SgExpression* expr;
13689 virtual SgStatement* generate(SgExpression* answer) {
13690 using namespace SageBuilder;
13691 return buildBasicBlock(buildAssignStatement(answer, expr));
13692 }
13693 };
13694 SplitStatementGenerator gen;
13695 gen.expr = expr;
13697 }
13698
13700 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,
13701 V_SgGotoStatement);
13702 map<SgLabelStatement*, SgLabelStatement*> labelsToReplace; for
13703 (size_t i = 0; i < gotos.size(); ++i) {
13704 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13705 SgBasicBlock* gsParent = isSgBasicBlock(gs->get_parent());
13706 if (!gsParent) continue;
13707 SgStatementPtrList& bbStatements = gsParent->get_statements();
13708 size_t j = std::find(bbStatements.begin(), bbStatements.end(), gs)
13709 - bbStatements.begin();
13710 ROSE_ASSERT (j != bbStatements.size());
13711 if (j == 0) continue;
13712 if (isSgLabelStatement(bbStatements[j - 1])) {
13713 labelsToReplace[isSgLabelStatement(bbStatements[j - 1])] =
13714 gs->get_label();
13715 }
13716 }
13717 for (size_t i = 0; i < gotos.size(); ++i) {
13718 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13719 SgLabelStatement* oldLabel = gs->get_label();
13720 while (labelsToReplace.find(oldLabel) != labelsToReplace.end()) {
13721 oldLabel = labelsToReplace[oldLabel];
13722 }
13723 gs->set_label(oldLabel);
13724 }
13725 }
13726
13728 switch (e->variantT()) {
13729#ifdef _MSC_VER
13730 // DQ (11/28/2009): This fixes a warning in MSVC (likely p_value should be a "bool" instead of an "int").
13731 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() != 0);
13732#else
13733 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() == true);
13734#endif
13735 case V_SgIntVal: return isSgIntVal(e)->get_value() != 0;
13736 case V_SgCastExp: return isConstantTrue(isSgCastExp(e)->get_operand());
13737 case V_SgNotOp: return isConstantFalse(isSgNotOp(e)->get_operand());
13738 case V_SgAddressOfOp: return true;
13739 default: return false;
13740 }
13741 }
13742
13744 switch (e->variantT()) {
13745 case V_SgBoolValExp: return isSgBoolValExp(e)->get_value() == false;
13746 case V_SgIntVal: return isSgIntVal(e)->get_value() == 0;
13747 case V_SgCastExp: return
13748 isConstantFalse(isSgCastExp(e)->get_operand());
13749 case V_SgNotOp: return isConstantTrue(isSgNotOp(e)->get_operand());
13750 default: return false;
13751 }
13752 }
13753
13755 SgExpression* e) {
13756 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13757 if (!fc) return false;
13758 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13759 if (fr == NULL) return false;
13760 return fr->get_symbol()->get_declaration() == decl;
13761 }
13762
13763 bool SageInterface::isCallToParticularFunction(const std::string& qualifiedName, size_t
13764 arity, SgExpression* e) {
13765 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13766 if (!fc) return false;
13767 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13768 if (fr == NULL) return false;
13769 string name =
13770 fr->get_symbol()->get_declaration()->get_qualified_name().getString();
13771 return (name == qualifiedName &&
13772 fc->get_args()->get_expressions().size() == arity);
13773 }
13774
13776 {
13777 ROSE_ASSERT( e != NULL);
13778 // We enforce that the source expression is fully attached to the AST
13779 // Too strict, the source expression can be just built and not attached.
13780 // Liao, 9/21/2009
13781// ROSE_ASSERT( e->get_parent() != NULL);
13782 return deepCopy(e);
13783 }
13784
13786 {
13787 return deepCopy(s);
13788 }
13789
13790 //----------------- add into AST tree --------------------
13792 {
13793 ROSE_ASSERT(expList);
13794 ROSE_ASSERT(exp);
13795 expList->append_expression(exp);
13796 exp->set_parent(expList);
13797 }
13798
13799 void SageInterface::appendExpressionList(SgExprListExp *expList, const std::vector<SgExpression*>& exp)
13800 {
13801 for (size_t i = 0; i < exp.size(); ++i)
13802 appendExpression(expList, exp[i]);
13803 }
13804
13805# if 0
13806 // DQ (11/25/2011): Moved to the header file so that it could be seen as a template function.
13807
13808 // TODO consider the difference between C++ and Fortran
13809 // fixup the scope of arguments,no symbols for nondefining function declaration's arguments
13810template <class actualFunction>
13811void
13812// SageInterface::setParameterList(SgFunctionDeclaration * func,SgFunctionParameterList * paralist)
13813SageInterface::setParameterList(actualFunction * func,SgFunctionParameterList * paralist)
13814 {
13815 // DQ (11/25/2011): Modified this to be a templated function so that we can handle both
13816 // SgFunctionDeclaration and SgTemplateFunctionDeclaration (and their associated member
13817 // function derived classes).
13818
13819 ROSE_ASSERT(func);
13820 ROSE_ASSERT(paralist);
13821
13822 // Warn to users if a paralist is being shared
13823 if (paralist->get_parent() !=NULL)
13824 {
13825 cerr << "Waring! Setting a used SgFunctionParameterList to function: "
13826 << (func->get_name()).getString()<<endl
13827 << " Sharing parameter lists can corrupt symbol tables!"<<endl
13828 << " Please use deepCopy() to get an exclusive parameter list for each function declaration!"<<endl;
13829 // ROSE_ASSERT(false);
13830 }
13831
13832 // Liao,2/5/2008 constructor of SgFunctionDeclaration will automatically generate SgFunctionParameterList, so be cautious when set new paralist!!
13833 if (func->get_parameterList() != NULL)
13834 if (func->get_parameterList() != paralist)
13835 delete func->get_parameterList();
13836
13837 func->set_parameterList(paralist);
13838 paralist->set_parent(func);
13839 }
13840#endif
13841
13842// static
13843SgVariableSymbol* addArg(SgFunctionParameterList *paraList, SgInitializedName* initName, bool isPrepend)
13844 {
13845 ROSE_ASSERT(paraList != NULL);
13846 ROSE_ASSERT(initName != NULL);
13847
13848 if (isPrepend == true)
13849 paraList->prepend_arg(initName);
13850 else
13851 paraList->append_arg(initName);
13852
13853 // DQ (12/4/2011): If this is going to be set, make sure it will not be over written.
13854 // initName->set_parent(paraList);
13855 if (initName->get_parent() == NULL)
13856 initName->set_parent(paraList);
13857
13858 ROSE_ASSERT(initName->get_parent() == paraList);
13859
13860 SgFunctionDeclaration* func_decl= isSgFunctionDeclaration(paraList->get_parent());
13861
13862 // DQ (12/4/2011): This will not be true for function parameter lists in SgTemplateFunctionDeclaration cases.
13863 // Also in typical use the SgFunctionDeclaration is not known yet so the parent is not set.
13864 // ROSE_ASSERT(paraList->get_parent() != NULL);
13865 // ROSE_ASSERT(func_decl != NULL);
13866
13867 SgScopeStatement* scope = NULL;
13868 if (func_decl != NULL)
13869 {
13870 if ((func_decl->get_definingDeclaration()) == func_decl )
13871 {
13872 // defining function declaration, set scope and symbol table
13873 SgFunctionDefinition* func_def = func_decl->get_definition();
13874 ROSE_ASSERT(func_def);
13875 scope = func_def;
13876 }
13877 else
13878 {
13879 // nondefining declaration, set scope only, currently set to decl's scope, TODO
13880 scope = func_decl->get_scope();
13881 }
13882
13883 // fix up declptr of the init name
13884 initName->set_declptr(func_decl);
13885 }
13886
13887 // 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
13888 // that initName already has a scope.
13889 //
13890 // DQ (12/4/2011): Added check...(fails for case of SgTypeEllipse).
13891 // ROSE_ASSERT(initName->get_scope() != NULL);
13892 // ROSE_ASSERT(initName->get_scope() != NULL || isSgTypeEllipse(initName->get_type()) != NULL);
13893
13894 // ROSE_ASSERT (scope); -- scope may not be set because the function declaration may not have been inserted anywhere
13895
13896 initName->set_scope(scope);
13897 if (scope != NULL)
13898 {
13899 SgVariableSymbol* sym = isSgVariableSymbol(initName->get_symbol_from_symbol_table());
13900 if (sym == NULL)
13901 {
13902 sym = new SgVariableSymbol(initName);
13903 scope->insert_symbol(initName->get_name(), sym);
13904 sym->set_parent(scope->get_symbol_table());
13905 }
13906 return sym;
13907 }
13908 else
13909 {
13910 return NULL;
13911 }
13912 }
13913
13915{
13916 return addArg(paraList,initName,false);
13917}
13918
13920{
13921 return addArg(paraList,initName,true);
13922}
13923
13925{
13926 ROSE_ASSERT(decl);
13927 ROSE_ASSERT(pragma);
13928 if (decl->get_pragma()!=NULL) delete (decl->get_pragma());
13929 decl->set_pragma(pragma);
13930 pragma->set_parent(decl);
13931}
13932
13933
13935//TODO should we ensureBasicBlockAsScope(scope) ? like ensureBasicBlockAsParent(targetStmt);
13936//It might be well legal to append the first and only statement in a scope!
13938 {
13939 // DQ (4/3/2012): Simple globally visible function to call (used for debugging in ROSE).
13940 void testAstForUniqueNodes ( SgNode* node );
13941
13942#if 0
13943 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
13944#endif
13945
13946 // DQ (6/19/2012): Exit as a test...
13947 // ROSE_ASSERT(isSgClassDeclaration(stmt) == NULL);
13948
13949 if (scope == NULL)
13950 {
13951#if 0
13952 printf (" --- scope was not specified as input! \n");
13953#endif
13955 }
13956
13957 ROSE_ASSERT(stmt != NULL);
13958 ROSE_ASSERT(scope != NULL);
13959
13960#if 0
13961 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
13962#endif
13963
13964#if 0
13965 // DQ (2/2/2010): This fails in the projects/OpenMP_Translator "make check" tests.
13966 // DQ (1/2/2010): Introducing test that are enforced at lower levels to catch errors as early as possible.
13967 SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(stmt);
13968 if (declarationStatement != NULL)
13969 {
13970 ROSE_ASSERT(declarationStatement->get_firstNondefiningDeclaration() != NULL);
13971 ROSE_ASSERT(declarationStatement->get_definingDeclaration() != NULL);
13972 }
13973#endif
13974
13975#if 0
13976 // This fix breaks other transformations.
13977 // It is better to do this explicitly as needed before calling appendStatement();
13978 // Liao 10/19/2010
13979 // In rare cases, we are moving the statement from its original scope to another scope
13980 // We have to remove it from its original scope before append it to the new scope
13981 SgNode* old_parent= stmt->get_parent();
13982 if (old_parent)
13983 {
13984 removeStatement(stmt);
13985 }
13986#endif
13987
13988#if 0
13989 // catch-all for statement fixup
13990 // Must fix it before insert it into the scope,
13991 fixStatement(stmt,scope);
13992
13993 //-----------------------
13994 // append the statement finally
13995 // scope->append_statement (stmt);
13996 scope->insertStatementInScope(stmt,false);
13997 stmt->set_parent(scope); // needed?
13998#else
13999 // DQ (7/12/2012): Skip adding when this is a non-autonomous type declaration.
14000 bool skipAddingStatement = false;
14001 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
14002 if (classDeclaration != NULL)
14003 {
14004 // DQ (7/9/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14005#if 0
14006 if (classDeclaration->get_parent() != NULL)
14007 {
14008 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());
14009 }
14010#endif
14011
14012#if 1
14013 // DQ (6/9/2013): This is the original code...
14014 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false);
14015#else
14016 // 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).
14017 // This fails to add enough statements to the AST.
14018 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false) || (classDeclaration->get_parent() != NULL);
14019#endif
14020
14021 // DQ (6/26/2013): Don't just check for SgTemplateInstantiationDecl, but also for SgClassDeclaration.
14022 // DQ (6/9/2013): Check if this is a SgTemplateInstantiationDecl, since it might be appearing
14023 // twice as a result of a template argument being instantiated and we only want to add it into
14024 // the scope once. This happens for test2013_198.C and I can't find a better solution.
14025 if (classDeclaration != NULL && scope->containsOnlyDeclarations() == true)
14026 {
14027 // Check if this instnatiated template has already been added to the scope.
14028
14029 // DQ (6/26/2013): This is a newer alternative to test for an existing statement in a scope.
14030 // const SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
14031 // SgDeclarationStatementPtrList::const_iterator existingDeclaration = find(declarationList.begin(),declarationList.end(),classDeclaration);
14032 bool statementAlreadyExistsInScope = scope->statementExistsInScope(classDeclaration);
14033 if (statementAlreadyExistsInScope == true)
14034 {
14035 if (isSgTemplateInstantiationDecl(classDeclaration) != NULL)
14036 {
14037// DQ (9/13/2014): Clean up this output when not printing developer warnings.
14038// #if 1
14039#if PRINT_DEVELOPER_WARNINGS
14040 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",
14041 classDeclaration,classDeclaration->class_name().c_str(),scope,scope->class_name().c_str());
14042#endif
14043 }
14044#if 1
14045 else
14046 {
14047#if 1
14048 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",
14049 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14050#endif
14051 }
14052#endif
14053 skipAddingStatement = true;
14054 }
14055 }
14056 }
14057 else
14058 {
14059 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(stmt);
14060 if (enumDeclaration != NULL)
14061 {
14062 // DQ (7/12/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14063 skipAddingStatement = (enumDeclaration->get_isAutonomousDeclaration() == false);
14064 }
14065 }
14066
14067#if 0
14068 // DQ (6/26/2013): This is an attempt to support better testing of possible redundant statements
14069 // that would be inserted into the current scope. This is however a bit expensive so we are using
14070 // this as a way to also debug the new cases where this happens.
14071 bool statementAlreadyExistsInScope = scope->statementExistsInScope(stmt);
14072 if (skipAddingStatement == false && statementAlreadyExistsInScope == true)
14073 {
14074#if 0
14075 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",
14076 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14077#endif
14078#if 0
14079 printf ("Exiting as a test! \n");
14080 ROSE_ABORT();
14081#endif
14082 skipAddingStatement = true;
14083 }
14084#endif
14085
14086#if 0
14087 printf (" --- skipAddingStatement = %s \n",skipAddingStatement ? "true" : "false");
14088#endif
14089
14090 if (skipAddingStatement == false)
14091 {
14092 // catch-all for statement fixup
14093 // Must fix it before insert it into the scope,
14094 // printf ("In appendStatementList(): Calling fixStatement() \n");
14095 fixStatement(stmt,scope);
14096 // printf ("DONE: In appendStatementList(): Calling fixStatement() \n");
14097
14098 //-----------------------
14099 // append the statement finally
14100 // scope->append_statement (stmt);
14101#if 0
14102 printf (" --- calling insertStatementInScope(): scope = %p = %s stmt = %p = %s \n",scope,scope->class_name().c_str(),stmt,stmt->class_name().c_str());
14103#endif
14104 scope->insertStatementInScope(stmt,false);
14105
14106 // DQ (6/9/2013): Added comment only: This is needed because some declaration have to have the
14107 // setting of there paremtn pointes delayed until now based on if they appear nested inside of
14108 // other declarations (e.g. "typedef struct { int x; } y;").
14109 stmt->set_parent(scope); // needed?
14110 }
14111#endif
14112
14113 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14114 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14115 // this). Also since this is only operating within a single scope it is likely too specific to C
14116 // instead of addressing the details of C++ where functions can be placed in alternative scopes and
14117 // use name qualification).
14118 // update the links after insertion!
14120 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14121 {
14122 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14123 }
14124
14125#if 0
14126 // DQ (6/26/2013): Turn on this test for debugging ROSE compiling rose.h header file.
14127 // Note that this is a stronger AST subtree test and not the weaker test for a redundant
14128 // statement in a single scope.
14129 // DQ (9/1/2012): this is a debugging mode that we need to more easily turn on and off.
14130 // DQ (4/3/2012): Added test to make sure that the pointers are unique.
14131 testAstForUniqueNodes(scope);
14132#else
14133 // printf ("In SageInterface::appendStatement(): Skipping test for unique statements in subtree \n");
14134#endif
14135 }
14136
14139{
14140 ROSE_ASSERT (stmt != NULL);
14141 ROSE_ASSERT (for_init_stmt != NULL);
14142
14143#if 0
14144 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());
14145#endif
14146
14147 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14148 // to record it being moved (and thus the macroExpansions that it might be associated with having
14149 // to force the macroExpansion's associated statements to be marked as a transformation.
14151
14152#if 0
14153 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());
14154#endif
14155
14156 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14157 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14158 // prepend, we only need to look at the scope.
14160
14161 for_init_stmt->append_init_stmt (stmt);
14162}
14163
14164void
14165SageInterface::appendStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14166 {
14167 for (size_t i = 0; i < stmts.size(); ++i)
14168 {
14169#if 0
14170#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14171 printf ("In appendStatementList(): stmts[i = %" PRIuPTR "] = %p = %s \n",i,stmts[i],stmts[i]->class_name().c_str());
14172 // printf ("In appendStatementList(): stmts[i = %" PRIuPTR "]->get_parent() = %p \n",i,stmts[i]->get_parent());
14173#endif
14174#endif
14175 appendStatement(stmts[i], scope); // Liao 5/15/2013, defer the logic of checking parent pointers to appendStatement()
14176#if 0
14177 if (stmts[i]->get_parent() != NULL)
14178 {
14179#if 0
14180#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14181 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());
14182#endif
14183#endif
14184 appendStatement(stmts[i], scope);
14185 }
14186 else
14187 {
14188 printf (" --- WARNING: In appendStatementList(): stmts[i = %" PRIuPTR "] not added to scope (because stmts[i]->get_parent() == NULL) \n",i);
14189 }
14190#endif
14191 }
14192 }
14193
14196 {
14197 ROSE_ASSERT (stmt != NULL);
14198
14199#if 0
14200 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14201#endif
14202
14203 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.1") == false);
14204
14205 if (scope == NULL)
14206 {
14208 }
14209
14210 ROSE_ASSERT(scope != NULL);
14211 // TODO handle side effect like SageBuilder::appendStatement() does
14212
14213 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.1a") == false);
14214
14215 // Must fix it before insert it into the scope,
14216 // otherwise assertions in insertStatementInScope() would fail
14217 fixStatement(stmt,scope);
14218
14219#if 0
14220 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",
14221 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14222#endif
14223
14224 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.2") == false);
14225
14226 // DQ (12/1/2015): If this is a moved statement then cause it to update internal data structures
14227 // to record it being moved (and thus the macroExpansions that it might be associated with having
14228 // to force the macroExpansion's associated statements to be marked as a transformation.
14230
14231#if 0
14232 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",
14233 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14234#endif
14235
14236 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.3") == false);
14237
14238 // DQ (12/1/2015): Also look at the statements on either side of the location where this statement
14239 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14240 // prepend, we only need to look at the scope.
14242
14243#if 0
14244 printf ("Calling insertStatementInScope() \n");
14245#endif
14246
14247 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.4") == false);
14248 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.4a") == false);
14249
14250 scope->insertStatementInScope(stmt,true);
14251 stmt->set_parent(scope); // needed?
14252
14253 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.5") == false);
14254
14255 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14256 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14257 // this). Also since this is only operating within a single scope it is likely too specific to C
14258 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14259 // use name qualification).
14260 // update the links after insertion!
14262 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14263 {
14264 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14265 }
14266
14267 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.6") == false);
14268
14269#if 0
14270 printf ("Leaving SageInterface::prependStatement() \n");
14271#endif
14272 } // prependStatement()
14273
14274
14277{
14278 ROSE_ASSERT (stmt != NULL);
14279 ROSE_ASSERT (for_init_stmt != NULL);
14280
14281#if 0
14282 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());
14283#endif
14284
14285 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14286 // to record it being moved (and thus the macroExpansions that it might be associated with having
14287 // to force the macroExpansion's associated statements to be marked as a transformation.
14289
14290#if 0
14291 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());
14292#endif
14293
14294 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14295 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14296 // prepend, we only need to look at the scope.
14298
14299 for_init_stmt->prepend_init_stmt (stmt);
14300}
14301
14302void SageInterface::prependStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14303 {
14304 for (size_t i = stmts.size(); i > 0; --i)
14305 {
14306 prependStatement(stmts[i - 1], scope);
14307 }
14308 }
14309
14314{
14315 bool rt = false;
14316 ROSE_ASSERT (scope != NULL);
14317 switch (scope->variantT())
14318 {
14319 case V_SgBasicBlock:
14320 case V_SgClassDefinition:
14321 case V_SgFunctionDefinition:
14322 case V_SgGlobal:
14323 case V_SgNamespaceDefinitionStatement: //?
14324 rt = true;
14325 break;
14326
14327 case V_SgAssociateStatement :
14328 case V_SgBlockDataStatement :
14329 case V_SgCatchOptionStmt:
14330 case V_SgDoWhileStmt:
14331 case V_SgForAllStatement:
14332 case V_SgForStatement:
14333 case V_SgFortranDo:
14334 case V_SgIfStmt:
14335 case V_SgSwitchStatement:
14336 case V_SgUpcForAllStatement:
14337 case V_SgWhileStmt:
14338 rt = false;
14339 break;
14340
14341 default:
14342 cout<<"unrecognized or unhandled scope type for SageInterface::hasSimpleChildrenList() "<<endl;
14343 break;
14344 }
14345 return rt;
14346}
14347
14348
14349// 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.
14351 {
14352 // When inserting a statement into global scope, if inserting at the top of scope it is best to insert
14353 // after the last statement from the preinclude file rose_edg_required_macros_and_functions.h.
14354
14355 SgDeclarationStatementPtrList & declarationList = globalScope->get_declarations();
14356
14357 SgStatement* last_statement = NULL;
14358 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
14359 // while (i != declarationList.end())
14360 while (i != declarationList.end() && (*i)->get_file_info() != NULL && (*i)->get_file_info()->isFrontendSpecific() == true)
14361 {
14362#if 0
14363 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");
14364#endif
14365 last_statement = *i;
14366
14367 i++;
14368 }
14369
14370 ROSE_ASSERT(last_statement != NULL);
14371#if 1
14372 printf ("last_statement = %p = %s \n",last_statement,last_statement->class_name().c_str());
14373#endif
14374#if 0
14375 printf ("Exiting as a test! \n");
14376 ROSE_ABORT();
14377#endif
14378
14379 return last_statement;
14380 }
14381
14382
14383 //TODO handle more side effect like SageBuilder::append_statement() does
14384 //Merge myStatementInsert()
14385 // insert SageInterface::insertStatement()
14386void SageInterface::insertStatement(SgStatement *targetStmt, SgStatement* newStmt, bool insertBefore, bool autoMovePreprocessingInfo /*= true */)
14387 {
14388 ROSE_ASSERT(targetStmt &&newStmt);
14389 ROSE_ASSERT(targetStmt != newStmt); // should not share statement nodes!
14390 SgNode* parent = targetStmt->get_parent();
14391 if (parent == NULL)
14392 {
14393 cerr << "Empty parent pointer for target statement. May be caused by the wrong order of target and new statements in insertStatement(targetStmt, newStmt)"<<endl;
14394 ROSE_ASSERT(parent);
14395 }
14396
14397 if (isSgLabelStatement(parent) != NULL)
14398 {
14399#if 0
14400 printf ("In SageInterface::insertStatement(): Detected case of label statement as parent, using parent of label statement \n");
14401#endif
14402 SgLabelStatement* labelStatement = isSgLabelStatement(parent);
14403 // parent = labelStatement->get_scope();
14404 parent = labelStatement->get_parent();
14405 ROSE_ASSERT(isSgLabelStatement(parent) == NULL);
14406 }
14407
14408#if 0
14409 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());
14410#endif
14411
14412 // DQ (12/2/2014): Not sure why this was here in the first place (likely debugging code from the fix for the SgLableStatement insertion.
14413 // SgFunctionDefinition* functionDefinition = SageInterface::getEnclosingProcedure(targetStmt);
14414 // ROSE_ASSERT(functionDefinition != NULL);
14415
14416 // Liao 3/2/2012. The semantics of ensureBasicBlockAsParent() are messy. input targetStmt may be
14417 // returned as it is if it is already a basic block as a body of if/while/catch/ etc.
14418 // We now have single statement true/false body for IfStmt etc
14419 // However, IfStmt::insert_child() is ambiguous and not implemented
14420 // So we make SgBasicBlock out of the single statement and
14421 // essentially call SgBasicBlock::insert_child() instead.
14422 // TODO: add test cases for If, variable, variable/struct inside if, etc
14423 // parent = ensureBasicBlockAsParent(targetStmt);
14424
14425 // must get the new scope after ensureBasicBlockAsParent ()
14426 SgScopeStatement* scope = targetStmt->get_scope();
14427 ROSE_ASSERT(scope);
14428
14429#if 0
14430 printf ("targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14431 printf ("scope = %p = %s \n",scope,scope->class_name().c_str());
14432#endif
14433
14434 // DQ (11/16/2014): This step is problematic if the targetStmt has been transformed to be associated with a SgLabelStatement.
14435 // The reason is that the targetStmt's parent will have been reset to be the SgLabelStatement and the logic in the set_parent()
14436 // function will assert fail when the parent is being set to itself (which is a good idea in general). A better solution might
14437 // 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
14438 // more sense in this special case of a SgLabelStatement.
14439 // newStmt->set_parent(targetStmt->get_parent());
14440 newStmt->set_parent(scope);
14441
14442 // 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.
14443 // The fix was the reuse the one that was found.
14444 fixStatement(newStmt,scope);
14445
14446 // DQ (9/16/2010): Added assertion that appears to be required to be true.
14447 // However, if this is required to be true then what about statements in
14448 // SgStatementExpression IR nodes?
14449 ROSE_ASSERT(isSgStatement(parent) != NULL);
14450
14451 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
14452 // appear before the statement to be attached to the inserted statement (and marked
14453 // to appear before that statement).
14454 ROSE_ASSERT(targetStmt != NULL);
14455 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
14456
14457#if 0
14458 printf ("In SageInterface::insertStatement(): after checking for associated comments \n");
14459 reportNodesMarkedAsModified(scope);
14460#endif
14461
14462 // TODO refactor this portion of code into a separate function
14463 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14464 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
14465 if (autoMovePreprocessingInfo) // Do this only if automatically handling of preprocessing information is request by users
14466 {
14467 if (comments != NULL && isSgBasicBlock(newStmt) == NULL)
14468 {
14469 vector<int> captureList;
14470#if 0
14471 printf ("Found attached comments (at %p = %s, inserting %p = %s insertBefore = %s): comments->size() = %" PRIuPTR " \n",
14472 targetStmt,targetStmt->class_name().c_str(),newStmt,newStmt->class_name().c_str(),insertBefore ? "true" : "false",comments->size());
14473#endif
14474 // DQ (9/17/2010): Assert that the new statement being inserted has no attached comments or CPP directives.
14475 if (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false)
14476 {
14477 // If the inserted statment has attached comments or CPP directives then this is gets a little
14478 // bit more comple and we don't support that at present.
14479 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");
14480 }
14481 // DQ (9/17/2010): commented out because it fails test in projects/OpenMP_Translator/for_firstprivate.c
14482 ROSE_ASSERT((newStmt->getAttachedPreprocessingInfo() == NULL) || (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false));
14483
14484 int commentIndex = 0;
14485 AttachedPreprocessingInfoType::iterator i;
14486 for (i = comments->begin(); i != comments->end(); i++)
14487 {
14488 ROSE_ASSERT ( (*i) != NULL );
14489#if 0
14490 printf (" Attached Comment (relativePosition=%s): %s\n",
14491 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
14492 (*i)->getString().c_str());
14493 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
14494 (*i)->get_file_info()->display("comment/directive location");
14495#endif
14496 PreprocessingInfo::RelativePositionType relativePosition = (insertBefore == true) ? PreprocessingInfo::before : PreprocessingInfo::after;
14497 if ((*i)->getRelativePosition() == relativePosition)
14498 {
14499 // accumulate into list
14500 captureList.push_back(commentIndex);
14501 }
14502
14503 commentIndex++;
14504 }
14505
14506 // printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
14507 if (captureList.empty() == false)
14508 {
14509 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
14510 // SgStatement* surroundingStatement = (insertBefore == true) ? getPreviousStatement(targetStmt) : getNextStatement(targetStmt);
14511 // SgStatement* surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14512 SgStatement* surroundingStatement = newStmt;
14513 ROSE_ASSERT(surroundingStatement != targetStmt);
14514 ROSE_ASSERT(surroundingStatement != NULL);
14515#if 0
14516 if (surroundingStatement == NULL)
14517 {
14518 // printf ("Warning: the surrounding statement for insertBefore = %s is NULL (so use the newStmt) \n",insertBefore ? "true" : "false");
14519 surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14520 }
14521#endif
14522 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
14523 // printf ("This is a valid surrounding statement = %s for insertBefore = %s \n",surroundingStatement->class_name().c_str(),insertBefore ? "true" : "false");
14524 vector<int>::iterator j = captureList.begin();
14525 while (j != captureList.end())
14526 {
14527 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
14528 // printf ("Attaching comments to newStmt = %p = %s \n",newStmt,newStmt->class_name().c_str());
14529 newStmt->addToAttachedPreprocessingInfo((*comments)[*j]);
14530
14531 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
14532 // printf ("Removing entry from comments list on targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14533 (*comments)[*j] = NULL;
14534
14535 j++;
14536 }
14537
14538 // Now remove each NULL entries in the comments vector.
14539 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
14540 for (size_t n = 0; n < captureList.size(); n++)
14541 {
14542 AttachedPreprocessingInfoType::iterator k = comments->begin();
14543 while (k != comments->end())
14544 {
14545 // Only modify the list once per iteration over the captureList
14546 if (*k == NULL)
14547 {
14548 comments->erase(k);
14549 break;
14550 }
14551 k++;
14552 }
14553 }
14554 }
14555 }
14556 else
14557 {
14558 // printf ("No attached comments (at %p of type: %s): \n",targetStmt,targetStmt->class_name().c_str());
14559 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14560 // I think that special rules apply to inserting a SgBasicBlock so disable comment relocation when inserting a SgBasicBlock.
14561 if (comments != NULL)
14562 {
14563 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");
14564 }
14565 }
14566 } // end if autoMovePreprocessingInfo
14567
14568
14569#if 0
14570 printf ("In SageInterface::insertStatement(): after processing associated comments \n");
14571 reportNodesMarkedAsModified(scope);
14572#endif
14573
14574 if (isSgIfStmt(parent))
14575 {
14576 if (isSgIfStmt(parent)->get_conditional()==targetStmt)
14577 {
14578 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14579 }
14580 else
14581 {
14582 if (isSgIfStmt(parent)->get_true_body()==targetStmt)
14583 {
14584 // Liao 3/2/2012
14585 // We have some choices:
14586 // 1) if the targeStmt is a basic block, we can append/prepend the new stmt
14587 // within the targetStmt. But this is not the exact semantics of insertStatment. It will break the outliner.
14588 // Since the targetStmt will have new content inside of it, which is not the semantics of
14589 // inserting anything before/or after it.
14590 // 2) always insert a padding basic block between parent and targetStmt
14591 // and we can legally insert before/after the target statement within the
14592 // padding basic block.
14593 //TODO: this insertion of padding basic block should ideally go into some AST normalization phase
14594 // so the transformation function (insertStatement) only does what it means to do, no more and no less.
14595 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14596 isSgIfStmt(parent)->set_true_body(newparent);
14597 newparent->set_parent(parent);
14598 insertStatement(targetStmt, newStmt,insertBefore);
14599 }
14600 else
14601 {
14602 if (isSgIfStmt(parent)->get_false_body()==targetStmt)
14603 {
14604 // ensureBasicBlockAsParent(targetStmt);
14605 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14606 isSgIfStmt(parent)->set_false_body(newparent);
14607 newparent->set_parent(parent);
14608 insertStatement(targetStmt, newStmt,insertBefore);
14609 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14610 }
14611 }
14612 }
14613 }
14614 else
14615 {
14616 if (isSgWhileStmt(parent))
14617 {
14618 if (isSgWhileStmt(parent)->get_condition()==targetStmt)
14619 {
14620 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14621 }
14622 else
14623 {
14624 if (isSgWhileStmt(parent)->get_body()==targetStmt)
14625 {
14626 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14627 isSgWhileStmt(parent)->set_body(newparent);
14628 newparent->set_parent(parent);
14629 insertStatement(targetStmt, newStmt,insertBefore);
14630 // ensureBasicBlockAsParent(targetStmt);
14631 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14632 }
14633 }
14634 }
14635 else
14636 {
14637 if (isSgDoWhileStmt(parent))
14638 {
14639 if (isSgDoWhileStmt(parent)->get_condition()==targetStmt)
14640 {
14641 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14642 }
14643 else
14644 {
14645 if (isSgDoWhileStmt(parent)->get_body()==targetStmt)
14646 {
14647 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14648 isSgDoWhileStmt(parent)->set_body(newparent);
14649 newparent->set_parent(parent);
14650 insertStatement(targetStmt, newStmt,insertBefore);
14651 // ensureBasicBlockAsParent(targetStmt);
14652 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14653 }
14654 }
14655 }
14656 else
14657 {
14658 if (isSgForStatement(parent))
14659 {
14660 if (isSgForStatement(parent)->get_loop_body()==targetStmt)
14661 {
14662 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14663 isSgForStatement(parent)->set_loop_body(newparent);
14664 newparent->set_parent(parent);
14665 insertStatement(targetStmt, newStmt,insertBefore);
14666 // ensureBasicBlockAsParent(targetStmt);
14667 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14668 }
14669 else
14670 {
14671 if (isSgForStatement(parent)->get_test()==targetStmt)
14672 {
14673 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14674 }
14675 }
14676 }
14677 else // \pp (2/24/2011) added support for UpcForAll
14678 {
14679 if (SgUpcForAllStatement* p = isSgUpcForAllStatement(parent))
14680 {
14681 //const bool stmt_present = (p->get_loop_body() == targetStmt || p->get_test() == targetStmt);
14682
14683 // \pp \todo what if !stmt_present
14684 // ROSE_ASSERT(stmt_present != NULL);
14685 insertStatement(p, newStmt, insertBefore);
14686 }
14687 else
14688 {
14689 if (SgOmpBodyStatement * p = isSgOmpBodyStatement (parent))
14690 {
14691 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14692 p->set_body(newparent);
14693 newparent->set_parent(parent);
14694 insertStatement(targetStmt, newStmt,insertBefore);
14695 }
14696 else
14697 {
14698 // It appears that all of the recursive calls are untimately calling this location.
14699 SgStatement* stmnt = isSgStatement(parent);
14700 ROSE_ASSERT(stmnt != NULL);
14701 stmnt->insert_statement(targetStmt,newStmt,insertBefore);
14702 }
14703 }
14704 }
14705 }
14706 }
14707 }
14708
14709 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14710 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14711 // this). Also since this is only operating within a single scope it is likely too specific to C
14712 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14713 // use name qualification).
14714 // update the links after insertion!
14716 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(newStmt) != NULL) )
14717 {
14718 updateDefiningNondefiningLinks(isSgFunctionDeclaration(newStmt),scope);
14719 }
14720
14721#if 0
14722 printf ("In SageInterface::insertStatement(): at BASE of function \n");
14723 reportNodesMarkedAsModified(scope);
14724#endif
14725 }
14726
14727
14728void SageInterface::insertStatementList(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts, bool insertBefore)
14729 {
14730 if (insertBefore)
14731 {
14732 for (size_t i = 0; i < newStmts.size(); ++i)
14733 {
14734 insertStatementBefore(targetStmt, newStmts[i]);
14735 }
14736 }
14737 else
14738 {
14739 for (size_t i = newStmts.size(); i > 0; --i)
14740 {
14741 insertStatementAfter(targetStmt, newStmts[i - 1]);
14742 }
14743 }
14744 }
14745
14746void SageInterface::insertStatementAfter(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true*/)
14747 {
14748 insertStatement(targetStmt,newStmt,false, autoMovePreprocessingInfo);
14749 }
14750
14751void SageInterface::insertStatementListAfter(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14752 {
14753 insertStatementList(targetStmt,newStmts,false);
14754 }
14755
14758 {
14759 ROSE_ASSERT (stmt != NULL);
14760 ROSE_ASSERT (scope != NULL);
14761 // Insert to be the declaration after current declaration sequence, if any
14762 SgStatement* l_stmt = findLastDeclarationStatement (scope);
14763 if (l_stmt)
14764 insertStatementAfter(l_stmt,stmt);
14765 else
14766 prependStatement(stmt, scope);
14767 }
14768
14770void SageInterface::insertStatementAfterLastDeclaration(std::vector<SgStatement*> stmt_list, SgScopeStatement* scope)
14771 {
14772 ROSE_ASSERT (scope != NULL);
14773 vector <SgStatement* >::iterator iter;
14774 SgStatement* prev_stmt = NULL;
14775 for (iter= stmt_list.begin(); iter != stmt_list.end(); iter++)
14776 {
14777 if (iter == stmt_list.begin())
14778 {
14780 }
14781 else
14782 {
14783 ROSE_ASSERT (prev_stmt != NULL);
14784 insertStatementAfter (prev_stmt, *iter);
14785 }
14786 prev_stmt = *iter;
14787 }
14788 }
14789
14791{
14792 ROSE_ASSERT(newStmt!=NULL);
14793 ROSE_ASSERT(scope!=NULL);
14794 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14795 if (!isSgDeclarationStatement(targetStmt)) {
14796 insertStatementBefore(targetStmt, newStmt, movePreprocessingInfo);
14797 return;
14798 }
14799 }
14800 appendStatement(newStmt, scope);
14801}
14802
14803void SageInterface::insertStatementListBeforeFirstNonDeclaration(const std::vector<SgStatement*> &newStmts,SgScopeStatement *scope)
14804{
14805 ROSE_ASSERT(scope!=NULL);
14806 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14807 if (!isSgDeclarationStatement(targetStmt)) {
14808 insertStatementListBefore(targetStmt, newStmts);
14809 return;
14810 }
14811 }
14812 appendStatementList(newStmts, scope);
14813}
14814
14815void SageInterface::insertStatementBefore(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true */)
14816 {
14817 insertStatement(targetStmt,newStmt,true, autoMovePreprocessingInfo);
14818 }
14819
14820void SageInterface::insertStatementListBefore(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14821 {
14822 insertStatementList(targetStmt,newStmts,true);
14823 }
14824
14825 //a wrapper for set_expression(), set_operand(), set_operand_exp() etc
14826 // special concern for lvalue, parent,
14827 // todo: warning overwriting existing operands
14829 {
14830 ROSE_ASSERT(target);
14831 ROSE_ASSERT(operand);
14832 ROSE_ASSERT(target!=operand);
14833 switch (target->variantT())
14834 {
14835 case V_SgActualArgumentExpression:
14836 isSgActualArgumentExpression(target)->set_expression(operand);
14837 break;
14838 case V_SgAsmOp:
14839 isSgAsmOp(target)->set_expression(operand);
14840 break;
14841 case V_SgSizeOfOp:
14842 isSgSizeOfOp(target)->set_operand_expr(operand);
14843 break;
14844 case V_SgTypeIdOp:
14845 isSgTypeIdOp(target)->set_operand_expr(operand);
14846 break;
14847 case V_SgVarArgOp:
14848 isSgVarArgOp(target)->set_operand_expr(operand);
14849 break;
14850 case V_SgVarArgStartOneOperandOp:
14851 isSgVarArgStartOneOperandOp(target)->set_operand_expr(operand);
14852 break;
14853 case V_SgAssignInitializer:
14854 isSgAssignInitializer (target)->set_operand(operand);
14855 break;
14856 default:
14857 if (isSgUnaryOp(target)!=NULL)
14858 isSgUnaryOp(target)->set_operand_i(operand);
14859 else
14860 {
14861 cerr<<"\tSageInterface::setOperand(): unhandled case for target expression of type "
14862 <<target->class_name()<<endl;
14863 ROSE_ABORT();
14864 }
14865 }// end switch
14866 operand->set_parent(target);
14867 markLhsValues(target);
14868 }
14869
14870 // binary and SgVarArgCopyOp, SgVarArgStartOp
14872 {
14873 ROSE_ASSERT(target);
14874 ROSE_ASSERT(lhs);
14875 ROSE_ASSERT(target!=lhs);
14876 bool hasrhs = false;
14877
14878 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14879 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14880 SgBinaryOp* binary = isSgBinaryOp(target);
14881
14882 if (varargcopy!=NULL)
14883 {
14884 varargcopy->set_lhs_operand(lhs);
14885 if( varargcopy->get_rhs_operand()!=NULL) hasrhs= true;
14886 }
14887 else if(varargstart!=NULL)
14888 {
14889 varargstart->set_lhs_operand(lhs);
14890 if( varargstart->get_rhs_operand()!=NULL) hasrhs= true;
14891 }
14892 else if(binary!=NULL)
14893 {
14894 binary->set_lhs_operand(lhs);
14895 if( binary->get_rhs_operand()!=NULL) hasrhs= true;
14896 }
14897 else
14898 {
14899 cout<<"SageInterface::setLhsOperand(): unhandled case for target expression of type "
14900 <<target->class_name()<<endl;
14901 ROSE_ABORT();
14902 }
14903 lhs->set_parent(target);
14904// only when both lhs and rhs are available, can we set lvalue
14905// there is assertion(rhs!=NULL) in markLhsValues()
14906 if (hasrhs)
14907 markLhsValues(target);
14908 }
14909
14911 {
14912 ROSE_ASSERT(target);
14913 ROSE_ASSERT(rhs);
14914 ROSE_ASSERT(target!=rhs);
14915 bool haslhs = false;
14916
14917 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14918 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14919 SgBinaryOp* binary = isSgBinaryOp(target);
14920
14921 if (varargcopy!=NULL)
14922 {
14923 varargcopy->set_rhs_operand(rhs);
14924 if( varargcopy->get_lhs_operand()!=NULL) haslhs= true;
14925 }
14926 else if(varargstart!=NULL)
14927 {
14928 varargstart->set_rhs_operand(rhs);
14929 if( varargstart->get_lhs_operand()!=NULL) haslhs= true;
14930 }
14931 else if(binary!=NULL)
14932 {
14933 binary->set_rhs_operand(rhs);
14934 if( binary->get_lhs_operand()!=NULL) haslhs= true;
14935 }
14936 else
14937 {
14938 cout<<"SageInterface::setRhsOperand(): unhandled case for target expression of type "
14939 <<target->class_name()<<endl;
14940 ROSE_ABORT();
14941 }
14942 rhs->set_parent(target);
14943// only when both lhs and rhs are available, can we set lvalue
14944 if (haslhs)
14945 markLhsValues(target);
14946 }
14947
14948// DQ (1/25/2010): Added to simplify handling of directories (e.g. for code generation).
14949void SageInterface::moveToSubdirectory ( std::string directoryName, SgFile* file )
14950 {
14951 // This support makes use of the new SgDirectory IR node. It causes the unparser to
14952 // generate a subdirectory and unparse the file into the subdirectory. It works
14953 // by internally calling the system function "system()" to call "mkdir directoryName"
14954 // and then chdir()" to change the current directory. These steps are handled by the
14955 // unparser.
14956
14957 // This function just does the transformation to insert a SgDirectory IR node between
14958 // the referenced SgFile and it's project (fixing up parents and file lists etc.).
14959
14960 // Add a directory and unparse the code (to the new directory)
14961 SgDirectory* directory = new SgDirectory(directoryName);
14962
14963 SgFileList* parentFileList = isSgFileList(file->get_parent());
14964 ROSE_ASSERT(parentFileList != NULL);
14965 directory->set_parent(file->get_parent());
14966
14967 SgProject* project = NULL;
14968 SgDirectory* parentDirectory = isSgDirectory(parentFileList->get_parent());
14969
14970 if (parentDirectory != NULL)
14971 {
14972 // Add a directory to the list in the SgDirectory node.
14973 parentDirectory->get_directoryList()->get_listOfDirectories().push_back(directory);
14974
14975 // Erase the reference to the file in the project's file list.
14976 // parentDirectory->get_fileList().erase(find(parentDirectory->get_fileList().begin(),parentDirectory->get_fileList().end(),file));
14977 }
14978 else
14979 {
14980 project = isSgProject(parentFileList->get_parent());
14981 ROSE_ASSERT(project != NULL);
14982
14983 // Add a directory to the list in the SgProject node.
14984 project->get_directoryList()->get_listOfDirectories().push_back(directory);
14985
14986 // Erase the reference to the file in the project's file list.
14987 // project->get_fileList().erase(find(project->get_fileList().begin(),project->get_fileList().end(),file));
14988 }
14989
14990 // Put the file into the new directory.
14991 directory->get_fileList()->get_listOfFiles().push_back(file);
14992
14993 // Erase the reference to the file in the project's file list.
14994 parentFileList->get_listOfFiles().erase(find(parentFileList->get_listOfFiles().begin(),parentFileList->get_listOfFiles().end(),file));
14995
14996 file->set_parent(directory);
14997}
14998
14999
15000//------------------------- AST repair----------------------------
15001//----------------------------------------------------------------
15003 {
15004 ROSE_ASSERT(structDecl != NULL);
15005 ROSE_ASSERT(scope != NULL);
15006 SgClassDeclaration* nondefdecl = isSgClassDeclaration(structDecl->get_firstNondefiningDeclaration());
15007 ROSE_ASSERT(nondefdecl != NULL);
15008
15009 // ROSE_ASSERT(structDecl->get_definingDeclaration() != NULL);
15010 SgClassDeclaration* defdecl = isSgClassDeclaration(structDecl->get_definingDeclaration());
15011 // ROSE_ASSERT(defdecl != NULL);
15012
15013 // Liao, 9/2/2009
15014 // fixup missing scope when bottomup AST building is used
15015 if (structDecl->get_scope() == NULL)
15016 structDecl->set_scope(scope);
15017 if (nondefdecl->get_scope() == NULL)
15018 nondefdecl->set_scope(scope);
15019
15020#if 0
15021 if (structDecl->get_parent() == NULL)
15022 structDecl->set_parent(scope);
15023 if (nondefdecl->get_parent() == NULL)
15024 nondefdecl->set_parent(scope);
15025#else
15026 // 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");
15027
15028 // DQ (7/21/2012): Can we assert this here? NO!
15029 // ROSE_ASSERT(structDecl->get_parent() == NULL);
15030 // ROSE_ASSERT(nondefdecl->get_parent() == NULL);
15031#endif
15032
15033 SgName name = structDecl->get_name();
15034
15035 // This is rare case (translation error) when scope->lookup_class_symbol(name) will find something
15036 // but nondefdecl->get_symbol_from_symbol_table() returns NULL
15037 // But symbols are associated with nondefining declarations whenever possible
15038 // and AST consistent check will check the nondefining declarations first
15039 // Liao, 9/2/2009
15040 // SgClassSymbol* mysymbol = scope->lookup_class_symbol(name);
15041 SgClassSymbol* mysymbol = isSgClassSymbol(nondefdecl->get_symbol_from_symbol_table());
15042
15043 // DQ (3/14/2014): This is false for a copy of a class declaration being inserted into the AST.
15044 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15045 // ROSE_ASSERT(mysymbol != NULL);
15046
15047 if (mysymbol == NULL)
15048 {
15049 printf ("Note: SageInterface::fixStructDeclaration(): structDecl = %p nondefdecl = %p (mysymbol == NULL) \n",structDecl,nondefdecl);
15050
15051 // 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...
15052 // DQ (12/4/2011): Only generate symbols and set the scope if this is the correct scope.
15053 ROSE_ASSERT(structDecl->get_scope() != NULL);
15054
15055 if (scope == structDecl->get_scope())
15056 {
15057 mysymbol = new SgClassSymbol(nondefdecl);
15058 ROSE_ASSERT(mysymbol);
15059
15060 // I need to check the rest of these functions.
15061 printf ("############## DANGER:DANGER:DANGER ################\n");
15062
15063 printf ("In SageInterface::fixStructDeclaration(): Adding class symbol to scope = %p = %s \n",scope,scope->class_name().c_str());
15064 scope->insert_symbol(name, mysymbol);
15065
15066 // ROSE_ASSERT(defdecl != NULL);
15067 if (defdecl)
15068 defdecl->set_scope(scope);
15069 nondefdecl->set_scope(scope);
15070
15071 printf ("*** WARNING: In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Commented out the setting of the parent to be the same as the scope \n");
15072#if 0
15073 if (defdecl)
15074 defdecl->set_parent(scope);
15075 nondefdecl->set_parent(scope);
15076#endif
15077 }
15078 else
15079 {
15080 printf ("In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Skipped building an associated symbol! \n");
15081 }
15082 }
15083
15084 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15085 ROSE_ASSERT(nondefdecl->get_type() != NULL);
15086
15087 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15088 ROSE_ASSERT(nondefdecl->get_type()->variantT() != V_SgNode);
15089
15090 // DQ (9/4/2012): This should be a SgClassType IR node.
15091 ROSE_ASSERT(isSgClassType(nondefdecl->get_type()) != NULL);
15092
15093 // fixup SgClassType, which is associated with the first non-defining declaration only
15094 // and the other declarations share it.
15095 if (nondefdecl->get_type() == NULL)
15096 {
15097 nondefdecl->set_type(SgClassType::createType(nondefdecl));
15098 }
15099 ROSE_ASSERT (nondefdecl->get_type() != NULL);
15100
15101 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15102 if (defdecl != NULL)
15103 {
15104 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15105 ROSE_ASSERT(defdecl->get_type()->variantT() != V_SgNode);
15106
15107 // DQ (9/4/2012): This should be a SgClassType IR node.
15108 ROSE_ASSERT(isSgClassType(defdecl->get_type()) != NULL);
15109 }
15110
15111 // ROSE_ASSERT(defdecl != NULL);
15112 if (defdecl != NULL)
15113 {
15114 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15115 ROSE_ASSERT(defdecl->get_type() != NULL);
15116 if (defdecl->get_type() != nondefdecl->get_type())
15117 {
15118 printf ("ERROR: defdecl->get_type() != nondefdecl->get_type(): what are these: \n");
15119 printf (" defdecl->get_type() = %p = %s \n",defdecl ->get_type(),defdecl ->get_type()->class_name().c_str());
15120 SgNamedType* namedType_definingDecl = isSgNamedType(defdecl->get_type());
15121 if (namedType_definingDecl != NULL)
15122 {
15123 printf ("namedType_definingDecl->get_declaration() = %p = %s \n",namedType_definingDecl->get_declaration(),namedType_definingDecl->get_declaration()->class_name().c_str());
15124 }
15125 printf (" nondefdecl->get_type() = %p = %s \n",nondefdecl->get_type(),nondefdecl->get_type()->class_name().c_str());
15126 SgNamedType* namedType_nondefiningDecl = isSgNamedType(nondefdecl->get_type());
15127 if (namedType_nondefiningDecl != NULL)
15128 {
15129 printf ("namedType_nondefiningDecl->get_declaration() = %p = %s \n",namedType_nondefiningDecl->get_declaration(),namedType_nondefiningDecl->get_declaration()->class_name().c_str());
15130 }
15131 }
15132 //ROSE_ASSERT(defdecl->get_type() == nondefdecl->get_type());
15133 }
15134 }
15135
15136
15138 {
15139 fixStructDeclaration(classDecl,scope);
15140 }
15141
15142
15144 {
15145 ROSE_ASSERT(structDecl);
15146 ROSE_ASSERT(scope);
15147 SgNamespaceDeclarationStatement* nondefdecl = isSgNamespaceDeclarationStatement(structDecl->get_firstNondefiningDeclaration());
15148 ROSE_ASSERT(nondefdecl);
15149 // Liao, 9/2/2009
15150 // fixup missing scope when bottomup AST building is used
15151 if (structDecl->get_parent() == NULL)
15152 structDecl->set_parent(scope);
15153 if (nondefdecl->get_parent() == NULL)
15154 nondefdecl->set_parent(scope);
15155
15156 // tps : (09/03/2009) Namespace should not have a scope
15157 /*
15158 if (structDecl->get_scope() == NULL)
15159 structDecl->set_scope(scope);
15160 if (nondefdecl->get_scope() == NULL)
15161 nondefdecl->set_scope(scope);
15162 */
15163
15164 SgName name= structDecl->get_name();
15165 // SgNamespaceSymbol* mysymbol = scope->lookup_namespace_symbol(name);
15166 SgNamespaceSymbol* mysymbol = isSgNamespaceSymbol(nondefdecl->get_symbol_from_symbol_table());
15167 if (mysymbol==NULL)
15168 {
15169 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15170 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15171 if (scope == structDecl->get_scope())
15172 {
15173 mysymbol = new SgNamespaceSymbol(name,nondefdecl);
15174 ROSE_ASSERT(mysymbol);
15175
15176 printf ("In SageInterface::fixNamespaceDeclaration(): inserting namespace symbol into scope = %p = %s \n",scope,scope->class_name().c_str());
15177 scope->insert_symbol(name, mysymbol);
15178
15179 SgNamespaceDeclarationStatement* defdecl = isSgNamespaceDeclarationStatement(structDecl->get_definingDeclaration());
15180 ROSE_ASSERT(defdecl);
15181 defdecl->set_scope(scope);
15182 nondefdecl->set_scope(scope);
15183
15184 defdecl->set_parent(scope);
15185 nondefdecl->set_parent(scope);
15186 }
15187 }
15188 }
15189
15190#define DEBUG__SageInterface__fixVariableDeclaration 0
15191
15193 {
15194 ROSE_ASSERT(varDecl != NULL);
15195 ROSE_ASSERT(scope != NULL);
15196
15197 SgInitializedNamePtrList namelist = varDecl->get_variables();
15198 SgTemplateVariableInstantiation * tplinst = isSgTemplateVariableInstantiation(varDecl);
15199
15200 // printf ("In SageInterface::fixVariableDeclaration(): Is this a recursive call! \n");
15201
15202#if DEBUG__SageInterface__fixVariableDeclaration
15203 printf ("In SageInterface::fixVariableDeclaration():\n");
15204 printf (" varDecl = %p scope = %p = %s \n", varDecl);
15205 printf (" scope = %p : %s \n", scope, scope->class_name().c_str());
15206#endif
15207
15208 ROSE_ASSERT(namelist.size() > 0);
15209
15210 SgInitializedNamePtrList::iterator i;
15211 for (i = namelist.begin(); i != namelist.end(); i++)
15212 {
15213 SgInitializedName *initName = *i;
15214 ROSE_ASSERT(initName != NULL);
15215#if DEBUG__SageInterface__fixVariableDeclaration
15216 printf (" initName = %p\n", initName);
15217 printf (" initName->get_scope() = %p : %s\n", initName->get_scope(), initName->get_scope() ? initName->get_scope()->class_name().c_str() : "");
15218#endif
15219
15220 SgName name = initName->get_name();
15221#if DEBUG__SageInterface__fixVariableDeclaration
15222 printf (" name = %s\n", name.str());
15223#endif
15224 if (tplinst) {
15225 name = appendTemplateArgumentsToName(name, tplinst->get_templateArguments());
15226 }
15227#if DEBUG__SageInterface__fixVariableDeclaration
15228 printf (" name = %s\n", name.str());
15229#endif
15230
15231 // DQ (11/19/2011): When used with C++, the variable may already have an associated scope
15232 // and be using name qualification, so might not be associated with the current scope.
15233 SgScopeStatement* requiredScope = scope;
15234 SgScopeStatement* preAssociatedScope = initName->get_scope();
15235 if (preAssociatedScope != NULL) {
15236 requiredScope = preAssociatedScope;
15237 }
15238
15239 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15240 initName->set_scope(requiredScope);
15241 if (topScopeStack() != NULL) {
15242 varDecl->set_parent(topScopeStack());
15243 ROSE_ASSERT(varDecl->get_parent() != NULL);
15244 }
15245 ROSE_ASSERT(requiredScope != NULL);
15246 SgVariableSymbol* varSymbol = requiredScope->lookup_variable_symbol(name);
15247#if DEBUG__SageInterface__fixVariableDeclaration
15248 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15249#endif
15250 if (varSymbol == NULL) {
15251 if (scope == initName->get_scope()) {
15252 if (isSgTemplateVariableDeclaration(varDecl)) {
15253 varSymbol = new SgTemplateVariableSymbol(initName);
15254 } else {
15255 varSymbol = new SgVariableSymbol(initName);
15256 }
15257 ROSE_ASSERT(varSymbol);
15258 scope->insert_symbol(name, varSymbol);
15259 }
15260 } else {
15261 SgInitializedName* prev_decl = varSymbol->get_declaration();
15262 ROSE_ASSERT(prev_decl);
15263 if (initName != prev_decl) {
15264 initName->set_prev_decl_item(prev_decl);
15265 }
15266 ROSE_ASSERT(initName->get_prev_decl_item() != initName);
15267 }
15268#if DEBUG__SageInterface__fixVariableDeclaration
15269 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15270#endif
15271 } //end for
15272
15273 // Liao 12/8/2010
15274 // For Fortran, a common statement may refer to a variable which is declared later.
15275 // In this case, a fake symbol is used for that variable reference.
15276 // But we have to replace the fake one with the real one once the variable declaration is inserted into AST
15278 {
15279 fixVariableReferences(scope);
15280 }
15281 }
15282
15283int SageInterface::fixVariableReferences(SgNode* root, bool cleanUnusedSymbols/*=true*/)
15284{
15285 ROSE_ASSERT(root);
15286 int counter=0;
15287 Rose_STL_Container<SgNode*> varList;
15288
15289 SgVarRefExp* varRef=NULL;
15290 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(root, V_SgVarRefExp);
15291 for (Rose_STL_Container<SgNode*>::iterator i=reflist.begin();i!=reflist.end();i++)
15292 {
15293 varRef= isSgVarRefExp(*i);
15294 ROSE_ASSERT(varRef->get_symbol());
15295 SgInitializedName* initname= varRef->get_symbol()->get_declaration();
15296
15297 ROSE_ASSERT (initname != NULL);
15298 if (initname->get_type()==SgTypeUnknown::createType())
15299 {
15300 SgName varName=initname->get_name();
15301 SgSymbol* realSymbol = NULL;
15302
15303#if 1
15304 // CH (5/7/2010): Before searching SgVarRefExp objects, we should first deal with class/structure
15305 // members. Or else, it is possible that we assign the wrong symbol to those members if there is another
15306 // variable with the same name in parent scopes. Those members include normal member referenced using . or ->
15307 // operators, and static members using :: operators.
15308 //
15309 if (SgArrowExp* arrowExp = isSgArrowExp(varRef->get_parent()))
15310 {
15311 if (varRef == arrowExp->get_rhs_operand_i())
15312 {
15313 // make sure the lhs operand has been fixed
15314 counter += fixVariableReferences(arrowExp->get_lhs_operand_i());
15315 SgType* lhs_type = arrowExp->get_lhs_operand_i()->get_type() ;
15316 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15317 SgPointerType* ptrType = isSgPointerType(lhs_type);
15318 ROSE_ASSERT(ptrType);
15319 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));
15320 ROSE_ASSERT(clsType);
15321 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15322 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15323 ROSE_ASSERT(decl);
15324
15325 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15326 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15327 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15328 }
15329 else
15330 {
15331 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15332 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15333 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15334 }
15335 }
15336 else if (SgDotExp* dotExp = isSgDotExp(varRef->get_parent()))
15337 {
15338 if (varRef == dotExp->get_rhs_operand_i())
15339 {
15340 // make sure the lhs operand has been fixed
15341 counter += fixVariableReferences(dotExp->get_lhs_operand_i());
15342
15343 SgType* lhs_type = dotExp->get_lhs_operand_i()->get_type() ;
15344 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15345 SgClassType* clsType = isSgClassType(lhs_type);
15346 ROSE_ASSERT(clsType);
15347 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15348 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15349 ROSE_ASSERT(decl);
15350
15351 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15352 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15353 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15354 }
15355 else
15356 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15357 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15358 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15359 }
15360 else
15361#endif
15362 {
15363 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15364 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15365 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15366 }
15367
15368 // should find a real symbol at this final fixing stage!
15369 // This function can be called any time, not just final fixing stage
15370 if (realSymbol==NULL)
15371 {
15372 //cerr<<"Error: cannot find a symbol for "<<varName.getString()<<endl;
15373 //ROSE_ASSERT(realSymbol);
15374 }
15375 else {
15376 // release placeholder initname and symbol
15377 ROSE_ASSERT(realSymbol!=(varRef->get_symbol()));
15378#if 0
15379 // CH (5/12/2010):
15380 // To delete a symbol node, first check if there is any node in memory
15381 // pool which points to this symbol node. Only if no such node exists,
15382 // this symbol together with its initialized name can be deleted.
15383 //
15384 bool toDelete = true;
15385
15386 SgSymbol* symbolToDelete = varRef->get_symbol();
15387 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15388 counter ++;
15389
15390 if (varList.empty())
15391 {
15392 VariantVector vv(V_SgVarRefExp);
15393 varList = NodeQuery::queryMemoryPool(vv);
15394 }
15395
15396 for (Rose_STL_Container<SgNode*>::iterator i = varList.begin();
15397 i != varList.end(); ++i)
15398 {
15399 if (SgVarRefExp* var = isSgVarRefExp(*i))
15400 {
15401 if (var->get_symbol() == symbolToDelete)
15402 {
15403 toDelete = false;
15404 break;
15405 }
15406 }
15407 }
15408 if (toDelete)
15409 {
15410 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15411 delete symbolToDelete;
15412 }
15413
15414#else
15415
15416 // CH (2010/7/26): We cannot delete those initname and symbol here, since there may be other variable references
15417 // which point to them. We will delay this clear just before AstTests.
15418#if 0
15419 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15420 delete (varRef->get_symbol());
15421#endif
15422
15423 //std::cout << "Fixed variable reference: " << realSymbol->get_name().str() << std::endl;
15424 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15425 counter ++;
15426#endif
15427 }
15428 }
15429 } // end for
15430 // Liao 2/1/2013: delete unused initname and symbol, considering possible use by the current subtree from root node
15431 if (cleanUnusedSymbols)
15433 return counter;
15434}
15435
15437{
15438 Rose_STL_Container<SgNode*> symbolList;
15439 VariantVector sym_vv(V_SgVariableSymbol);
15440 symbolList = NodeQuery::queryMemoryPool(sym_vv);
15441
15442 Rose_STL_Container<SgNode*> varList;
15443 VariantVector var_vv(V_SgVarRefExp);
15444 //varList = NodeQuery::queryMemoryPool(var_vv);
15445 if (root != NULL)
15446 {
15447 varList = NodeQuery::querySubTree(root, V_SgVarRefExp);
15448 }
15449
15450 for (Rose_STL_Container<SgNode*>::iterator i = symbolList.begin();
15451 i != symbolList.end(); ++i)
15452 {
15453 SgVariableSymbol* symbolToDelete = isSgVariableSymbol(*i);
15454 ROSE_ASSERT(symbolToDelete);
15455 if (symbolToDelete->get_declaration()->get_type() != SgTypeUnknown::createType())
15456 continue;
15457 // symbol with a declaration of SgTypeUnknown will be deleted
15458 bool toDelete = true;
15459
15460 if (root != NULL) // if root is specified. We further check if the symbol is referenced by any nodes of the tree rooted at "root"
15461 {
15462 for (Rose_STL_Container<SgNode*>::iterator j = varList.begin();
15463 j != varList.end(); ++j)
15464 {
15465 SgVarRefExp* var = isSgVarRefExp(*j);
15466 ROSE_ASSERT(var);
15467
15468 if (var->get_symbol() == symbolToDelete)
15469 {
15470 toDelete = false;
15471 break;
15472 }
15473 }
15474 }
15475
15476 if (toDelete)
15477 {
15478#if 0
15479 std::cout << "Symbol " << symbolToDelete->get_name().str() << ' ' << symbolToDelete <<
15480 ' ' << symbolToDelete->get_declaration() << " is deleted." << std::endl;
15481#endif
15482 delete symbolToDelete->get_declaration();
15483 delete symbolToDelete;
15484 }
15485 }
15486}
15487
15488
15490/*
15491 * label statement has special scope: the closest function definition , not SgBasicBlock or others!
15492 */
15494 {
15495 SgLabelStatement* label_stmt = isSgLabelStatement(stmt);
15496 ROSE_ASSERT(label_stmt);
15497 SgName name = label_stmt->get_label();
15498
15499 // PP (07/18/23): In Ada, label symbols should be inserted in the current scope's symbol table
15500 const bool symbolAtFunctionLevel = !is_Ada_language();
15501 SgScopeStatement* label_scope = symbolAtFunctionLevel ? getEnclosingFunctionDefinition(scope,true)
15502 : scope;
15503
15504 // DQ (11/16/2014): Added error checking for when the input scope is the SgFunctionDefinition instead of a nested scope.
15505 if (isSgFunctionDefinition(scope) != nullptr)
15506 {
15507 ASSERT_not_null(label_scope);
15508 }
15509
15510 if (label_scope) //Should we assert this instead? No for bottom up AST building
15511 {
15512 label_stmt->set_scope(label_scope);
15513 SgLabelSymbol* lsymbol = label_scope->lookup_label_symbol(name);
15514
15515 if (lsymbol == nullptr)
15516 {
15517 // SgLabelStatement should always be in the function scope
15518 // PP (07/18/23): in Ada symbols should be at the innermost scope
15519 lsymbol= new SgLabelSymbol(label_stmt);
15520 ASSERT_not_null(lsymbol);
15521 label_scope->insert_symbol(lsymbol->get_name(), lsymbol);
15522 }
15523 }
15524 }
15525
15526
15528//efExp are created transparently as needed.
15530 SgLabelSymbol::label_type_enum label_type, SgScopeStatement* label_scope)
15531 {
15532 ROSE_ASSERT (stmt != NULL);
15533 ROSE_ASSERT (label_value >0 && label_value <=99999); //five digits for Fortran label
15534
15535 // Added optional label_type and label_scope [Rasmussen 2019.01.20]
15536 if (label_scope == NULL)
15537 {
15538 label_scope = getEnclosingFunctionDefinition(stmt);
15539 }
15540 ROSE_ASSERT (label_scope != NULL);
15541 SgName label_name(StringUtility::numberToString(label_value));
15542 SgLabelSymbol * symbol = label_scope->lookup_label_symbol (label_name);
15543 if (symbol == NULL)
15544 {
15545 // DQ (12/4/2011): This is the correct handling for SgLabelStatement (always in the function scope, same as C and C++).
15546 // DQ (2/2/2011): We want to call the old constructor (we now have another constructor that takes a SgInitializedName pointer).
15547 // symbol = new SgLabelSymbol(NULL);
15548 symbol = new SgLabelSymbol((SgLabelStatement*) NULL);
15549 ROSE_ASSERT(symbol != NULL);
15550 symbol->set_fortran_statement(stmt);
15551 symbol->set_numeric_label_value(label_value);
15552 label_scope->insert_symbol(label_name,symbol);
15553 }
15554 else
15555 {
15556 cerr<<"Error. SageInterface::setFortranNumericLabel() tries to set a duplicated label value!"<<endl;
15557 ROSE_ASSERT (false);
15558 }
15559
15560 // SgLabelRefExp
15561 SgLabelRefExp* ref_exp = buildLabelRefExp(symbol);
15562 ref_exp->set_parent(stmt);
15563
15564 switch(label_type)
15565 {
15566 case SgLabelSymbol::e_start_label_type:
15567 {
15568 stmt->set_numeric_label(ref_exp);
15569 break;
15570 }
15571 case SgLabelSymbol::e_end_label_type:
15572 {
15573 stmt->set_end_numeric_label(ref_exp);
15574 break;
15575 }
15576 default:
15577 {
15578 std::cerr << "SageInterface::setFortranNumericLabel: unimplemented for label_type " << label_type << "\n";
15579 ROSE_ABORT(); // NOT IMPLEMENTED
15580 }
15581 }
15582
15583 }
15584
15585
15588{
15589 int result =10;
15590 ROSE_ASSERT (func_def != NULL);
15591 ROSE_ASSERT (SageInterface::is_Fortran_language()== true);
15592 std::set<SgNode*> symbols = func_def->get_symbol_table()->get_symbols();
15593
15594 // find the max label value, +10 to be the suggested next label value
15595 std::set<SgNode*>::iterator iter ;
15596 for (iter=symbols.begin(); iter !=symbols.end(); iter++)
15597 {
15598 SgLabelSymbol * l_symbol = isSgLabelSymbol(*iter);
15599 if (l_symbol)
15600 {
15601 int cur_val = l_symbol->get_numeric_label_value();
15602 if (result <=cur_val)
15603 result = cur_val +10;
15604 }
15605 }
15606
15607 ROSE_ASSERT (result <= 99999); // max 5 digits for F77 label
15608 return result;
15609}
15610
15612/*
15613 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15614 */
15616 {
15617 // DQ (3/5/2012): Added test.
15618 ROSE_ASSERT(scope != NULL);
15619
15620 // fix function type table's parent edge
15621 // Liao 5/4/2010
15623 ROSE_ASSERT(fTable != NULL);
15624
15625 if (fTable->get_parent() == NULL)
15626 {
15627 // DQ (3/5/2012): This is a problem for test2012_13.C (test code taken from test2004_42.C).
15628 // fTable->set_parent(getGlobalScope(scope));
15629#if 0
15630 printf ("WARNING: Skip setting the scope of the SgFunctionTypeTable scope = %p = %s \n",scope,scope->class_name().c_str());
15631#endif
15632 fTable->set_parent(getGlobalScope(scope));
15633 }
15634
15635#if 0
15636 printf ("In SageInterface::fixStatement(): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15637#endif
15638
15639 // Liao 4/23/2010, Fix function symbol
15640 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15641 // Added SgProgramHeaderStatement [Rasmussen, 2020.01.19]
15642 SgFunctionDeclaration * func = isSgFunctionDeclaration(stmt);
15643 SgMemberFunctionDeclaration * mfunc = isSgMemberFunctionDeclaration(stmt);
15644 SgTemplateFunctionDeclaration * tfunc = isSgTemplateFunctionDeclaration(stmt);
15645 SgTemplateMemberFunctionDeclaration * tmfunc = isSgTemplateMemberFunctionDeclaration(stmt);
15646 SgProcedureHeaderStatement * procfunc = isSgProcedureHeaderStatement(stmt);
15647 SgProgramHeaderStatement * progfunc = isSgProgramHeaderStatement(stmt);
15648
15649 if (tmfunc != NULL)
15650 assert(tmfunc->variantT() == V_SgTemplateMemberFunctionDeclaration);
15651 else if (mfunc != NULL)
15652 assert(mfunc->variantT() == V_SgMemberFunctionDeclaration || mfunc->variantT() == V_SgTemplateInstantiationMemberFunctionDecl);
15653 else if (tfunc != NULL)
15654 assert(tfunc->variantT() == V_SgTemplateFunctionDeclaration);
15655 else if (procfunc != NULL)
15656 assert(procfunc->variantT() == V_SgProcedureHeaderStatement);
15657 else if (progfunc != NULL)
15658 assert(progfunc->variantT() == V_SgProgramHeaderStatement);
15659 else if (func != NULL)
15660 assert(func->variantT() == V_SgFunctionDeclaration || func->variantT() == V_SgTemplateInstantiationFunctionDecl);
15661 else ROSE_ABORT();
15662
15663#if 0
15664 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15665 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15666#endif
15667
15668 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15669 // It is an error to put the symbol for a function into the current scope if the function's scope
15670 // is explicitly set to be different. So this should be allowed only if the function's scope is
15671 // not explicitly set, or if the scopes match. This is an example of something different for C++
15672 // than for C or other simpler languages.
15673 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15674 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15675 {
15676#if 0
15677 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());
15678#endif
15679 SgFunctionSymbol* func_symbol = NULL;
15680
15681 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
15682 // In this case these are unavailable from this point.
15683 if (tmfunc != NULL)
15684 {
15685 SgTemplateParameterPtrList & templateParameterList = tmfunc->get_templateParameters();
15686 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type());
15687 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),NULL);
15688 func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15689 }
15690 else if (mfunc != NULL)
15691 {
15692 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(mfunc);
15693 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationMemberFunctionDecl != NULL) ? &(templateInstantiationMemberFunctionDecl->get_templateArguments()) : NULL;
15694 // func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),NULL);
15695 func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15696 }
15697 else if (tfunc != NULL)
15698 {
15699 SgTemplateParameterPtrList & templateParameterList = tfunc->get_templateParameters();
15700#if 0
15701 printf ("In SageInterface::fixStatement(): templateParameterList.size() = %" PRIuPTR " \n",templateParameterList.size());
15702#endif
15703 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type());
15704 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),NULL);
15705 func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15706 }
15707 else if (procfunc != NULL)
15708 {
15709#if 0
15710 printf ("In SageInterface::fixStatement(): procfunc->get_name() = %s calling lookup_function_symbol() \n",procfunc->get_name().str());
15711#endif
15712 func_symbol = scope->lookup_function_symbol (procfunc->get_name(), procfunc->get_type());
15713 assert(func_symbol != NULL);
15714 }
15715 else if (progfunc != NULL)
15716 {
15717 func_symbol = scope->lookup_function_symbol (progfunc->get_name(), progfunc->get_type());
15718 assert(func_symbol != NULL);
15719 }
15720 else if (func != NULL)
15721 {
15722#if 0
15723 printf ("In SageInterface::fixStatement(): func->get_name() = %s calling lookup_function_symbol() \n",func->get_name().str());
15724#endif
15725 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(func);
15726 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationFunctionDecl != NULL) ? &(templateInstantiationFunctionDecl->get_templateArguments()) : NULL;
15727 // func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),NULL);
15728 func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15729
15730 // 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
15731 // 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
15732 // opportunity to fixup the function to have a symbol in the scope's symbol table.
15733 if (func_symbol == NULL)
15734 {
15735 // scope->print_symboltable("In SageInterface::fixStatement()");
15736 func_symbol = new SgFunctionSymbol(func);
15737 scope->insert_symbol(func->get_name(), func_symbol);
15738 }
15739 }
15740 else
15741 {
15742 ROSE_ABORT();
15743 }
15744#if 0
15745 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15746#endif
15747 assert(func_symbol != NULL);
15748 }
15749 }
15750
15752/*
15753 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15754 */
15756 {
15757 // DQ (12/4/2011): This function has not been implemented yet. It will assert fail if it is required.
15758 printf ("Need to handle SgTemplateDeclaration IR nodes as well...(implement later) \n");
15759 }
15760
15761
15764 {
15765 // fix symbol table
15766 if (isSgVariableDeclaration(stmt))
15767 {
15768 fixVariableDeclaration(isSgVariableDeclaration(stmt), scope);
15769 }
15770 else if (isStructDeclaration(stmt))
15771 {
15772 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
15773 ROSE_ASSERT(classDeclaration != nullptr);
15774 fixStructDeclaration(classDeclaration,scope);
15775 }
15776 else if (isSgClassDeclaration(stmt))
15777 {
15778 fixClassDeclaration(isSgClassDeclaration(stmt),scope);
15779 }
15780 else if (isSgLabelStatement(stmt))
15781 {
15782 fixLabelStatement(isSgLabelStatement(stmt),scope);
15783 }
15784 else if (isSgFunctionDeclaration(stmt))
15785 {
15786#if 1
15787 fixFunctionDeclaration(isSgFunctionDeclaration(stmt),scope);
15788#else
15789 // fix function type table's parent edge
15790 // Liao 5/4/2010
15792 ROSE_ASSERT(fTable);
15793 if (fTable->get_parent() == NULL)
15794 fTable->set_parent(getGlobalScope(scope));
15795
15796 // Liao 4/23/2010, Fix function symbol
15797 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15798 SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt);
15799 SgMemberFunctionDeclaration* mfunc = isSgMemberFunctionDeclaration(stmt);
15800
15801 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15802 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15803
15804 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15805 // It is an error to put the symbol for a function into the current scope if the function's scope
15806 // is explicitly set to be different. So this should be allowed only if the function's scope is
15807 // not explicitly set, or if the scopes match. This is an example of something different for C++
15808 // than for C or other simpler languages.
15809 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15810 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15811 {
15812#if 0
15813 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());
15814#endif
15815 SgFunctionSymbol* func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type());
15816
15817 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15818 if (func_symbol == NULL)
15819 {
15820 // DQ (12/3/2011): Added support for C++ member functions.
15821 // func_symbol = new SgFunctionSymbol (func);
15822 if (mfunc != NULL)
15823 {
15824 func_symbol = new SgMemberFunctionSymbol (func);
15825 }
15826 else
15827 {
15828 func_symbol = new SgFunctionSymbol (func);
15829 }
15830 ROSE_ASSERT (func_symbol != NULL);
15831
15832 scope->insert_symbol(func->get_name(), func_symbol);
15833 }
15834 else
15835 {
15836 printf ("In SageInterface::fixStatement(): found a valid function so no need to insert new symbol \n");
15837 }
15838 }
15839#if 0
15840 // Fix local symbol, a symbol directly refer to this function declaration
15841 // This could happen when a non-defining func decl is copied, the corresonding symbol will point to the original source func
15842 // symbolTable->find(this) used inside get_symbol_from_symbol_table() won't find the copied decl
15843 SgSymbol* local_symbol = func ->get_symbol_from_symbol_table();
15844 if (local_symbol == NULL) //
15845 {
15846 if (func->get_definingDeclaration() == NULL) // prototype function
15847 {
15848 SgFunctionDeclaration * src_func = func_symbol->get_declaration();
15849 if (func != src_func )
15850 {
15851 ROSE_ASSERT (src_func->get_firstNondefiningDeclaration () == src_func);
15852 func->set_firstNondefiningDeclaration (func_symbol->get_declaration());
15853 }
15854 }
15855 }
15856#endif
15857#endif
15858 }
15859 else if (isSgTemplateDeclaration(stmt) != NULL)
15860 {
15861 // DQ (12/3/2011): Added new case for SgTemplateDeclaration (adding template declarations to the AST).
15862 fixTemplateDeclaration(isSgTemplateDeclaration(stmt),scope);
15863 }
15864
15865#if 0
15866 // DQ (12/4/2011): This WAS not the correct behavior for C++ since declarations can appear structureally in different
15867 // scopes than where the are positioned (e.g. member functions defined outside of there associated class).
15868 // This this code is very dangerous.
15869
15870 // fix scope pointer for statements explicitly storing scope pointer
15871 switch (stmt->variantT())
15872 {
15873 // The case of SgLabelStatement should maybe be included.
15874 case V_SgEnumDeclaration:
15875 case V_SgTemplateDeclaration:
15876 case V_SgTypedefDeclaration:
15877 case V_SgFunctionDeclaration:
15878 case V_SgMemberFunctionDeclaration:
15879 case V_SgTemplateInstantiationFunctionDecl:
15880 {
15881 // DQ (12/4/2011): We can't just set the scope this simily (except in C). In C++ the scope should have
15882 // already been set or we can let it default to the current scope where it si located structurally.
15883 // stmt->set_scope(scope);
15884 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
15885 {
15886 stmt->set_scope(scope);
15887 }
15888 break;
15889 }
15890
15891 default:
15892 {
15893 // debugging support...
15894 printf ("In SageInterface::fixStatement(): switch default case used (likely OK): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15895 ROSE_ASSERT(stmt->hasExplicitScope() == false);
15896#if 0
15897 printf ("switch case not handled properly: stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15898 ROSE_ABORT();
15899#endif
15900 break;
15901 }
15902 }
15903#else
15904 // If the scoep has to be set and it has not yet been set, then set it directly.
15905 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
15906 {
15907 stmt->set_scope(scope);
15908 }
15909#endif
15910 }
15911
15912
15925 {
15926 // DQ (11/19/2012): Note that this appears to be an expensive function presently taking 22.5% of the total time
15927 // to process the tests/CompilerTests/Cxx_tests/rosePerformance.C file. So this is a performance problem.
15928
15929 ROSE_ASSERT(func != NULL && scope != NULL);
15930
15931 ROSE_ASSERT(func != NULL);
15932 ROSE_ASSERT(scope != NULL);
15933
15934 SgStatementPtrList stmtList, sameFuncList;
15935
15936 // SgFunctionDeclaration* first_nondef = NULL;
15937 // Some annoying part of scope
15938 if (scope->containsOnlyDeclarations())
15939 {
15940 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
15941 SgDeclarationStatementPtrList::iterator i;
15942 for (i=declList.begin();i!=declList.end();i++)
15943 stmtList.push_back(*i);
15944 }
15945 else
15946 {
15947 stmtList = scope->getStatementList();
15948 }
15949
15950 SgFunctionDeclaration* firstNondefiningFunctionDeclaration = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
15951 if (firstNondefiningFunctionDeclaration != NULL)
15952 {
15953 // If there exists a non-NULL reference to a firstNondefiningFunctionDeclaration
15954 // then use it (unless we want to handle where it might be set wrong).
15955#if 0
15956 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid pointer to a firstNondefiningFunctionDeclaration = %p \n",func,firstNondefiningFunctionDeclaration);
15957#endif
15958 }
15959
15960 // DQ (3/12/2012): Added assertion
15961 // ROSE_ASSERT(scope == func->get_firstNondefiningDeclaration()->get_scope());
15962 ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope() != NULL);
15963
15964 // 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.
15965 if (func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) == NULL)
15966 {
15967 printf ("WARNING: symbol for func->get_firstNondefiningDeclaration() = %p = %s = %s is not present in the scope = %p = %s associated with the firstNondefiningDeclaration \n",
15968 func->get_firstNondefiningDeclaration(),func->get_firstNondefiningDeclaration()->class_name().c_str(),func->get_name().str(),
15970 }
15971 // ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) != NULL);
15972
15973#if 0
15974 // It would be better to find the first non-defining declaration via the symbol.
15975 SgSymbol* functionSymbol = scope->lookup_function_symbol(func->get_name(),func->get_type());
15976 if (functionSymbol != NULL)
15977 {
15978 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid symbol = %p \n",func,functionSymbol);
15979 }
15980 else
15981 {
15982 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p functionSymbol == NULL \n",func);
15983 }
15984#endif
15985
15986 // Find the same function declaration list, including func itself
15987 SgStatementPtrList::iterator j;
15988 for (j = stmtList.begin(); j != stmtList.end(); j++)
15989 {
15990 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
15991 if (func_decl != NULL)
15992 {
15993 // DQ (11/19/2012): This call to the isSameFunction() function is taking a total of 22.1%
15994 // of the total execution time of the tests/CompilerTests/Cxx_tests/rosePerformance.C file.
15995 if (isSameFunction(func_decl, func))
15996 {
15997 // Assume all defining functions have definingdeclaration links set properly already!!
15998 sameFuncList.push_back(func_decl);
15999 }
16000 }
16001 }
16002
16003#if 0
16004 printf ("func = %p \n",func);
16005 printf ("func->get_definingDeclaration() = %p \n",func->get_definingDeclaration());
16006#endif
16007
16008 ROSE_ASSERT(func != NULL);
16009
16010 if (func->get_definingDeclaration() == func)
16011 {
16012 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16013 isSgFunctionDeclaration(*j)->set_definingDeclaration(func);
16014 }
16015 else
16016 {
16017 ROSE_ASSERT(func != NULL);
16018
16019 // DQ (3/9/2012): Added assertion to avoid empty list that would be an error in both cases below.
16020 ROSE_ASSERT(sameFuncList.empty() == false);
16021
16022 if (func == isSgFunctionDeclaration(*(sameFuncList.begin()))) // is first_nondefining declaration
16023 {
16024 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16025 {
16026 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16027#if 0
16028 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Testing j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16029#endif
16030 // DQ (3/9/2012): Avoid setting the function to be it's own firstNondefiningDeclaration.
16031 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16032 if (func_decl != func)
16033 {
16034 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16035 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16036 if (func_decl->get_firstNondefiningDeclaration() == NULL)
16037 {
16038#if 0
16039 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Calling j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16040#endif
16041 func_decl->set_firstNondefiningDeclaration(func);
16042 }
16043 }
16044 }
16045 }
16046 else // is a following nondefining declaration, grab any other's first nondefining link then
16047 {
16048#if 0
16049 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Testing func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16050#endif
16051 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16052 // func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16053 if (func->get_firstNondefiningDeclaration() == NULL)
16054 {
16055#if 0
16056 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Calling func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16057#endif
16058 func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16059 }
16060 }
16061 }
16062 }
16063
16064PreprocessingInfo* SageInterface::attachComment(SgSourceFile * source_file, const std::string & content, PreprocessingInfo::DirectiveType directive_type, PreprocessingInfo::RelativePositionType position) {
16065 assert(source_file != NULL);
16066 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16067
16068 SgGlobal * global_scope = source_file->get_globalScope();
16069
16070 PreprocessingInfo* result = new PreprocessingInfo(directive_type, content, "Transformation generated",0, 0, 0, position);
16071 ROSE_ASSERT(result);
16072
16073 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16074 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16075 // when multiple files are used on the command line.
16076 result->get_file_info()->setTransformation();
16077
16078 global_scope->addToAttachedPreprocessingInfo(result, position);
16079
16080 return result;
16081}
16082
16083//---------------------------------------------------------------
16085 SgLocatedNode* target, const string& content,
16086 PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/,
16087 PreprocessingInfo::DirectiveType dtype /* PreprocessingInfo::CpreprocessorUnknownDeclaration */)
16088 {
16089 ASSERT_not_null(target); //dangling comment is not allowed
16090
16091 PreprocessingInfo* result = NULL;
16092 PreprocessingInfo::DirectiveType mytype=dtype;
16093 string comment;
16094
16095 // Rasmussen (11/3/2020): Added Ada and Jovial style comments
16096 // DQ (5/5/2010): infer comment type from target's language
16097 if (mytype == PreprocessingInfo::CpreprocessorUnknownDeclaration)
16098 {
16099 // This is a rather expensive way to detect the language type (chases pointers back to the SgFile object).
16100 if (is_C_language() || is_C99_language())
16101 {
16102 // Comment = "/* "+ content + " */";
16103 mytype = PreprocessingInfo::C_StyleComment;
16104 }
16105 else if (is_Cxx_language() || is_Java_language())
16106 {
16107 // Comment = "// "+ content;
16108 mytype = PreprocessingInfo::CplusplusStyleComment;
16109 }
16110 else if (is_Fortran_language() || is_CAF_language()) //FMZ:3/23/2009
16111 {
16112 // Comment = "! "+ content;
16113 mytype = PreprocessingInfo::F90StyleComment;
16114 }
16115 else if (is_Ada_language())
16116 {
16117 // Comment = "-- " + content;
16118 mytype = PreprocessingInfo::AdaStyleComment;
16119 }
16120 else if (is_Jovial_language())
16121 {
16122 // Comment = "% " + content + " %";
16123 mytype = PreprocessingInfo::JovialStyleComment;
16124 }
16125 else
16126 {
16127 cout << "WARNING: SageInterface::attachComment(): Unknown programming language \n";
16128 ROSE_ABORT();
16129 }
16130 }
16131
16132 // Once the langauge type is set (discovered automatically or more directly specified by the user).
16133 bool resetPositionInfo = false;
16134 switch (mytype)
16135 {
16136 case PreprocessingInfo::C_StyleComment: comment = "/* " + content + " */"; break;
16137 case PreprocessingInfo::CplusplusStyleComment: comment = "// " + content; break;
16138 case PreprocessingInfo::FortranStyleComment: comment = " C " + content; break;
16139 case PreprocessingInfo::F90StyleComment: comment = "!" + content; break;
16140 case PreprocessingInfo::AdaStyleComment: comment = "-- " + content; break;
16141 case PreprocessingInfo::JovialStyleComment:
16142 // The Jovial comment content will already have the comment delimiters, '%' or '"'
16143 comment = content;
16144 break;
16145 case PreprocessingInfo::CpreprocessorLineDeclaration:
16146 comment = "#myline " + content;
16147 mytype = PreprocessingInfo::CplusplusStyleComment;
16148 resetPositionInfo = true;
16149 break;
16150 case PreprocessingInfo::CpreprocessorIfndefDeclaration: comment = "#ifndef " + content + "\n"; break;
16151 case PreprocessingInfo::CpreprocessorDefineDeclaration: comment = "#define " + content + "\n"; break;
16152 case PreprocessingInfo::CpreprocessorEndifDeclaration: comment = "#endif" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16153 case PreprocessingInfo::CpreprocessorEnd_ifDeclaration: comment = "#end if" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16154
16155 default:
16156 {
16157 printf ("Error: default in switch reached in SageInterface::attachComment() PreprocessingInfo::DirectiveType == %d \n",mytype);
16158 ROSE_ABORT();
16159 }
16160 }
16161
16162 result = new PreprocessingInfo (mytype,comment, "transformation-generated", 0, 0, 0, position);
16163
16164 // If this is a Cpp Line declaration then we have to set the position to match the statement.
16165 if (resetPositionInfo == true)
16166 {
16167 // Call the Sg_File_Info::operator=() member function.
16168 *(result->get_file_info()) = *(target->get_file_info());
16169 }
16170 else
16171 {
16172 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16173 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16174 // when multiple files are used on the command line.
16175 result->get_file_info()->setTransformation();
16176 }
16177
16178 ASSERT_not_null(result);
16179 target->addToAttachedPreprocessingInfo(result);
16180 return result;
16181 }
16182
16183void SageInterface::guardNode(SgLocatedNode * target, std::string guard) {
16184 PreprocessingInfo * if_macro = new PreprocessingInfo(
16185 PreprocessingInfo::CpreprocessorIfDeclaration,
16186 "#if " + guard,
16187 "transformation-generated", 0, 0, 0,
16188 PreprocessingInfo::before
16189 );
16190 target->addToAttachedPreprocessingInfo(if_macro);
16191
16192 PreprocessingInfo * endif_macro = new PreprocessingInfo(
16193 PreprocessingInfo::CpreprocessorEndifDeclaration,
16194 "#endif",
16195 "transformation-generated", 0, 0, 0,
16196 PreprocessingInfo::after
16197 );
16198 target->addToAttachedPreprocessingInfo(endif_macro);
16199
16200// DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16201// This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16202// when multiple files are used on the command line.
16203 if_macro->get_file_info()->setTransformation();
16204 endif_macro->get_file_info()->setTransformation();
16205}
16206
16207// internal hash table to cache the results: fileHeaderDict[file][header-key]
16208// header-key:
16209// system header : <header.h>
16210// non-system headers : "header.h"
16211static map<SgSourceFile*, map<string, PreprocessingInfo*> > fileHeaderDict;
16213PreprocessingInfo * SageInterface::findHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader)
16214{
16215 string header_key;
16216 if (isSystemHeader)
16217 header_key="<"+header_file_name+">";
16218 else
16219 header_key="\""+header_file_name+"\"";
16220
16221 if (fileHeaderDict.count(source_file) && fileHeaderDict[source_file].count(header_key))
16222 return fileHeaderDict[source_file][header_key];
16223
16224 vector<SgLocatedNode*> candidates;
16225 // do a fresh check. we only check global scope's declarations since we insert header into global scope
16226 // check SgGlobal
16227 SgGlobal* global= source_file -> get_globalScope();
16228
16229 candidates.push_back(global);
16230
16231 //check declarations within the global scope
16232 SgDeclarationStatementPtrList decl_stmt_list = global->get_declarations();
16233 for (SgDeclarationStatementPtrList::iterator iter= decl_stmt_list.begin(); iter!=decl_stmt_list.end(); iter++)
16234 candidates.push_back(*iter);
16235
16236 bool found = false;
16237 for (size_t ci=0; ci<candidates.size(); ci++)
16238 {
16239 SgLocatedNode* locatedNode= candidates[ci];
16240 AttachedPreprocessingInfoType *comments = locatedNode->getAttachedPreprocessingInfo ();
16241
16242 if (comments == NULL) continue;
16243 AttachedPreprocessingInfoType::iterator i;
16244 for (i = comments->begin (); i != comments->end (); i++)
16245 {
16246 if ((*i)->getTypeOfDirective () != PreprocessingInfo::CpreprocessorIncludeDeclaration) continue;
16247 string content = (*i)->getString ();
16248 if (content.find(header_key) != string::npos)
16249 {
16250 fileHeaderDict[source_file][header_key] = *i;
16251 found =true;
16252 break;
16253 }
16254
16255 } // each comment
16256
16257 if (found) break;
16258 } // each node
16259
16260 if (found)
16261 return fileHeaderDict[source_file][header_key];
16262 return NULL;
16263}
16264
16266SageInterface::insertHeader(SgSourceFile * source_file, const string & header_file_name, bool isSystemHeader, PreprocessingInfo::RelativePositionType position)
16267 {
16268 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16269 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16270 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16271 bool supportTokenUnparsing = false;
16272
16273 assert(source_file != NULL);
16274 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16275
16276 SgGlobal * global_scope = source_file->get_globalScope();
16277
16278 string content;
16279 if (isSystemHeader)
16280 content = "#include <" + header_file_name + "> \n";
16281 else
16282 content = "#include \"" + header_file_name + "\" \n";
16283
16284 PreprocessingInfo* result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, position);
16285 ROSE_ASSERT(result);
16286
16287 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16288 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16289 // when multiple files are used on the command line.
16290 result->get_file_info()->setTransformation();
16291
16292 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16293 supportTokenUnparsing = source_file->get_unparse_tokens();
16294 bool supportUnparseHeaders = source_file->get_unparseHeaderFiles();
16295
16296#if 0
16297 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16298 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16299 printf ("source_file = %p \n",source_file);
16300 printf ("global_scope = %p \n",global_scope);
16301#endif
16302#if 0
16303 printf ("Exiting as a test! \n");
16304 ROSE_ABORT();
16305#endif
16306
16307 // global_scope->addToAttachedPreprocessingInfo(result, position);
16308 if (supportTokenUnparsing == false)
16309 {
16310 global_scope->addToAttachedPreprocessingInfo(result, position);
16311 }
16312 else
16313 {
16314 // global_scope->prepend_statement(null_statement);
16315 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16316
16317 if (supportUnparseHeaders == true)
16318 {
16319 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16320 int physical_file_id = global_scope->get_startOfConstruct()->get_physical_file_id();
16321#if 0
16322 printf ("physical_file_id = %d \n",physical_file_id);
16323#endif
16324 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16325 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16326#if 0
16327 printf ("Exiting as a test! \n");
16328 ROSE_ABORT();
16329#endif
16330 }
16331
16332 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16333
16334 global_scope->prepend_statement(emptyDeclaration);
16335 }
16336
16337#if 0
16338 printf ("Exiting as a test! \n");
16339 ROSE_ASSERT(false);
16340#endif
16341
16342 return result;
16343 }
16344
16345PreprocessingInfo* SageInterface::insertHeader(const string& filename, PreprocessingInfo::RelativePositionType position /*=after*/, bool isSystemHeader /*=false*/, SgScopeStatement* scope /*=NULL*/)
16346 {
16347 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16348 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16349 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16350 bool supportTokenUnparsing = false;
16351
16352 // DQ (8/12/2020): This is a compiler warning.
16353 // bool successful = false;
16354
16355#if 0
16356 printf ("In SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16357 printf (" --- position = %s \n",PreprocessingInfo::relativePositionName(position).c_str());
16358#endif
16359
16360 if (scope == NULL)
16362
16363 ROSE_ASSERT(scope);
16364
16365 SgGlobal* globalScope = getGlobalScope(scope);
16366 ROSE_ASSERT(globalScope != NULL);
16367
16368 // 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
16369 // if the input scope is within a header file,
16370 // its global scope will jump to a .cpp file. Later looping will not find a match.
16371 SgScopeStatement* srcScope = globalScope;
16372 PreprocessingInfo* result=NULL;
16373 string content;
16374 if (isSystemHeader)
16375 content = "#include <" + filename + "> \n";
16376 else
16377 content = "#include \"" + filename + "\" \n";
16378
16379 // DQ (11/21/2019): Token based unparsing has an additional requirement, we need to mark that the
16380 // whitespace around the statement has been modified. This will trigger the unparser to output
16381 // the comments and CPP directives when using the token-based unparsing. The insertion of a header
16382 // file requires this support else the original token stream will not have the added header file.
16383
16384 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16385 SgSourceFile* sourceFile = getEnclosingSourceFile(scope);
16386 ROSE_ASSERT(sourceFile != NULL);
16387
16388 supportTokenUnparsing = sourceFile->get_unparse_tokens();
16389
16390 bool supportUnparseHeaders = sourceFile->get_unparseHeaderFiles();
16391 // if unparsing header and the scope is within a header file, we adjust srcScope to be scope, not its enclosing global scope
16392 if (supportUnparseHeaders)
16393 {
16394 string filename= scope->get_file_info()->get_filename();
16395 string suffix = Rose::StringUtility ::fileNameSuffix(filename);
16396
16397 // vector.tcc: This is an internal header file, included by other library headers
16398 if (suffix=="h" ||suffix=="hpp"|| suffix=="hh"||suffix=="H" ||suffix=="hxx"||suffix=="h++" ||suffix=="tcc")
16399 srcScope = scope;
16400 }
16401
16402#if 0
16403 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16404 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16405 printf ("sourceFile = %p \n",sourceFile);
16406 printf ("globalScope = %p \n",globalScope);
16407#endif
16408#if 0
16409 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16410#endif
16411#if 0
16412 printf ("Exiting as a test! \n");
16413 ROSE_ABORT();
16414#endif
16415
16416 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations();
16417
16418#if 0
16419 printf ("stmtList.size() = %zu \n",stmtList.size());
16420#endif
16421
16422 if (stmtList.size() > 0) // the source file is not empty
16423 {
16424 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16425 {
16426 // must have this judgement, otherwise wrong file will be modified!
16427 // It could also be the transformation generated statements with #include attached
16428 if ( ((*j)->get_file_info())->isSameFile(srcScope->get_file_info ()) || ((*j)->get_file_info ())->isTransformation() )
16429 {
16430 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16431 ROSE_ASSERT(result != NULL);
16432#if 0
16433 printf ("Building a PreprocessingInfo: result = %p \n",result);
16434#endif
16435 // DQ (3/22/2019): Fixing this to work with the token-based unparsing.
16436 // add to the last position
16437 // TODO: support to add to the first,
16438 // TODO: support fine positioning with #include directives
16439 // (*j)->addToAttachedPreprocessingInfo(result,position);
16440
16441 if (supportTokenUnparsing == false)
16442 {
16443 (*j)->addToAttachedPreprocessingInfo(result,position);
16444 }
16445 else
16446 {
16447 (*j)->addToAttachedPreprocessingInfo(result,position);
16448#if 0
16449 printf ("In SageInterface::insertHeader(): Calling set_containsTransformationToSurroundingWhitespace(true) \n");
16450#endif
16451#if 1
16452 // DQ (12/31/2020): Set the whitespace around the statement as being modified.
16453 (*j)->set_containsTransformationToSurroundingWhitespace(true);
16454#endif
16455#if 0
16456 SgDeclarationStatement* declarationStatement = *j;
16457
16458 // DQ (1/5/2021): Don't call unparseToString, since this triggers the unparer which then unparses
16459 // from the token stream and makrs some token stream elements as already unparsed.
16460 // printf ("declarationStatement = %p = %s unparseToString() = %s \n",declarationStatement,
16461 // declarationStatement->class_name().c_str(),declarationStatement->unparseToString().c_str());
16462 printf ("In SageInterface::insertHeader(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
16463 printf ("In SageInterface::insertHeader(): declarationStatement->get_containsTransformationToSurroundingWhitespace() = %s \n",
16464 declarationStatement->get_containsTransformationToSurroundingWhitespace() ? "true" : "false");
16465#endif
16466#if 0
16467 // Liao, let's try the new way.
16468 // global_scope->prepend_statement(null_statement);
16469 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16470
16471 if (supportUnparseHeaders == true)
16472 {
16473 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16474 int physical_file_id = globalScope->get_startOfConstruct()->get_physical_file_id();
16475#if 0
16476 printf ("physical_file_id = %d \n",physical_file_id);
16477#endif
16478 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16479 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16480#if 0
16481 printf ("Exiting as a test! \n");
16482 ROSE_ASSERT(false);
16483#endif
16484 }
16485
16486 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16487
16488 globalScope->insert_statement(*j,emptyDeclaration);
16489#endif
16490 }
16491#if 0
16492 printf ("break out of for loop: result = %p \n",result);
16493#endif
16494 // DQ (8/12/2020): This is a compiler warning.
16495 // successful = true;
16496 break;
16497 }
16498 }
16499 }
16500 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16501 {
16502 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16503 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16504 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16505 ROSE_ASSERT(false);
16506 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16507 ROSE_ASSERT(result);
16508 globalScope->addToAttachedPreprocessingInfo(result,position);
16509
16510 // DQ (8/12/2020): This is a compiler warning.
16511 // successful = true;
16512 }
16513
16514 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16515 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16516 // when multiple files are used on the command line.
16517 // DQ (3/12/2019): This can be NULL for the omp tests.
16518 if (result != NULL)
16519 {
16520 result->get_file_info()->setTransformation();
16521 }
16522
16523 // must be inserted once somehow
16524 // 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
16525 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16526 // ROSE_ASSERT(successful==true);
16527
16528#if 0
16529 printf ("Exiting as a test! \n");
16530 ROSE_ASSERT(false);
16531#endif
16532
16533#if 0
16534 printf ("Leaving SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16535#endif
16536
16537#if 0
16538 printf ("Exiting as a test! \n");
16539 ROSE_ASSERT(false);
16540#endif
16541
16542 return result;
16543 }
16544
16545
16546// 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
16547void SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader)
16548{
16549 ROSE_ASSERT (stmt != NULL);
16550 ROSE_ASSERT (newheader != NULL);
16551
16552#if 0
16553 printf ("In SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader) \n");
16554#endif
16555
16557
16558 if (asLastHeader )
16559 position = PreprocessingInfo::after;
16560 else
16561 position = PreprocessingInfo::before;
16562
16563
16564 // Find existing first and last header.
16565 AttachedPreprocessingInfoType *comments = stmt->getAttachedPreprocessingInfo ();
16566
16567 if (comments != NULL)
16568 {
16569 PreprocessingInfo * firstExistingHeader = NULL;
16570 PreprocessingInfo * lastExistingHeader = NULL;
16571 PreprocessingInfo * firstExistingEndif = NULL;
16572
16573 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16574 // PreprocessingInfo * lastExistingEndif = NULL;
16575
16576 AttachedPreprocessingInfoType::iterator i, firsti, lasti;
16577 for (i = comments->begin (); i != comments->end (); i++)
16578 {
16579 // DQ (9/12/2020): this original code is not sufficent since when the final #include is enclosed in a
16580 // #ifdef #endif the added include directive might not be visible in the generated file.
16581 // This actually happened in the case of wget application: wget.c source file.
16582#if 0
16583 // Original version of code.
16584 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16585 {
16586 // Only set first header for the first time
16587 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16588 {
16589 if (firstExistingHeader == NULL)
16590 {
16591 firstExistingHeader = (*i);
16592 firsti = i;
16593 }
16594 // always updates last header
16595 lastExistingHeader = (*i);
16596 lasti = i;
16597 }
16598 }
16599#else
16600 // DQ (9/12/2020): New version of code. Addresses insertion after last endif if it is after any #include.
16601 if ( (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration ||
16602 (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration )
16603 {
16604 // Only set first header for the first time
16605 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16606 {
16607 if (firstExistingHeader == NULL)
16608 {
16609 firstExistingHeader = (*i);
16610 firsti = i;
16611 }
16612 // always updates last header
16613 lastExistingHeader = (*i);
16614 lasti = i;
16615 }
16616 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration)
16617 {
16618 if (firstExistingEndif == NULL)
16619 {
16620 firstExistingEndif = (*i);
16621 firsti = i;
16622 }
16623 // always updates last header
16624 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16625 // lastExistingEndif = (*i);
16626 lasti = i;
16627 }
16628 }
16629#endif
16630 }
16631
16632 // based on existing header positions, insert the new header
16633 if (asLastHeader)
16634 {
16635 if (lastExistingHeader == NULL) // No last header at all, just append to after
16636 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16637 else
16638 {
16639 comments->insert (lasti+1, newheader);
16640 }
16641 }
16642 else // add as the first header
16643 {
16644 if (firstExistingHeader == NULL) // no existing header at all, just append to after
16645 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16646 else
16647 {
16648 comments->insert (firsti, newheader);
16649 }
16650 }
16651 }
16652 else // No comments at all, first and last header mean the same, just attach to the located node
16653 stmt->addToAttachedPreprocessingInfo(newheader, position);
16654
16655#if 0
16656 printf ("Exiting as a test! \n");
16657 ROSE_ASSERT(false);
16658#endif
16659
16660}
16661
16662
16663// The recommended version
16664PreprocessingInfo* SageInterface::insertHeader(SgSourceFile * source_file, const std::string & filename, bool isSystemHeader , bool asLastHeader)
16665{
16666 ROSE_ASSERT (source_file != NULL);
16667 SgGlobal* globalScope = source_file->get_globalScope();
16668 ROSE_ASSERT (globalScope != NULL);
16669
16670 PreprocessingInfo* result=NULL;
16671 string content;
16672 if (isSystemHeader)
16673 content = "#include <" + filename + "> \n";
16674 else
16675 content = "#include \"" + filename + "\" \n";
16676
16677#if 0
16678 // 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.
16680
16681 if (asLastHeader )
16682 position = PreprocessingInfo::after;
16683 else
16684 position = PreprocessingInfo::before;
16685#endif
16686
16687 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations ();
16688 if (stmtList.size()>0) // the source file is not empty
16689 {
16690 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16691 {
16692 // Attach to the first eligible located statement
16693 //must have this judgement, otherwise wrong file will be modified!
16694 //It could also be the transformation generated statements with #include attached
16695 if ( (*j)->get_file_info()->isSameFile(globalScope->get_file_info()) || (*j)->get_file_info()->isTransformation() )
16696 {
16697#if 0
16698 printf ("In SageInterface::insertHeader(): Found statement to attached #include: *j = %p = %s \n",*j,(*j)->class_name().c_str());
16699 printf (" --- unparseToString() = %s \n",(*j)->unparseToString().c_str());
16700#endif
16701 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16702 ROSE_ASSERT(result);
16703 insertHeader (*j, result, asLastHeader);
16704 //successful = true;
16705#if 0
16706 printf ("Exiting as a test! \n");
16707 ROSE_ABORT();
16708#endif
16709 break;
16710 }
16711 } // end for
16712 }
16713 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16714 {
16715 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16716 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16717 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16718 ROSE_ABORT();
16719#if 0 // [Robb Matzke 2021-03-24]: unreachable
16720 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration,
16721 content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16722 ROSE_ASSERT(result);
16723 globalScope->addToAttachedPreprocessingInfo(result,position);
16724#endif
16725 // successful = true;
16726 }
16727
16728#if 0
16729 printf ("In SageInterface::insertHeader(): Marking include file for filename = %s as a transformation \n",filename.c_str());
16730#endif
16731
16732 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16733 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16734 // when multiple files are used on the command line.
16735 if (result)
16736 result->get_file_info()->setTransformation();
16737
16738#if 0
16739 printf ("Exiting as a test! \n");
16740 ROSE_ASSERT(false);
16741#endif
16742
16743 // must be inserted once somehow
16744 // 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
16745 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16746 // ROSE_ASSERT(successful==true);
16747 return result;
16748
16749} // end insertHeader
16750
16751
16754SageInterface::attachArbitraryText(SgLocatedNode* target, const std::string & text, PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/)
16755 {
16756 // DQ (1/13/2014): This function needs a better mechanism than attaching text to the AST unparser as a CPP directive.
16757
16758 ROSE_ASSERT(target != NULL); //dangling #define xxx is not allowed in the ROSE AST
16759 PreprocessingInfo* result = NULL;
16760
16761 // DQ (1/13/2014): It is a mistake to attach arbitrary test to the AST as a #define
16762 // (since we evaluate all #define CPP declarations to be a self-referential macro).
16763 // For now I will make it a #if CPP declaration, since these are not evaluated internally.
16764 // PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorDefineDeclaration;
16765 PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorIfDeclaration;
16766
16767 // DQ (1/13/2014): Output a warning so that this can be fixed whereever it is used.
16768 printf ("Warning: attachArbitraryText(): attaching arbitrary text to the AST as a #if declaration: text = %s \n",text.c_str());
16769
16770 result = new PreprocessingInfo (mytype,text, "transformation-generated", 0, 0, 0, position);
16771 ROSE_ASSERT(result);
16772
16773 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16774 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16775 // when multiple files are used on the command line.
16776 result->get_file_info()->setTransformation();
16777
16778 target->addToAttachedPreprocessingInfo(result);
16779
16780 return result;
16781 }
16782
16783
16785// 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.
16787{
16788 // This is part of Wave support in ROSE.
16789// #if CAN_NOT_COMPILE_WITH_ROSE != true
16790// #if CAN_NOT_COMPILE_WITH_ROSE == 0
16791#ifndef USE_ROSE
16792 ROSE_ASSERT(target != NULL);
16793 AttachedPreprocessingInfoType *info= target->getAttachedPreprocessingInfo ();
16794 if (info == NULL) return;
16795 AttachedPreprocessingInfoType::iterator j;
16796 for (j = info->begin (); j != info->end (); j++)
16797 {
16798 if ((*j)->getTypeOfDirective()==PreprocessingInfo::CMacroCall)
16799 {
16800#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
16801 // DQ (2/17/2016): The token_container type is not defined if Wave is not available.
16802 std::ostringstream os;
16803 token_container tc = (*j)->get_macro_call()->expanded_macro;
16804 token_container::const_iterator iter;
16805 for (iter=tc.begin(); iter!=tc.end(); iter++)
16806 os<<(*iter).get_value();
16807 //cout<<"Found a macro call: "<<(*j)->getString()<<
16808 //"\nexpanding it to: "<<os.str()<<endl;
16809 string pragmaText = target->get_pragma()->get_pragma();
16810 string targetString = (*j)->getString();
16811 string replacement = os.str();
16812 // repeat until not found
16813 size_t pos1 = pragmaText.find(targetString);
16814 while (pos1 != string::npos)
16815 {
16816 pragmaText.replace(pos1, targetString.size(), replacement);
16817 pos1 = pragmaText.find(targetString);
16818 }
16819 delete target->get_pragma();
16820 target->set_pragma(buildPragma(pragmaText));
16821#endif
16822 } // end if
16823 } // end for
16824#endif
16825}
16826
16831 using namespace SageBuilder;
16832 SgStatement* body = NULL;
16833 if (isSgWhileStmt(loopOrSwitch) || isSgDoWhileStmt(loopOrSwitch) ||
16834 isSgForStatement(loopOrSwitch)) {
16835 body = SageInterface::getLoopBody(isSgScopeStatement(loopOrSwitch));
16836 } else if (isSgSwitchStatement(loopOrSwitch)) {
16837 body = isSgSwitchStatement(loopOrSwitch)->get_body();
16838 }
16839 ROSE_ASSERT (body);
16840 std::vector<SgBreakStmt*> breaks = SageInterface::findBreakStmts(body);
16841 if (!breaks.empty()) {
16842 static int breakLabelCounter = 0;
16843 SgLabelStatement* breakLabel =
16844 buildLabelStatement("breakLabel" +
16845StringUtility::numberToString(++breakLabelCounter),
16847 isSgScopeStatement(loopOrSwitch->get_parent()));
16848 insertStatement(loopOrSwitch, breakLabel, false);
16849 for (size_t j = 0; j < breaks.size(); ++j) {
16850 SgGotoStatement* newGoto = buildGotoStatement(breakLabel);
16851
16852 isSgStatement(breaks[j]->get_parent())->replace_statement(breaks[j],
16853 newGoto);
16854 newGoto->set_parent(breaks[j]->get_parent());
16855 }
16856 }
16857 }
16858
16860 {
16861 ROSE_ASSERT(node!=NULL);
16862 SgClassDeclaration *decl = isSgClassDeclaration(node);
16863 if (decl==NULL)
16864 return false;
16865 else
16866 return (decl->get_class_type() == SgClassDeclaration::e_struct)? true:false;
16867 }
16868
16870 {
16871 ROSE_ASSERT(node!=NULL);
16872 SgClassDeclaration *decl = isSgClassDeclaration(node);
16873 if (decl==NULL)
16874 return false;
16875 else
16876 return (decl->get_class_type() == SgClassDeclaration::e_union)? true:false;
16877 }
16878
16879
16880void
16881SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
16882 PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
16883 {
16884 ROSE_ASSERT(stmt_src != NULL);
16885 ROSE_ASSERT(stmt_dst != NULL);
16886 AttachedPreprocessingInfoType* infoList = stmt_src->getAttachedPreprocessingInfo();
16887
16888 if (infoList == NULL)
16889 {
16890#if 0
16891 printf ("In SageInterface::movePreprocessingInfo(): infoList == NULL: exiting movePreprocessingInfo() \n");
16892#endif
16893 return;
16894 }
16895
16896 AttachedPreprocessingInfoType* infoToRemoveList = new AttachedPreprocessingInfoType();
16897
16898#if 0
16899 printf ("In SageInterface::movePreprocessingInfo(): \n");
16900 printf (" --- stmt_src = %p = %s src_position = %d \n",stmt_src,stmt_src->class_name().c_str(),src_position);
16901 SgDeclarationStatement* src_declarationStatement = isSgDeclarationStatement(stmt_src);
16902 if (src_declarationStatement != NULL)
16903 {
16904 printf ("src_declarationStatement->get_firstNondefiningDeclaration() = %p \n",src_declarationStatement->get_firstNondefiningDeclaration());
16905 printf ("src_declarationStatement->get_definingDeclaration() = %p \n",src_declarationStatement->get_definingDeclaration());
16906 }
16907 printf (" --- stmt_dst = %p = %s dst_position = %d \n",stmt_dst,stmt_dst->class_name().c_str(),dst_position);
16908 SgDeclarationStatement* dst_declarationStatement = isSgDeclarationStatement(stmt_dst);
16909 if (dst_declarationStatement != NULL)
16910 {
16911 printf ("dst_declarationStatement->get_firstNondefiningDeclaration() = %p \n",dst_declarationStatement->get_firstNondefiningDeclaration());
16912 printf ("dst_declarationStatement->get_definingDeclaration() = %p \n",dst_declarationStatement->get_definingDeclaration());
16913 }
16914 printf (" --- src_position = %s \n",PreprocessingInfo::relativePositionName(src_position).c_str());
16915 printf (" --- dst_position = %s \n",PreprocessingInfo::relativePositionName(dst_position).c_str());
16916 printf (" --- usePrepend = %s \n",usePrepend ? "true" : "false");
16917
16918 printf (" --- infoList = %p \n",infoList);
16919 printf (" --- infoToRemoveList = %p \n",infoToRemoveList);
16920
16921 AttachedPreprocessingInfoType* dst_infoList = stmt_dst->getAttachedPreprocessingInfo();
16922 printf (" --- dst_infoList = %p \n",dst_infoList);
16923#endif
16924#if 0
16925 printf ("****************************************************************** \n");
16926 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_src \n");
16928 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_dst \n");
16930 printf ("****************************************************************** \n");
16931#endif
16932
16933 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
16934 // This is a bug in the support for building a new prototype from a defining function declaration
16935 // and caused this problem. This assertion will prevent this sort of error from happening again.
16936 ROSE_ASSERT(infoList == NULL || stmt_src->getAttachedPreprocessingInfo() != stmt_dst->getAttachedPreprocessingInfo());
16937
16938
16939#if 0
16940 printf (" --- infoList->size() = %zu \n",infoList->size());
16941 printf (" --- infoToRemoveList->size() = %zu \n",infoToRemoveList->size());
16942#endif
16943
16944#if 0
16945 int counter = 0;
16946
16947 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
16948 {
16949 // DQ (11/19/2020): Added assertion.
16950 ROSE_ASSERT(*i != NULL);
16951
16952 // DQ (11/19/2020): Why do we have a dynamic cast here.
16953 // PreprocessingInfo * info = dynamic_cast<PreprocessingInfo*> (*i);
16954 PreprocessingInfo * info = *i;
16955 ROSE_ASSERT(info != NULL);
16956
16957 // printf ("counter = %d \n",counter);
16958 printf ("counter = %d Processing PreprocessingInfo = %s \n",counter,info->getString().c_str());
16959 counter++;
16960 }
16961
16962 counter = 0;
16963#endif
16964
16965 PreprocessingInfo* prevItem = NULL;
16966
16967 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
16968 {
16969 ROSE_ASSERT(*i != NULL);
16970
16971 PreprocessingInfo * info = *i;
16972 ROSE_ASSERT(info != NULL);
16973
16974 if ( // match enum values in http://rosecompiler.org/ROSE_HTML_Reference/classPreprocessingInfo.html
16975 (info->getTypeOfDirective()==PreprocessingInfo::C_StyleComment)||
16976 (info->getTypeOfDirective()==PreprocessingInfo::CplusplusStyleComment)||
16977 (info->getTypeOfDirective()==PreprocessingInfo::FortranStyleComment)||
16978 (info->getTypeOfDirective()==PreprocessingInfo::F90StyleComment)||
16979 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeDeclaration )||
16980 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeNextDeclaration )||
16981 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDefineDeclaration )||
16982 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorUndefDeclaration)||
16983 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfdefDeclaration )||
16984 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfndefDeclaration )||
16985 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfDeclaration )||
16986 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDeadIfDeclaration )||
16987 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElseDeclaration )||
16988 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElifDeclaration )||
16989 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEndifDeclaration ) ||
16990 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEnd_ifDeclaration ) ||
16991 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorLineDeclaration) ||
16992 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorErrorDeclaration) ||
16993 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorWarningDeclaration) ||
16994 // DQ (12/28/2020): Added support for C linkage specifications.
16995 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationStart) ||
16996 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationEnd)
16997 )
16998 {
16999 // move all source preprocessing info if the desired source type is not specified or matching
17000 // a specified desired source type
17001 if ( src_position == PreprocessingInfo::undef || info->getRelativePosition() == src_position)
17002 {
17003 if (usePrepend == true)
17004 {
17005 // Liao (1/27/2015): modification to fix order of CPP directives when a list of them are moved.
17006 if (prevItem == NULL)
17007 {
17008 // addToAttachedPreprocessingInfo() is poorly designed, the last parameter is used
17009 // to indicate appending or prepending by reusing the type of relative position.
17010 // this is very confusing for users
17011 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::before);
17012 }
17013 else // there is a previous item, insert after it
17014 {
17015 stmt_dst->insertToAttachedPreprocessingInfo(info, prevItem);
17016 }
17017 prevItem = info;
17018 }
17019 else
17020 {
17021 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::after);
17022 }
17023 // 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.
17024 info->setAsTransformation();
17025
17026 // DQ (10/13/2015): This is a problem for the token-based unparsing since we don't want to have this
17027 // set_containsTransformationToSurroundingWhitespace() function cause the isModified flag to be set.
17028 // So we have to detect it being set and reset it as needed. An alternative would be to have a
17029 // non-ROSETTA generate function that didn't have the isModified flag set for the seter access function.
17030 // Note that the inputmoveDeclarationToInnermostScope_test2015_123.C file demonstrates this problem.
17031 bool isMarkedAsModified = stmt_dst->get_isModified();
17032 stmt_dst->set_containsTransformationToSurroundingWhitespace(true);
17033 if (isMarkedAsModified == false)
17034 {
17035 if (stmt_dst->get_isModified() == true)
17036 {
17037 stmt_dst->set_isModified(false);
17038 }
17039 }
17040 (*infoToRemoveList).push_back(*i);
17041 }
17042
17043 // adjust dst position if needed
17044 if (dst_position != PreprocessingInfo::undef)
17045 {
17046 info->setRelativePosition(dst_position);
17047 }
17048 } // end if
17049 } // end for
17050
17051 // Remove the element from the list of comments at the current astNode
17052 AttachedPreprocessingInfoType::iterator j;
17053 for (j = (*infoToRemoveList).begin(); j != (*infoToRemoveList).end(); j++)
17054 {
17055 infoList->erase( find(infoList->begin(),infoList->end(),*j) );
17056 }
17057 }
17058
17059
17060//----------------------------
17061// Sometimes, the preprocessing info attached to a declaration has to be
17062// moved 'up' if another declaration is inserted before it.
17063// This is a workaround for the broken LowLevelRewrite::insert() and the private
17064// LowLevelRewrite::reassociatePreprocessorDeclarations()
17065//
17066// input:
17067// *stmt_dst: the new inserted declaration
17068// *stmt_src: the existing declaration with preprocessing information
17069// tasks:
17070// judge if stmt_src has propressingInfo with headers, ifdef, etc..
17071// add them into stmt_dst
17072// delete them from stmt_dst
17073// More general usage: move preprocessingInfo of stmt_src to stmt_dst, should used before any
17074// LoweLevel::remove(stmt_src)
17076 PreprocessingInfo::RelativePositionType src_position/*=PreprocessingInfo::undef*/,
17077 PreprocessingInfo::RelativePositionType dst_position/*=PreprocessingInfo::undef*/,
17078 bool usePrepend /*= false */)
17079 {
17080 movePreprocessingInfo (stmt_src, stmt_dst, src_position, dst_position, usePrepend);
17081 } // moveUpPreprocessingInfo()
17082
17083
17088static bool isNotRelPos (const PreprocessingInfo* info,
17090{
17091 return info && (info->getRelativePosition () != pos);
17092}
17093
17098static bool isRelPos (const PreprocessingInfo* info,
17100{
17101 return info && !isNotRelPos (info, pos);
17102}
17103
17104
17106void SageInterface::cutPreprocessingInfo (SgLocatedNode* src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17107{
17108 ASSERT_not_null(src_node);
17109
17110 // [Rasmussen,Sottile 2023.01.10]: Replaced deleted bind2nd (as of 2017)
17111 AttachedPreprocessingInfoType* info = src_node->get_attachedPreprocessingInfoPtr();
17112 if (info)
17113 {
17114 // copy elements to save_buf where isRelPos() is false
17115 remove_copy_if(info->begin(),
17116 info->end(),
17117 back_inserter(save_buf),
17118 [pos](auto x) { return !isRelPos(x, pos); }
17119 );
17120
17121 // delete copied elements from save_buf
17122 AttachedPreprocessingInfoType::iterator
17123 new_end = remove_if(info->begin(),
17124 info->end(),
17125 [pos](auto x) { return isRelPos(x, pos); }
17126 );
17127 info->erase(new_end, info->end());
17128 }
17129}
17130
17131static AttachedPreprocessingInfoType *
17132createInfoList (SgLocatedNode* s)
17133{
17134 ROSE_ASSERT (s);
17135 AttachedPreprocessingInfoType* info_list = s->get_attachedPreprocessingInfoPtr ();
17136 if (!info_list)
17137 {
17138 info_list = new AttachedPreprocessingInfoType;
17139 ROSE_ASSERT (info_list);
17140 s->set_attachedPreprocessingInfoPtr (info_list);
17141 }
17142
17143 // Guarantee a non-NULL pointer.
17144 ROSE_ASSERT (info_list);
17145 return info_list;
17146}
17147
17149void SageInterface::pastePreprocessingInfo (SgLocatedNode* dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17150{
17151 if (save_buf.size()==0) return;
17152 // if front
17153 AttachedPreprocessingInfoType* info = createInfoList (dst_node);
17154 ROSE_ASSERT (info);
17155
17156 // DQ (9/26/2007): Commented out as part of move from std::list to std::vector
17157 // printf ("Commented out front_inserter() as part of move from std::list to std::vector \n");
17158 // copy (save_buf.rbegin (), save_buf.rend (), front_inserter (*info));
17159
17160 // Liao (10/3/2007), vectors can only be appended at the rear
17161 if (pos==PreprocessingInfo::before)
17162 {
17163 for(AttachedPreprocessingInfoType::reverse_iterator i=save_buf.rbegin();i!=save_buf.rend();i++)
17164 info->insert(info->begin(),*i);
17165 }
17166 // if back
17167 else if (pos==PreprocessingInfo::after)
17168 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17169 else if (pos==PreprocessingInfo::inside)
17170 {
17171 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17172 cerr<<"SageInterface::pastePreprocessingInfo() pos==PreprocessingInfo::inside is not supported."<<endl;
17173 save_buf[0]->display("ttt");
17174 }
17175}
17176
17178{
17179 ROSE_ASSERT(locatedNode != NULL);
17180 AttachedPreprocessingInfoType *comments =
17181 locatedNode->getAttachedPreprocessingInfo ();
17182
17183 if (comments != NULL)
17184 {
17185 printf ("-----------------------------------------------\n");
17186 printf ("Found an IR node (at %p of type: %s) in file %s \n",
17187 locatedNode, locatedNode->class_name ().c_str (),
17188 (locatedNode->get_file_info ()->get_filenameString ()).c_str ());
17189 int counter = 0;
17190 AttachedPreprocessingInfoType::iterator i;
17191 for (i = comments->begin (); i != comments->end (); i++)
17192 {
17193 printf
17194 ("with attached preprocessingInfo numbering #%d :------------- \nclassification= %s:\nString format:%s\n",
17195 counter++,
17196 PreprocessingInfo::directiveTypeName ((*i)->getTypeOfDirective ()).
17197 c_str (), (*i)->getString ().c_str ());
17198 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
17199 printf ("relative position is: inside\n");
17200 else
17201 printf ("relative position is: %s\n", \
17202 ((*i)->getRelativePosition () == PreprocessingInfo::before) ? "before" : "after");
17203 }
17204 }
17205 else
17206 {
17207 printf ("No attached preprocessing info. (at %p of type: %s): \n", locatedNode,
17208 locatedNode->sage_class_name ());
17209 }
17210}
17211
17223template <class ParentNode>
17224static
17225SgBasicBlock* ensureBasicBlock_aux( ParentNode& stmt,
17226 SgStatement* (ParentNode::*getter) () const,
17227 void (ParentNode::*setter) (SgStatement*)
17228 )
17229{
17230 SgStatement* const body_stmt = (stmt.*getter)();
17231 SgBasicBlock* basicblock = isSgBasicBlock(body_stmt);
17232
17233 if (basicblock == NULL) {
17234 basicblock = SageBuilder::buildBasicBlock(body_stmt);
17235 (stmt.*setter)(basicblock);
17236 basicblock->set_parent(&stmt);
17237 }
17238
17239 ROSE_ASSERT (basicblock != NULL);
17240 return basicblock;
17241}
17242
17244{
17245 SgStatement* b = fs->get_loop_body();
17246 if (!isSgBasicBlock(b)) {
17248 fs->set_loop_body(b);
17249 b->set_parent(fs);
17250
17251 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17253 }
17254 ROSE_ASSERT (isSgBasicBlock(b));
17255 return isSgBasicBlock(b);
17256}
17257
17259{
17260 SgStatement* b = cs->get_body();
17261 if (!isSgBasicBlock(b)) {
17263 cs->set_body(b);
17264 b->set_parent(cs);
17265
17266 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17268 }
17269 ROSE_ASSERT (isSgBasicBlock(b));
17270 return isSgBasicBlock(b);
17271}
17272
17274{
17275 SgStatement* b = cs->get_body();
17276 if (!isSgBasicBlock(b)) {
17278 cs->set_body(b);
17279 b->set_parent(cs);
17280
17281 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17283 }
17284 ROSE_ASSERT (isSgBasicBlock(b));
17285 return isSgBasicBlock(b);
17286}
17287
17289{
17290 ROSE_ASSERT (fs != NULL);
17291
17292 return ensureBasicBlock_aux(*fs, &SgUpcForAllStatement::get_loop_body, &SgUpcForAllStatement::set_loop_body);
17293}
17294
17296 SgStatement* b = fs->get_body();
17297 if (!isSgBasicBlock(b)) {
17299 fs->set_body(b);
17300 b->set_parent(fs);
17301
17302 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17304 }
17305 ROSE_ASSERT (isSgBasicBlock(b));
17306 return isSgBasicBlock(b);
17307 }
17308
17310 SgStatement* b = fs->get_body();
17311 if (!isSgBasicBlock(b)) {
17313 fs->set_body(b);
17314 b->set_parent(fs);
17315
17316 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17318 }
17319 ROSE_ASSERT (isSgBasicBlock(b));
17320 return isSgBasicBlock(b);
17321 }
17322
17324 SgStatement* b = fs->get_body();
17325 if (!isSgBasicBlock(b)) {
17327 fs->set_body(b);
17328 b->set_parent(fs);
17329
17330 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17332 }
17333 ROSE_ASSERT (isSgBasicBlock(b));
17334 return isSgBasicBlock(b);
17335 }
17336
17338 SgStatement* b = fs->get_true_body();
17339 if (!isSgBasicBlock(b)) {
17341 fs->set_true_body(b);
17342 b->set_parent(fs);
17343
17344 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17346#if 0
17347 printf ("In SageInterface::ensureBasicBlockAsTrueBodyOfIf(): Added SgBasicBlock b = %p to addedBasicBlockNodes.size() = %zu \n",b,addedBasicBlockNodes.size());
17348#endif
17349 }
17350 ROSE_ASSERT (isSgBasicBlock(b));
17351 return isSgBasicBlock(b);
17352 }
17353
17354// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17356 {
17357 // Record where normalization have been done so that we can preform denormalizations as required
17358 // for the token-based unparsing to generate minimal diffs.
17359
17360 SgBasicBlock* bb = isSgBasicBlock(s);
17361 ROSE_ASSERT(bb != NULL);
17362 addedBasicBlockNodes.push_back(bb);
17363#if 0
17364 printf ("In SageInterface::recordNormalizations(): Added SgBasicBlock = %p to addedBasicBlockNodes.size() = %zu \n",bb,addedBasicBlockNodes.size());
17365#endif
17366 }
17367
17368// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17370 {
17371 // Remove unused basic block IR nodes added as part of normalization.
17372 // This function should be called before the unparse step.
17373
17374#if 0
17375 printf ("In SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17376#endif
17377
17378 for (vector<SgBasicBlock*>::iterator i = addedBasicBlockNodes.begin(); i != addedBasicBlockNodes.end(); i++)
17379 {
17380 SgBasicBlock* b = *i;
17381 ROSE_ASSERT(b != NULL);
17382 if (b->get_statements().size() == 1)
17383 {
17384#if 0
17385 printf ("This SgBasicBlock can be denormalized: b = %p \n",b);
17386#endif
17387 SgStatement* parentOfBlock = isSgStatement(b->get_parent());
17388 ROSE_ASSERT(parentOfBlock != NULL);
17389
17390 bool wasPreviouslyModified = parentOfBlock->get_isModified();
17391
17392 SgStatement* s = b->get_statements()[0];
17393 ROSE_ASSERT(s != NULL);
17394
17395 switch (parentOfBlock->variantT())
17396 {
17397 case V_SgIfStmt:
17398 {
17399 SgIfStmt* ifStatement = isSgIfStmt(parentOfBlock);
17400 if (b == ifStatement->get_true_body())
17401 {
17402#if 0
17403 printf ("Calling set_true_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17404#endif
17405 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17406 ifStatement->set_true_body(s);
17407#if 0
17408 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17409#endif
17410 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17411 s->set_parent(ifStatement);
17412#if 0
17413 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17414#endif
17415 *i = NULL;
17416 // delete b;
17417 }
17418 else
17419 {
17420 ROSE_ASSERT(b == ifStatement->get_false_body());
17421#if 0
17422 printf ("Calling set_false_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17423#endif
17424 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17425 ifStatement->set_false_body(s);
17426#if 0
17427 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17428#endif
17429 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17430 s->set_parent(ifStatement);
17431#if 0
17432 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17433#endif
17434 *i = nullptr;
17435#if 0
17436 printf ("Mark as NOT modified after calling set_false_body on ifStatement = %p = %n \n",ifStatement,ifStatement->class_name().c_str());
17437#endif
17438#if 0
17439 printf ("Error: case not handled in case V_SgIfStmt: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17440 ROSE_ABORT();
17441#endif
17442 }
17443 break;
17444 }
17445
17446 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17447 case V_SgWhileStmt:
17448 {
17449 SgWhileStmt* whileStatement = isSgWhileStmt(parentOfBlock);
17450 if (b == whileStatement->get_body())
17451 {
17452 whileStatement->set_body(s);
17453 s->set_parent(whileStatement);
17454 }
17455 break;
17456 }
17457
17458 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17459 case V_SgSwitchStatement:
17460 {
17461 SgSwitchStatement* switchStatement = isSgSwitchStatement(parentOfBlock);
17462 if (b == switchStatement->get_body())
17463 {
17464 switchStatement->set_body(s);
17465 s->set_parent(switchStatement);
17466 }
17467 break;
17468 }
17469
17470 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17471 case V_SgForStatement:
17472 {
17473 SgForStatement* forStatement = isSgForStatement(parentOfBlock);
17474 if (b == forStatement->get_loop_body())
17475 {
17476 forStatement->set_loop_body(s);
17477 s->set_parent(forStatement);
17478 }
17479 break;
17480 }
17481
17482 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17483 case V_SgCaseOptionStmt:
17484 {
17485 SgCaseOptionStmt* caseOptionStatement = isSgCaseOptionStmt(parentOfBlock);
17486 if (b == caseOptionStatement->get_body())
17487 {
17488 caseOptionStatement->set_body(s);
17489 s->set_parent(caseOptionStatement);
17490 }
17491 break;
17492 }
17493
17494 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17495 case V_SgDefaultOptionStmt:
17496 {
17497 SgDefaultOptionStmt* defaultOptionStatement = isSgDefaultOptionStmt(parentOfBlock);
17498 if (b == defaultOptionStatement->get_body())
17499 {
17500 defaultOptionStatement->set_body(s);
17501 s->set_parent(defaultOptionStatement);
17502 }
17503 break;
17504 }
17505
17506 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17507 case V_SgDoWhileStmt:
17508 {
17509 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(parentOfBlock);
17510 if (b == doWhileStatement->get_body())
17511 {
17512 doWhileStatement->set_body(s);
17513 s->set_parent(doWhileStatement);
17514 }
17515 break;
17516 }
17517
17518 default:
17519 {
17520 printf ("Error: case not handled in switch: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17521 ROSE_ABORT();
17522 }
17523 }
17524
17525 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17526 if (wasPreviouslyModified == false)
17527 {
17528 if (parentOfBlock->get_isModified() == true)
17529 {
17530#if 0
17531 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());
17532#endif
17533 parentOfBlock->set_isModified(false);
17534 }
17535
17536 }
17537#if 0
17538 printf ("Exiting as a test! \n");
17539 ROSE_ABORT();
17540#endif
17541 }
17542 }
17543
17544#if 0
17545 printf ("Leaving SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17546#endif
17547 }
17548
17549
17551 SgStatement* b = fs->get_false_body();
17552 // if no false body at all AND no-create-empty-body
17553 if (!createEmptyBody && (b == NULL || isSgNullStatement(b)))
17554 return NULL;
17555 if (!isSgBasicBlock(b)) {
17556 b = SageBuilder::buildBasicBlock(b); // This works if b is NULL as well (producing an empty block)
17557 fs->set_false_body(b);
17558 b->set_parent(fs);
17559
17560 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17562 }
17563 ROSE_ASSERT (isSgBasicBlock(b));
17564 return isSgBasicBlock(b);
17565 }
17566
17568 SgStatement* b = fs->get_body();
17569 if (!isSgBasicBlock(b)) {
17571 fs->set_body(b);
17572 b->set_parent(fs);
17573 }
17574 ROSE_ASSERT (isSgBasicBlock(b));
17575 return isSgBasicBlock(b);
17576 }
17577
17579{
17580 SgStatement* b = fs->get_body();
17581 if (!isSgBasicBlock(b)) {
17583 fs->set_body(b);
17584 b->set_parent(fs);
17585 }
17586 ROSE_ASSERT (isSgBasicBlock(b));
17587 return isSgBasicBlock(b);
17588}
17589
17591{
17592 bool rt = false;
17593 ROSE_ASSERT(s);
17594 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17595 ROSE_ASSERT(p);
17596
17597 switch (p->variantT())
17598 {
17599 case V_SgForStatement:
17600 {
17601 if (isSgForStatement(p)->get_loop_body() == s)
17602 rt = true;
17603 break;
17604 }
17605 case V_SgUpcForAllStatement: // PP
17606 {
17607 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17608 if (upcforall.get_loop_body() == s)
17609 rt = true;
17610 break;
17611 }
17612 case V_SgWhileStmt:
17613 {
17614 if (isSgWhileStmt(p)->get_body() == s)
17615 rt = true;
17616 break;
17617 }
17618 case V_SgDoWhileStmt:
17619 {
17620 if (isSgDoWhileStmt(p)->get_body() == s)
17621 rt = true;
17622 break;
17623 }
17624 case V_SgSwitchStatement:
17625 {
17626 if (isSgSwitchStatement(p)->get_body() == s)
17627 rt = true;
17628 break;
17629 }
17630 case V_SgCaseOptionStmt:
17631 {
17632 if (isSgCaseOptionStmt(p)->get_body() == s)
17633 rt = true;
17634 break;
17635 }
17636 case V_SgDefaultOptionStmt:
17637 {
17638 if (isSgDefaultOptionStmt(p)->get_body() == s)
17639 rt = true;
17640 break;
17641 }
17642 case V_SgCatchOptionStmt:
17643 {
17644 if (isSgCatchOptionStmt(p)->get_body() == s)
17645 rt = true;
17646 break;
17647 }
17648 case V_SgIfStmt:
17649 {
17650 if (isSgIfStmt(p)->get_true_body() == s)
17651 rt = true;
17652 else if (isSgIfStmt(p)->get_false_body() == s)
17653 rt = true;
17654 break;
17655 }
17656 default:
17657 {
17658 if (isSgOmpBodyStatement(p))
17659 rt = true;
17660 break;
17661 }
17662 }
17663 return rt;
17664}
17665
17667//etc.
17669{
17670 ROSE_ASSERT (singleStmt != NULL); // not NULL
17671 ROSE_ASSERT (isSgBasicBlock(singleStmt) == NULL); //not a block
17672 ROSE_ASSERT (isBodyStatement(singleStmt) == true); // is a body statement
17673
17674 SgBasicBlock* rt = NULL;
17675
17676
17677
17678 SgStatement* s = singleStmt;
17679 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17680 ROSE_ASSERT(p);
17681 switch (p->variantT())
17682 {
17683 case V_SgForStatement:
17684 {
17685 if (isSgForStatement(p)->get_loop_body() == s)
17686 rt = ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17687 break;
17688 }
17689 case V_SgUpcForAllStatement: // PP
17690 {
17691 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17692
17693 if (upcforall.get_loop_body() == s)
17694 rt = ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17695 break;
17696 }
17697 case V_SgWhileStmt:
17698 {
17699 if (isSgWhileStmt(p)->get_body() == s)
17700 rt = ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17701 break;
17702 }
17703 case V_SgDoWhileStmt:
17704 {
17705 if (isSgDoWhileStmt(p)->get_body() == s)
17706 rt = ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17707 break;
17708 }
17709 case V_SgSwitchStatement:
17710 {
17711 if (isSgSwitchStatement(p)->get_body() == s)
17712 rt = ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17713 break;
17714 }
17715 case V_SgCaseOptionStmt:
17716 {
17717 if (isSgCaseOptionStmt(p)->get_body() == s)
17718 rt = ensureBasicBlockAsBodyOfCaseOption(isSgCaseOptionStmt(p));
17719 break;
17720 }
17721 case V_SgDefaultOptionStmt:
17722 {
17723 if (isSgDefaultOptionStmt(p)->get_body() == s)
17724 rt = ensureBasicBlockAsBodyOfDefaultOption(isSgDefaultOptionStmt(p));
17725 break;
17726 }
17727 case V_SgCatchOptionStmt:
17728 {
17729 if (isSgCatchOptionStmt(p)->get_body() == s)
17730 rt = ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17731 break;
17732 }
17733 case V_SgIfStmt:
17734 {
17735 if (isSgIfStmt(p)->get_true_body() == s)
17736 rt = ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17737 else if (isSgIfStmt(p)->get_false_body() == s)
17738 rt = ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17739 break;
17740 }
17741 default:
17742 {
17743 if (isSgOmpBodyStatement(p))
17744 {
17745 rt = ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17746 }
17747 break;
17748 }
17749 }
17750 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.
17751 return rt;
17752}
17753
17754#if 0
17755SgLocatedNode* SageInterface::ensureBasicBlockAsParent(SgStatement* s)
17756{
17757 ROSE_ASSERT(s);
17758
17759 //Vulov: The parent of a statement is not necessarily a statement. It could be SgStatementExpression
17760 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17761 ROSE_ASSERT(p);
17762 switch (p->variantT())
17763 {
17764 case V_SgBasicBlock: return isSgBasicBlock(p);
17765 case V_SgForStatement:
17766 {
17767 if (isSgForStatement(p)->get_loop_body() == s)
17768 return ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17769 else if (isSgForStatement(p)->get_test() == s)
17770 {
17771 }
17772 else if (isSgForStatement(p)->get_for_init_stmt() == s)
17773 {
17774 }
17775 else ROSE_ABORT();
17776 break;
17777 }
17778 case V_SgUpcForAllStatement: // PP
17779 {
17780 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17781
17782 if (upcforall.get_loop_body() == s)
17783 return ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17784
17785 ROSE_ASSERT( (s == upcforall.get_for_init_stmt())
17786 || (s == upcforall.get_test())
17787 );
17788 break;
17789 }
17790 case V_SgWhileStmt:
17791 {
17792 if (isSgWhileStmt(p)->get_body() == s)
17793 return ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17794 else if (isSgWhileStmt(p)->get_condition() == s)
17795 {
17796 }
17797 else ROSE_ABORT();
17798 break;
17799 }
17800 case V_SgDoWhileStmt:
17801 {
17802 if (isSgDoWhileStmt(p)->get_body() == s)
17803 return ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17804 else if (isSgDoWhileStmt(p)->get_condition() == s)
17805 {
17806 }
17807 else ROSE_ABORT();
17808 break;
17809 }
17810 case V_SgSwitchStatement:
17811 {
17812 if (isSgSwitchStatement(p)->get_body() == s)
17813 return ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17814 else if (isSgSwitchStatement(p)->get_item_selector() == s)
17815 {
17816 }
17817 else ROSE_ABORT();
17818 break;
17819 }
17820 case V_SgCatchOptionStmt:
17821 {
17822 if (isSgCatchOptionStmt(p)->get_body() == s)
17823 return ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17824 else if (isSgCatchOptionStmt(p)->get_condition() == s)
17825 {
17826 }
17827 else ROSE_ABORT();
17828 break;
17829 }
17830 case V_SgIfStmt:
17831 {
17832 if (isSgIfStmt(p)->get_true_body() == s)
17833 return ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17834 else if (isSgIfStmt(p)->get_false_body() == s)
17835 return ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17836 else if (isSgIfStmt(p)->get_conditional() == s)
17837 {
17838 }
17839 else ROSE_ABORT();
17840 break;
17841 }
17842 default:
17843 {
17844 if (isSgOmpBodyStatement(p))
17845 {
17846 return ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17847 }
17848 else
17849 // Liao, 7/3/2008 We allow other conditions to fall through,
17850 // they are legal parents with list of statements as children.
17851 //cerr << "Unhandled parent block:"<< p->class_name() << endl;
17852 // ROSE_ASSERT (!"Bad parent in ensureBasicBlockAsParent");
17853 break;
17854 }
17855 }
17856 return p;
17857}
17858
17859 void SageInterface::changeAllLoopBodiesToBlocks(SgNode* top) {
17860 cerr<<"Warning: SageInterface::changeAllLoopBodiesToBlocks() is being replaced by SageInterface::changeAllBodiesToBlocks()."<<endl;
17861 cerr<<"Please use SageInterface::changeAllBodiesToBlocks() if you can."<<endl;
17863 }
17864
17865#endif
17866 void SageInterface::changeAllBodiesToBlocks(SgNode* top, bool createEmptyBody /*= true*/ ) {
17867 class Visitor: public AstSimpleProcessing {
17868 public:
17869 bool allowEmptyBody;
17870 Visitor (bool flag):allowEmptyBody(flag) {}
17871 virtual void visit(SgNode* n) {
17872
17873 bool wasPreviouslyModified = n->get_isModified();
17874
17875 switch (n->variantT()) {
17876 case V_SgForStatement: {
17877 ensureBasicBlockAsBodyOfFor(isSgForStatement(n));
17878 break;
17879 }
17880 case V_SgWhileStmt: {
17881 ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(n));
17882 break;
17883 }
17884 case V_SgDoWhileStmt: {
17885 ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(n));
17886 break;
17887 }
17888 case V_SgSwitchStatement: {
17889 ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(n));
17890 break;
17891 }
17892 case V_SgIfStmt: {
17893 ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(n));
17894 ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(n), allowEmptyBody);
17895#if 0
17896 // DQ (10/6/2015): Debugging why changes are being made to the AST for token-based unparsing.
17897 printf ("In changeAllBodiesToBlocks(): case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
17898#endif
17899#if 0
17900 // Reset this to false as a test.
17901 if (n->get_isModified() == true)
17902 {
17903 n->set_isModified(false);
17904 printf ("In changeAllBodiesToBlocks(): AFTER RESET: case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
17905 }
17906#endif
17907 break;
17908 }
17909 case V_SgCatchOptionStmt: {
17910 ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(n));
17911 break;
17912 }
17913 case V_SgUpcForAllStatement: {
17914 ensureBasicBlockAsBodyOfUpcForAll(isSgUpcForAllStatement(n));
17915 break;
17916 }
17917
17918 default:
17919 {
17920 if (isSgOmpBodyStatement(n))
17921 ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(n));
17922 break;
17923 }
17924 }
17925
17926 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17927 if (wasPreviouslyModified == false)
17928 {
17929 if (n->get_isModified() == true)
17930 {
17931#if 0
17932 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());
17933#endif
17934 n->set_isModified(false);
17935 }
17936
17937 }
17938
17939 }
17940 };
17941 Visitor(createEmptyBody).traverse(top, postorder);
17942 }
17943
17944
17945// Replace a given expression with a list of statements produced by a
17946// generator. The generator, when given a variable as input, must produce
17947// some code which leaves its result in the given variable. The output
17948// from the generator is then inserted into the original program in such a
17949// way that whenever the expression had previously been evaluated, the
17950// statements produced by the generator are run instead and their result is
17951// used in place of the expression.
17952// Assumptions: not currently traversing from or the statement it is in
17953void
17955 {
17956 // DQ (3/11/2006): The problem here is that the test expression for a "for loop" (SgForStmt)
17957 // is assumed to be a SgExpression. This was changed in Sage III as part of a bugfix and so
17958 // the original assumptions upon which this function was based are not incorrect, hence the bug!
17959 // Note that a number of cases were changed when this fix was made to SageIII (see documentation
17960 // for SgScopeStatement).
17961
17962#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
17963 SgStatement* enclosingStatement = getStatementOfExpression(from);
17964 SgExprStatement* exprStatement = isSgExprStatement(enclosingStatement);
17965
17966 SgForStatement* forStatement = isSgForStatement(enclosingStatement);
17967 SgReturnStmt* returnStatement = isSgReturnStmt(enclosingStatement);
17968 SgVariableDeclaration* varDeclarationStatement = isSgVariableDeclaration(enclosingStatement);
17969
17970
17971 // DQ (3/11/2006): Bugfix for special cases of conditional that are either SgStatement or SgExpression IR nodes.
17972
17973 ROSE_ASSERT (exprStatement || forStatement || returnStatement || varDeclarationStatement);
17974
17975 if (varDeclarationStatement)
17976 {
17978 }
17979 else
17980 {
17981 SgExpression* root = getRootOfExpression(from);
17982 ROSE_ASSERT (root);
17983 // printf ("root = %p \n",root);
17984 {
17985 if (forStatement && forStatement->get_increment() == root)
17986 {
17987 // printf ("Convert step of for statement \n");
17988 // Convert step of for statement
17989 // for (init; test; e) body; (where e contains from) becomes
17990 // for (init; test; ) {
17991 // body (with "continue" changed to "goto label");
17992 // label: e;
17993 // }
17994 // std::cout << "Converting for step" << std::endl;
17995 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(forStatement->get_increment());
17996 forStatement->get_increment()->set_parent(incrStmt);
17997
17998 SageInterface::addStepToLoopBody(forStatement, incrStmt);
18000 forStatement->set_increment(ne);
18001 ne->set_parent(forStatement);
18003 }
18004 else
18005 {
18006 SgStatement* enclosingStmtParent = isSgStatement(enclosingStatement->get_parent());
18007 assert (enclosingStmtParent);
18008 SgWhileStmt* whileStatement = isSgWhileStmt(enclosingStmtParent);
18009 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(enclosingStmtParent);
18010 SgIfStmt* ifStatement = isSgIfStmt(enclosingStmtParent);
18011 SgSwitchStatement* switchStatement = isSgSwitchStatement(enclosingStmtParent);
18012 SgForStatement* enclosingForStatement = isSgForStatement(enclosingStmtParent);
18013 if (enclosingForStatement && enclosingForStatement->get_test() == exprStatement)
18014 {
18015 // Convert test of for statement:
18016 // for (init; e; step) body; (where e contains from) becomes
18017 // for (init; true; step) {
18018 // bool temp;
18019 // temp = e;
18020 // if (!temp) break;
18021 // body;
18022 // }
18023 // in which "temp = e;" is rewritten further
18024 // std::cout << "Converting for test" << std::endl;
18025 pushTestIntoBody(enclosingForStatement);
18027 }
18028 else if (whileStatement && whileStatement->get_condition() == exprStatement)
18029 {
18030 // printf ("Convert while statements \n");
18031 // Convert while statement:
18032 // while (e) body; (where e contains from) becomes
18033 // while (true) {
18034 // bool temp;
18035 // temp = e;
18036 // if (!temp) break;
18037 // body;
18038 // }
18039 // in which "temp = e;" is rewritten further
18040 // std::cout << "Converting while test" << std::endl;
18041 pushTestIntoBody(whileStatement);
18042 // FixSgTree(whileStatement);
18044 }
18045 else if (doWhileStatement && doWhileStatement->get_condition() == exprStatement)
18046 {
18047 // printf ("Convert do-while statements \n");
18048 // Convert do-while statement:
18049 // do body; while (e); (where e contains from) becomes
18050 // {bool temp = true;
18051 // do {
18052 // body (with "continue" changed to "goto label";
18053 // label:
18054 // temp = e;} while (temp);}
18055 // in which "temp = e;" is rewritten further
18056 // std::cout << "Converting do-while test" << std::endl;
18057 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18058 // printf ("Building IR node #14: new SgBasicBlock = %p \n",new_statement);
18059 assert (doWhileStatement->get_parent());
18060 new_statement->set_parent(doWhileStatement->get_parent());
18061 myStatementInsert(doWhileStatement, new_statement, false);
18062 SageInterface::myRemoveStatement(doWhileStatement);
18063 SgName varname = "rose__temp1"; // Does not need to be unique, but must not be used in user code anywhere
18064 SgAssignInitializer* assignInitializer = buildAssignInitializer(
18065 buildBoolValExp(true));
18066 //SageInterface::getBoolType(doWhileStatement));
18068 varname, buildBoolType(), assignInitializer, new_statement);
18069
18070 SgInitializedName* initname = new_decl->get_variables().back();
18071 initname->set_scope(new_statement);
18072
18073 // DQ (12/14/2006): set the parent of the SgAssignInitializer to the variable (SgInitializedName).
18074 assignInitializer->set_parent(initname);
18075
18076#if 1
18077 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18079#else
18080 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18081 new_statement->insert_symbol(varname, varsym);
18082 varsym->set_parent(new_statement->get_symbol_table());
18083#endif
18084
18085 SageInterface::appendStatement(new_decl, new_statement);
18086 SageInterface::appendStatement(doWhileStatement, new_statement);
18087 assert (varsym);
18088 SgCastExp* castExp1 = buildCastExp(root,buildBoolType());
18089 SgVarRefExp* vr = buildVarRefExp(varsym);
18090 vr->set_lvalue(true);
18091
18092 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp1);
18093
18094 SageInterface::addStepToLoopBody(doWhileStatement, temp_setup);
18095 SgVarRefExp* varsymVr = buildVarRefExp(varsym);
18096
18098 varsymVr->set_parent(condStmt);
18099 doWhileStatement->set_condition(condStmt);
18100 condStmt->set_parent(doWhileStatement);
18102 }
18103 else if (ifStatement && ifStatement->get_conditional() == exprStatement)
18104 {
18105 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18106 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18107 assert (ifStatement->get_parent());
18108 new_statement->set_parent(ifStatement->get_parent());
18109 myStatementInsert(ifStatement, new_statement, false);
18111 SgName varname = "rose__temp2"; // Does not need to be unique, but must not be used in user code anywhere
18112 SgBoolValExp* trueVal = buildBoolValExp(true);
18113
18115
18117 buildBoolType(), ai,new_statement);
18118 SgInitializedName* initname = new_decl->get_variables().back();
18119 ai->set_parent(initname);
18120 initname->set_scope(new_statement);
18121#if 1
18122 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18124#else
18125 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18126 new_statement->insert_symbol(varname, varsym);
18127 varsym->set_parent(new_statement->get_symbol_table());
18128#endif
18129 SageInterface::appendStatement(new_decl, new_statement);
18130 ifStatement->set_parent(new_statement);
18131 assert (varsym);
18132
18133 SgCastExp* castExp2 = SageBuilder::buildCastExp(root, SageInterface::getBoolType(ifStatement));
18134 SgVarRefExp* vr = buildVarRefExp(varsym);
18135 vr->set_lvalue(true);
18136 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp2 );
18137 SageInterface::appendStatement(temp_setup, new_statement);
18138 SageInterface::appendStatement(ifStatement, new_statement);
18141 ifStatement->set_conditional(es);
18142 es->set_parent(ifStatement);
18144 }
18145 else if (switchStatement && switchStatement->get_item_selector() == exprStatement)
18146 {
18147 SgExpression* switchCond = exprStatement->get_expression();
18148 ROSE_ASSERT (switchCond);
18149 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18150 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18151 assert (switchStatement->get_parent());
18152 new_statement->set_parent(switchStatement->get_parent());
18153 myStatementInsert(switchStatement, new_statement, false);
18154 SageInterface::myRemoveStatement(switchStatement);
18155 SgName varname = "rose__temp3"; // Does not need to be unique, but must not be used in user code anywhere
18156 switchCond->set_parent(NULL);
18157 SgVariableDeclaration* new_decl = SageBuilder::buildVariableDeclaration(varname, switchCond->get_type(), SageBuilder::buildAssignInitializer(switchCond), new_statement);
18159 SageInterface::appendStatement(new_decl, new_statement);
18160 switchStatement->set_parent(new_statement);
18161 assert (varsym);
18162
18163
18164 SageInterface::appendStatement(switchStatement, new_statement);
18167 switchStatement->set_item_selector(es);
18168 es->set_parent(switchStatement);
18170 }
18171 else
18172 {
18173 // printf ("Handles expression and return statements \n");
18174 // Handles expression and return statements
18175 // std::cout << "Converting other statement" << std::endl;
18177 }
18178 }
18179 }
18180 }
18181
18182#endif
18183
18184 // printf ("Leaving replaceExpressionWithStatement(from,to) \n");
18185 }
18186
18195
18196// Similar to replaceExpressionWithStatement, but with more restrictions.
18197// Assumptions: from is not within the test of a loop or if
18198// not currently traversing from or the statement it is in
18200 {
18201
18202#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18203 SgStatement* stmt = getStatementOfExpression(from);
18204
18205 if (isSgExprStatement(stmt))
18206 {
18207 SgExpression* top = getRootOfExpression(from);
18208
18209
18210 if (top == from)
18211 {
18212 SgStatement* generated = to->generate(0);
18213 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18214 generated->set_parent(stmt->get_parent());
18215 return;
18216 }
18217 else
18218 {
18219 if (isSgAssignOp(top) && isSgAssignOp(top)->get_rhs_operand() == from)
18220 {
18221 SgAssignOp* t = isSgAssignOp(top);
18222 SgStatement* generated = to->generate(t->get_lhs_operand());
18223 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18224 generated->set_parent(stmt->get_parent());
18225 return;
18226 }
18227 else
18228 {
18229 // printf ("In replaceSubexpressionWithStatement(): Statement not generated \n");
18230 }
18231 }
18232 }
18233
18234 // cout << "1: " << getStatementOfExpression(from)->unparseToString() << endl;
18236 // cout << "2: " << getStatementOfExpression(from)->unparseToString() << endl;
18237 convertInitializerIntoAssignment(init);
18238 // cout << "3: " << getStatementOfExpression(from)->unparseToString() << endl;
18239 // cout << "3a: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18240 SgExprStatement* new_stmt = isSgExprStatement(getStatementOfExpression(from));
18241 assert (new_stmt != NULL); // Should now have this form because of conversion
18242 replaceAssignmentStmtWithStatement(new_stmt, to);
18243
18244 // printf ("In replaceSubexpressionWithStatement: new_stmt = %p = %s \n",new_stmt,new_stmt->class_name().c_str());
18245 // cout << "4: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18246
18247#endif
18248 }
18249
18250
18251 // Liao, 6/27/2008
18252 //Tasks
18253 // find all return statements
18254 // rewrite it to temp = expression; return temp; if expression is not a single value.
18255 // insert s right before 'return xxx;'
18257 {
18258 int result = 0;
18259 ROSE_ASSERT(func&&s);
18260 // vector<SgReturnStmt* > stmts = findReturnStmts(func);
18261 Rose_STL_Container <SgNode* > stmts = NodeQuery::querySubTree(func, V_SgReturnStmt);
18262 //vector<SgReturnStmt*>::iterator i;
18263 Rose_STL_Container<SgNode*>::iterator i;
18264 for (i=stmts.begin();i!=stmts.end();i++)
18265 {
18266 SgReturnStmt* cur_stmt = isSgReturnStmt(*i);
18267 ROSE_ASSERT(cur_stmt);
18268 SgExpression * exp = cur_stmt->get_expression();
18269 // TV (05/03/2011) Catch the case "return ;" where exp is NULL
18270 bool needRewrite = (exp != NULL) && !(isSgValueExp(exp));
18271 if (needRewrite)
18272 {
18273 splitExpression(exp);
18274 }
18275 // avoid reusing the statement
18276 if (result>=1 )
18277 s = copyStatement(s);
18278 insertStatementBefore(cur_stmt,s);
18279 result ++;
18280 } // for
18281 if (stmts.size()==0 ) // a function without any return at all,
18282 {
18283 SgBasicBlock * body = func->get_definition()->get_body();
18284 if (body== NULL)
18285 {
18286 cout<<"In instrumentEndOfFunction(), found an empty function body.! "<<endl;
18287 ROSE_ABORT();
18288 }
18289 appendStatement(s,body);
18290 result ++;
18291 }
18292 return result;
18293 } // instrumentEndOfFunction
18294
18296 {
18297 ROSE_ASSERT(stmt);
18298 return ((stmt->get_declarationModifier()).get_storageModifier()).isStatic();
18299 } // isStatic()
18300
18303 {
18304 ROSE_ASSERT(stmt);
18305 return ((stmt->get_declarationModifier()).get_storageModifier()).setStatic();
18306 }
18307
18309 {
18310 ROSE_ASSERT(stmt);
18311 return ((stmt->get_declarationModifier()).get_storageModifier()).isExtern();
18312 } // isExtern()
18313
18314
18317 {
18318 ROSE_ASSERT(stmt);
18319 return ((stmt->get_declarationModifier()).get_storageModifier()).setExtern();
18320 }
18321
18322 // Check if an SgInitializedName is "mutable' (has storage modifier set)
18324 {
18325 ROSE_ASSERT(name);
18326 return name->get_storageModifier().isMutable();
18327 }
18328
18329 // True if a parameter name is a Jovial output parameter
18331 {
18332 return isMutable(name);
18333 }
18334
18335 // Get a vector of Jovial input parameters from the function parameter list
18336 // TODO: Look into making this work for Fortran
18337 std::vector<SgInitializedName*> SageInterface::getInParameters(const SgInitializedNamePtrList &params)
18338 {
18339 std::vector<SgInitializedName*> in_params;
18340 BOOST_FOREACH (SgInitializedName* name, params)
18341 {
18342 if (!isJovialOutParam(name)) in_params.push_back(name);
18343 }
18344 return in_params;
18345 }
18346
18347 // Get a list of Jovial output parameters from the function parameter list
18348 // TODO: Look into making this work for Fortran
18349 std::vector<SgInitializedName*> SageInterface::getOutParameters(const SgInitializedNamePtrList &params)
18350 {
18351 std::vector<SgInitializedName*> out_params;
18352 BOOST_FOREACH (SgInitializedName* name, params)
18353 {
18354 if (isJovialOutParam(name)) out_params.push_back(name);
18355 }
18356 return out_params;
18357 }
18358
18360 switch (expr->variantT()) {
18361 case V_SgCharVal: return (long long)(isSgCharVal(expr)->get_value());
18362 case V_SgSignedCharVal: return (long long)(isSgSignedCharVal(expr)->get_value());
18363 case V_SgUnsignedCharVal: return isSgUnsignedCharVal(expr)->get_value();
18364 case V_SgShortVal: return (long long)(isSgShortVal(expr)->get_value());
18365 case V_SgUnsignedShortVal: return isSgUnsignedShortVal(expr)->get_value();
18366 case V_SgIntVal: return (long long)(isSgIntVal(expr)->get_value());
18367 case V_SgUnsignedIntVal: return isSgUnsignedIntVal(expr)->get_value();
18368 case V_SgLongIntVal: return (long long)(isSgLongIntVal(expr)->get_value());
18369 case V_SgUnsignedLongVal: return isSgUnsignedLongVal(expr)->get_value();
18370 case V_SgLongLongIntVal: return isSgLongLongIntVal(expr)->get_value();
18371 case V_SgUnsignedLongLongIntVal: return isSgUnsignedLongLongIntVal(expr)->get_value();
18372 case V_SgBoolValExp: return (long long )(isSgBoolValExp(expr)->get_value());
18373
18374 // DQ (2/18/2015): Make this a better error message.
18375 // default: ROSE_ASSERT (!"Bad kind in getIntegerConstantValue");
18376 default:
18377 {
18378 printf ("ERROR: In SageInterface::getIntegerConstantValue(): default reached: expr = %p = %s \n",expr,expr->class_name().c_str());
18379 ROSE_ASSERT (false);
18380 }
18381
18382 }
18383
18384 ROSE_ASSERT (!"Bad kind return in getIntegerConstantValue");
18385 return 0;
18386 }
18387
18388
18389#ifdef ROSE_ENABLE_BINARY_ANALYSIS
18390// tps : 28 Oct 2008 - support for finding the main interpretation
18391// rpm : 18 Sep 2009 - rewritten to support multiple files per interpretation
18395SageInterface::getMainInterpretation(SgAsmGenericFile *file)
18396{
18397 SgBinaryComposite *binary = getEnclosingNode<SgBinaryComposite>(file);
18398 ROSE_ASSERT(binary!=NULL);
18399
18400 /* Find the only header or the PE header of this file */
18401 SgAsmGenericHeader *requisite_header = NULL; /*the returned interpretation must point to this header*/
18402 const SgAsmGenericHeaderPtrList &headers = file->get_headers()->get_headers();
18403 if (1==headers.size()) {
18404 requisite_header = headers[0];
18405 } else {
18406 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18407 if (isSgAsmPEFileHeader(*hi)) {
18408 requisite_header = isSgAsmPEFileHeader(*hi);
18409 break;
18410 }
18411 }
18412 }
18413 ROSE_ASSERT(requisite_header!=NULL);
18414
18415 /* Find an interpretation that points to this header */
18416 const SgAsmInterpretationPtrList &interps = binary->get_interpretations()->get_interpretations();
18417 for (SgAsmInterpretationPtrList::const_iterator ii=interps.begin(); ii!=interps.end(); ++ii) {
18418 const SgAsmGenericHeaderPtrList &headers = (*ii)->get_headers()->get_headers();
18419 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18420 if ((*hi)==requisite_header)
18421 return *ii;
18422 }
18423 }
18424
18425 ROSE_ASSERT(!"no appropriate interpretation");
18426 return NULL;
18427}
18428#endif
18429
18431 {
18432 public:
18433 // This is the simpliest possible version of a deep copy SgCopyHelp::copyAst() member function.
18434 // Note that the root of the does not have its file info set like its children.
18435 virtual SgNode *copyAst(const SgNode *n)
18436 {
18437 // DQ (2/26/2009): This defines a simple concept of "deep" copy. It forms a more testable building block, I hope.
18438 SgNode* copy = n->copy(*this);
18439
18440 // Also mark this as a transformation and to be output in unparsing (so it will be output by the code generator).
18441 Sg_File_Info* fileInfo = copy->get_file_info();
18442 if (fileInfo != NULL)
18443 {
18444 // Must make this for output (checked in unparser), marking as a transformation is not checked
18445 fileInfo->setOutputInCodeGeneration();
18446 fileInfo->setTransformation();
18447 }
18448
18449 return copy;
18450 }
18451 } collectDependentDeclarationsCopyType;
18452
18453
18455 {
18456 // This traversal collects the includes at the top of a file.
18457
18458 public:
18459 vector<PreprocessingInfo*> cppDirectiveList;
18460
18461 void visit(SgNode *astNode);
18462 };
18463
18464
18465void
18467 {
18468 SgLocatedNode* locatedNode = isSgLocatedNode(astNode);
18469 if (locatedNode != NULL)
18470 {
18471 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
18472
18473 if (comments != NULL)
18474 {
18475#if 0
18476 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18477#endif
18478 AttachedPreprocessingInfoType::iterator i;
18479 for (i = comments->begin(); i != comments->end(); i++)
18480 {
18481 ROSE_ASSERT ( (*i) != NULL );
18482#if 0
18483 printf (" Attached Comment (relativePosition=%s): %s\n",
18484 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18485 (*i)->getString().c_str());
18486 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
18487 (*i)->get_file_info()->display("comment/directive location");
18488#endif
18489
18490 // We only save the #include directives, but likely we should be collecting ALL directives to
18491 // avoid the collection of #include that is meant to be hidden in an #if 0 ... #endif pairing.
18492 // if ((*i)->getTypeOfDirective() == PreprocessingInfo::CpreprocessorIncludeDeclaration)
18493 {
18494 // This is an include directive.
18495 cppDirectiveList.push_back(*i);
18496#if 0
18497 printf (" Attached include directive (relativePosition=%s): %s\n",
18498 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18499 (*i)->getString().c_str());
18500#endif
18501 }
18502 }
18503 }
18504 else
18505 {
18506#if 0
18507 printf ("No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18508#endif
18509 }
18510 }
18511 }
18512
18513
18514// This is part of a mechanism to collect directives from code that is to be outlined.
18515// However if we collect include directives we likely should really be collecting ALL
18516// directives (since the #include could be inside of an #if 0 ... #endif pairing.
18517// This level of detail will be addressed later (in an iterative approach).
18518vector<PreprocessingInfo*>
18519collectCppDirectives ( SgSourceFile* file )
18520 {
18521 // This function is used to collect include directives from the whole file.
18523 t.traverse(file,preorder);
18524
18525 return t.cppDirectiveList;
18526 }
18527
18528
18529vector<PreprocessingInfo*>
18530collectCppDirectives ( SgLocatedNode* n )
18531 {
18532 // This function is used to collect include directives from specific dependent declarations.
18534 t.traverse(n,preorder);
18535
18536 return t.cppDirectiveList;
18537 }
18538
18539// Debugging support.
18540void
18541outputPreprocessingInfoList ( const vector<PreprocessingInfo*> & l )
18542 {
18543 // This function support debugging the generated directive lists.
18544
18545 vector<PreprocessingInfo*>::const_iterator i = l.begin();
18546 while ( i != l.end() )
18547 {
18548 printf (" Attached include directive (relativePosition=%s): %s\n",
18549 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18550 (*i)->getString().c_str());
18551 i++;
18552 }
18553 }
18554
18555
18556
18558getAssociatedDeclaration( SgScopeStatement* scope )
18559 {
18560 //TODO This should become a member of SgScopeStatement
18561
18562 SgDeclarationStatement* declaration = NULL;
18563 switch(scope->variantT())
18564 {
18565 case V_SgNamespaceDefinitionStatement:
18566 {
18567 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
18568 declaration = namespaceDefinition->get_namespaceDeclaration();
18569 break;
18570 }
18571
18572 case V_SgClassDefinition:
18573 case V_SgTemplateInstantiationDefn: // Liao, 5/12/2009
18574 {
18575 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
18576 declaration = classDefinition->get_declaration();
18577 break;
18578 }
18579
18580 default:
18581 {
18582 printf ("Error: default reached in getAssociatedDeclaration(): scope = %p = %s \n",scope,scope->class_name().c_str());
18583 ROSE_ABORT();
18584 }
18585 }
18586
18587 // There may be some scopes that don't have an associated declaration.
18588 ROSE_ASSERT(declaration != NULL);
18589
18590 return declaration;
18591 }
18592
18593
18595 {
18596 public:
18597 // Accumulate a list of copies of associated declarations referenced in the AST subtree
18598 // (usually of the outlined functions) to insert in the separate file to support outlining.
18599 vector<SgDeclarationStatement*> declarationList;
18600
18601 // Save the list of associated symbols of dependent declarations identified so that we can
18602 // support their replacement in the new AST.
18603 vector<SgSymbol*> symbolList;
18604
18605 // Keep track of declarations already copied so that we don't copy them more than once and try to insert them.
18606 set<SgDeclarationStatement*> alreadySavedDeclarations;
18607
18608 // Required visit function for the AST traversal
18609 void visit(SgNode *astNode);
18610 private:
18611 void addDeclaration(SgDeclarationStatement* decl);
18612 };
18613
18615getGlobalScopeDeclaration( SgDeclarationStatement* inputDeclaration )
18616 {
18617 // DQ (2/16/2009): Basically if a class is used from a namespace (or any outer scope) and we
18618 // outline the reference to the class, we have to declare not the class but the outer scope
18619 // (which will have the class included).
18620
18621 SgDeclarationStatement* returnDeclaration = inputDeclaration;
18622
18623 // I think that we have to copy the outer scope if the declaration's scope is not SgGlobal.
18624 SgScopeStatement* scope = inputDeclaration->get_scope();
18625 ROSE_ASSERT(scope != NULL);
18626
18627 // printf ("inputDeclaration->get_scope() = %p = %s \n",scope,scope->class_name().c_str());
18628
18629 // If the input declaration is not in global scope then find the parent declaration that is in global scope!
18630 SgGlobal* globalScope = isSgGlobal(scope);
18631 if (globalScope == NULL)
18632 {
18633 // Traverse back to the global scope to include outer declarations which contain the "declaration"
18634 // printf ("Traverse back to the global scope to include outer declarations \n");
18635
18636 SgScopeStatement* parentScope = scope;
18637 SgDeclarationStatement* associatedDeclaration = returnDeclaration;
18638 ROSE_ASSERT(parentScope != NULL);
18639 while (globalScope == NULL)
18640 {
18641 associatedDeclaration = getAssociatedDeclaration(parentScope);
18642 ROSE_ASSERT(associatedDeclaration != NULL);
18643
18644 parentScope = parentScope->get_scope();
18645 globalScope = isSgGlobal(parentScope);
18646 }
18647
18648 returnDeclaration = associatedDeclaration;
18649 }
18650
18651 return returnDeclaration;
18652 }
18653
18654
18655// Debugging support.
18656void
18657outputDeclarationList ( const vector<SgDeclarationStatement*> & l )
18658 {
18659 // This function support debugging the generated declarations.
18660
18661 int counter = 0;
18662 vector<SgDeclarationStatement*>::const_iterator i = l.begin();
18663 while ( i != l.end() )
18664 {
18665 printf ("In outputDeclarationList(): list[%d] = %p = %s = %s \n",counter++,*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
18666 i++;
18667 }
18668 }
18669
18670void CollectDependentDeclarationsTraversal::addDeclaration(SgDeclarationStatement* declaration)
18671{
18672 // If there was a declaration found then handle it.
18673 if (declaration != NULL)
18674 {
18675 // Reset the defining declaration in case there is an outer declaration that is more important
18676 // to consider the dependent declaration (e.g. a class in a namespace). In general this will
18677 // find the associated outer declaration in the global scope.
18678 SgDeclarationStatement* dependentDeclaration = getGlobalScopeDeclaration(declaration);
18679
18680 // This declaration is in global scope so we just copy the declaration
18681 // For namespace declarations: they may have the save name but they have to be saved separated.
18682 if (alreadySavedDeclarations.find(dependentDeclaration) == alreadySavedDeclarations.end())
18683 {
18684#if 0
18685 printf ("In CollectDependentDeclarationsTraversal::visit(): selected dependentDeclaration = %p = %s = %s \n",
18686 dependentDeclaration,dependentDeclaration->class_name().c_str(),SageInterface::get_name(dependentDeclaration).c_str());
18687#endif
18688 // DQ (2/22/2009): Semantics change for this function, just save the original declaration, not a copy of it.
18689 declarationList.push_back(dependentDeclaration);
18690
18691 // Record this as a copied declaration
18692 alreadySavedDeclarations.insert(dependentDeclaration);
18693#if 0
18694 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18695 printf ("############### ADDING dependentDeclaration = %p = %s to alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18696 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18697#endif
18698 // DQ (2/21/2009): Added assertions (will be inforced in SageInterface::appendStatementWithDependentDeclaration()).
18699 // ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
18700 }
18701 else
18702 {
18703#if 0
18704 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18705 printf ("############### EXISTING dependentDeclaration = %p = %s found in alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18706 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18707#endif
18708 }
18709 }
18710}
18711
18713static std::vector<SgTypedefDeclaration*> collectTypedefDeclarations(SgType* type)
18714{
18715 ROSE_ASSERT(type != NULL);
18716 std::vector<SgTypedefDeclaration*> result;
18717 SgType* currentType = type;
18718
18719 SgModifierType* modType = NULL;
18720 SgPointerType* pointType = NULL;
18721 SgReferenceType* refType = NULL;
18722 SgArrayType* arrayType = NULL;
18723 SgTypedefType* typedefType = NULL;
18724
18725 while (true)
18726 {
18727 modType = isSgModifierType(currentType);
18728 if(modType)
18729 {
18730 currentType = modType->get_base_type();
18731 }
18732 else
18733 {
18734 refType = isSgReferenceType(currentType);
18735 if(refType)
18736 {
18737 currentType = refType->get_base_type();
18738 }
18739 else
18740 {
18741 pointType = isSgPointerType(currentType);
18742 if ( pointType)
18743 {
18744 currentType = pointType->get_base_type();
18745 }
18746 else
18747 {
18748 arrayType = isSgArrayType(currentType);
18749 if (arrayType)
18750 {
18751 currentType = arrayType->get_base_type();
18752 }
18753 else
18754 {
18755 typedefType = isSgTypedefType(currentType);
18756 if (typedefType)
18757 {
18758 currentType = typedefType->get_base_type();
18759 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(typedefType->get_declaration());
18760 // have to try to get the defining declaration for a defining typedef declaration
18761 // otherwise AST traversal will not visit the non-defining one for a defining typedef declaration
18762 // sortSgNodeListBasedOnAppearanceOrderInSource() won't work properly
18763 SgTypedefDeclaration* decl = isSgTypedefDeclaration(tdecl->get_definingDeclaration());
18764 if (decl ==NULL)
18765 decl = tdecl;
18766 result.push_back(decl);
18767 }
18768 else
18769 {
18770 // Exit the while(true){} loop!
18771 break;
18772 }
18773 }
18774 }
18775 }
18776 }
18777 }
18778#if 0
18779 // debug here
18780 if (result.size()>0)
18781 {
18782 cout<<"------------Found a chain of typedef decls: count="<<result.size()<<endl;
18783 for (vector <SgTypedefDeclaration*>::const_iterator iter = result.begin();
18784 iter!=result.end(); iter ++)
18785 cout<<(*iter)->unparseToString()<<endl;
18786 }
18787#endif
18788 return result;
18789}
18790
18792void
18794 {
18795 // Statements that can cause us to have declaration dependences:
18796 // 1) variable declarations (through their types)
18797 // 2) function calls
18798 // 3) typedefs (through their base types)
18799 // Not implemented:
18800 // 4) static member functions (through their class)
18801 // 5) static data members (through their class)
18802 // 6) namespaces
18803 // 7) #include<> CPP directives.
18804
18805 // DQ (2/22/2009): Changing the semantics for this function,
18806 // just save the original declaration, not a copy of it.
18807
18808#if 0
18809 // Debugging support.
18810 Sg_File_Info* fileInfo = astNode->get_file_info();
18811 if (fileInfo != NULL && fileInfo->isFrontendSpecific() == false && (isSgStatement(astNode) != NULL) )
18812 {
18813 printf ("\n\nIn CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18814 // fileInfo->display("In CollectDependentDeclarationsTraversal::visit()");
18815 int counter = 0;
18816 printf ("alreadySavedDeclarations.size() = %" PRIuPTR " \n",alreadySavedDeclarations.size());
18817 for (set<SgDeclarationStatement*>::iterator i = alreadySavedDeclarations.begin(); i != alreadySavedDeclarations.end(); i++)
18818 {
18819 printf ("alreadySavedDeclarations %d: %p = %s \n",counter++,*i,(*i)->class_name().c_str());
18820 }
18821 }
18822#endif
18823
18824 // The following conditionals set this variable
18825 SgDeclarationStatement* declaration = NULL;
18826
18827 // 1) ------------------------------------------------------------------
18828 // Collect the declarations associated with referenced types in variable declarations (or any types associated with SgInitializedName IR nodes)
18829 SgInitializedName* initializedname = isSgInitializedName(astNode);
18830 if (initializedname != NULL)
18831 {
18832 SgType* type = initializedname->get_type();
18833
18834 // handle all dependent typedef declarations, if any
18835 std::vector <SgTypedefDeclaration*> typedefVec = collectTypedefDeclarations(type);
18836 for (std::vector <SgTypedefDeclaration*>::const_iterator iter =typedefVec.begin();
18837 iter != typedefVec.end(); iter++)
18838 {
18839 SgTypedefDeclaration* typedef_decl = *iter;
18840 addDeclaration(typedef_decl);
18841 symbolList.push_back(typedef_decl->get_symbol_from_symbol_table());
18842 }
18843
18844 // handle base type:
18845
18846 // We now can to strip typedefs since they are already handled by collectTypedefDeclarations()
18847 // this also reach to the defining body of a defining typedef declaration
18848 // and treat it as an independent declarations,
18849 // the assumption here is that a defining typedef declaration will only has its
18850 // nondefining declaration copied to avoid redefining of the struct.
18851 // This is also a workaround for an AST copy bug: defining body gets lost after copying
18852 // a defining typedef declaration.
18853 // Liao, 5/8/2009
18854 //
18855 // e.g. typedef struct hypre_BoxArray_struct
18856 // {
18857 // int alloc_size;
18858 // } hypre_BoxArray;
18859 //
18860 // struct hypre_BoxArray_struct will be treated as a strippedType and its declaration
18861 // will be inserted.
18862 //
18863 SgType* strippedType = type->stripType();
18864 SgNamedType* namedType = isSgNamedType(strippedType);
18865 if (namedType != NULL)
18866 {
18867 // Note that since this was obtained via the types and types are shared, this is the non-defining
18868 // declaration in original program (not the separate file is this is to support outlining into a
18869 // separate file.
18870 SgDeclarationStatement* named_decl = namedType->get_declaration();
18871 // the case of class declaration, including struct, union
18872 SgClassDeclaration* classDeclaration = isSgClassDeclaration(named_decl);
18873 if (classDeclaration != NULL)
18874 {
18875 // printf ("Found class declaration: classDeclaration = %p \n",classDeclaration);
18876 declaration = classDeclaration->get_definingDeclaration();
18877 // Liao, 12/09/2016.
18878 // In some cases, forward declaration of class types are used and sufficient, without providing defining declaration.
18879 // We should allow this.
18880 if (declaration != NULL)
18881 {
18882 // ROSE_ASSERT(declaration != NULL);
18883 addDeclaration(declaration);
18884 }
18885 else
18886 addDeclaration (classDeclaration); // we use the original forward declaration.
18887
18888 // Note that since types are shared in the AST, the declaration for a named type may be (is)
18889 // associated with the class declaration in the original file. However, we want to associated
18890 // class declaration in the current file, but since the AST copy mechanism work top-down, this
18891 // mapping form the declaration in the original file to the new declaration in the copied AST
18892 // is available in the SgCopyHelp map of copied IR nodes.
18893 // DQ (3/3/2009): Added support for symbol references to be saved (symbols in the original file).
18894 // these symbols will be mapped to their new symbols.
18895 ROSE_ASSERT(classDeclaration->hasAssociatedSymbol() == true);
18896 SgSymbol* classSymbol = classDeclaration->get_symbol_from_symbol_table();
18897 ROSE_ASSERT(classSymbol != NULL);
18898
18899 // printf ("Saving classSymbol = %p \n",classSymbol);
18900 symbolList.push_back(classSymbol);
18901 }
18902
18903 // handle Enum types
18904 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(named_decl);
18905 if (enum_decl != NULL)
18906 {
18907 declaration = enum_decl->get_definingDeclaration();
18908 ROSE_ASSERT(declaration != NULL);
18909 addDeclaration(declaration);
18910 ROSE_ASSERT(enum_decl->hasAssociatedSymbol() == true);
18911 // Liao 12/14/2012. use search_for_symbol_from_symbol_table() instead to avoid the defining/nondefing decl issue
18912 //SgSymbol* esymbol = enum_decl->get_symbol_from_symbol_table();
18913 SgSymbol* esymbol = enum_decl->search_for_symbol_from_symbol_table();
18914 ROSE_ASSERT(esymbol!= NULL);
18915 symbolList.push_back(esymbol);
18916 }
18917 } // end if namedType
18918#if 0
18919 printf ("Found reference to type = %p = %s strippedType = %p = %s \n",type,type->class_name().c_str(),strippedType,strippedType->class_name().c_str());
18920#endif
18921 }// end if (initializedname)
18922
18923 // 2) ------------------------------------------------------------------
18924 // Collect declarations associated with function calls.
18925 SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
18926 if (functionCallExp != NULL)
18927 {
18928 declaration = functionCallExp->getAssociatedFunctionDeclaration();
18929 //ROSE_ASSERT(declaration != NULL);
18930 // We allow a function pointer to have no specific declaration associated.
18931 if (declaration != NULL)
18932 addDeclaration(declaration);
18933
18934 // DQ (3/2/2009): Added support for symbol references to be saved (this can be a SgFunctionSymbol or a SgMemberFunctionSymbol).
18935 SgSymbol* functionSymbol = functionCallExp->getAssociatedFunctionSymbol();
18936 //ROSE_ASSERT(functionSymbol != NULL);
18937
18938 // printf ("Saving functionSymbol = %p \n",functionSymbol);
18939 if (functionSymbol)
18940 symbolList.push_back(functionSymbol);
18941 }
18942
18943 // 3) ------------------------------------------------------------------
18944 // Collect enumerate declarations associated with SgEnumVal
18945 SgEnumVal * eval = isSgEnumVal(astNode);
18946 if (eval != NULL)
18947 {
18948 declaration = eval->get_declaration();
18949 ROSE_ASSERT(declaration != NULL);
18950 addDeclaration(declaration);
18952 ROSE_ASSERT(symbol != NULL);
18953 symbolList.push_back(symbol);
18954 }
18955// addDeclaration(declaration); // do it in different cases individually
18956 }
18957
18958static std::map<const SgStatement*, bool> visitedDeclMap; // avoid infinite recursion
18959
18960
18962// Used to separate a function to a new source file and add necessary type declarations into the new file.
18963// NOTICE: each call to this function has to have call visitedDeclMap.clear() first!!
18964static void
18965getDependentDeclarations (SgStatement* stmt, vector<SgDeclarationStatement*> & declarationList, vector<SgSymbol*> & symbolList )
18966{
18967 // This function returns a list of the dependent declaration for any input statement.
18968 // Dependent declaration are functions called, types referenced in variable declarations, etc.
18969#if 0
18970 printf ("\n\n********************************************************** \n");
18971 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
18972 printf ("********************************************************** \n");
18973#endif
18974 visitedDeclMap[stmt]= true;
18976 t.traverse(stmt,preorder);
18977#if 0
18978 declarationList = t.declarationList;
18979 symbolList = t.symbolList;
18980#else
18981 // Merge to the parent level list
18982 copy(t.declarationList.begin(),t.declarationList.end(), back_inserter(declarationList));
18983 copy(t.symbolList.begin(),t.symbolList.end(), back_inserter(symbolList));
18984 // make their elements unique
18985 sort (declarationList.begin(), declarationList.end());
18986 vector<SgDeclarationStatement*>::iterator new_end = unique(declarationList.begin(), declarationList.end());
18987 declarationList.erase(new_end, declarationList.end());
18988
18989 sort (symbolList.begin(), symbolList.end());
18990 vector<SgSymbol*>::iterator end2 = unique(symbolList.begin(), symbolList.end());
18991 symbolList.erase(end2, symbolList.end());
18992
18993
18994 // Liao, 5/7/2009 recursively call itself to get dependent declarations' dependent declarations
18995 for (vector<SgDeclarationStatement*>::const_iterator iter = t.declarationList.begin();
18996 iter !=t.declarationList.end(); iter++)
18997 {
18998 SgDeclarationStatement* decl = *iter;
18999 SgType* base_type = NULL;
19000 SgStatement* body_stmt= NULL;
19001
19002 // grab base type for a declaration
19003 // For class declaration: grab their
19004 if (isSgClassDeclaration(decl))
19005 {
19006 base_type = isSgClassDeclaration(decl)->get_type();
19007 } else
19008 if (isSgTypedefDeclaration(decl))
19009 {
19010
19011 // we don't want to strip of nested typedef declarations
19012 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);
19013 }
19014
19015 //TODO variable declaration, function declaration: parameter list types,
19016 // multiple base_type then
19017
19018 // is the base type associated with a defining body?
19019 // TODO enum type
19020 if (isSgClassType(base_type))
19021 {
19022 SgClassDeclaration* class_decl = isSgClassDeclaration(isSgClassType(base_type)->get_declaration()->get_definingDeclaration());
19023 if (class_decl!=NULL)
19024 {
19025 body_stmt = class_decl->get_definition();
19026 }
19027 }
19028 // recursively collect dependent declarations for the body stmt
19029 if ((body_stmt!=NULL) &&(!visitedDeclMap[body_stmt]))
19030 { // avoid infinite recursion
19031 getDependentDeclarations(body_stmt, declarationList, symbolList);
19032 }
19033 }
19034#endif
19035} // end void getDependentDeclarations()
19036
19037
19038// Reorder a list of declaration statements based on their appearance order in source files
19039// This is essential to insert their copies into a new file in a right order
19040// Liao, 5/7/2009
19041vector<SgDeclarationStatement*>
19042SageInterface::sortSgNodeListBasedOnAppearanceOrderInSource(const vector<SgDeclarationStatement*>& nodevec)
19043{
19044 vector<SgDeclarationStatement*> sortedNode;
19045
19046 if (nodevec.size()==0 )
19047 return sortedNode;
19048 // no need to sort if there is only 1 element
19049 if (nodevec.size() ==1)
19050 return nodevec;
19051
19053 Rose_STL_Container<SgNode*> queryResult = NodeQuery::querySubTree(project,V_SgDeclarationStatement);
19054 for (Rose_STL_Container<SgNode*>::const_iterator iter = queryResult.begin();
19055 iter!= queryResult.end(); iter++)
19056 {
19057 // cerr<<"Trying to match:"<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19058 SgNode* cur_node = *iter;
19059 SgDeclarationStatement* cur_stmt = isSgDeclarationStatement(cur_node);
19060 ROSE_ASSERT(cur_stmt!=NULL);
19061 // Liao 12/14/2012. It is possible nodevec contains a first non-defining function declaration since the function is called in the outlined function
19062 // This is true even if the AST only has a defining function declaration.
19063 //
19064 // But that first non-defining function declaration is not traversable in AST due to it is hidden.
19065 // The solution here is to for each defining function decl traversed, convert it to the first nondefining one to do the match.
19066 SgFunctionDeclaration * func_decl = isSgFunctionDeclaration (cur_stmt);
19067 if (func_decl)
19068 {
19069 if (func_decl->get_definingDeclaration() == func_decl )
19070 {
19071 cur_stmt = func_decl->get_firstNondefiningDeclaration();
19072 ROSE_ASSERT (cur_stmt != func_decl);
19073 }
19074 }
19075 vector<SgDeclarationStatement*>::const_iterator i = find (nodevec.begin(), nodevec.end(), cur_stmt);
19076 if (i!=nodevec.end())
19077 {
19078 // It is possible we already visited a real prototype func decl before, now we see a prototype converted from a defining declaration.
19079 // We have to make sure only one copy is inserted.
19080 vector<SgDeclarationStatement*>::const_iterator j = find (sortedNode.begin(), sortedNode.end(), *i);
19081 if (j == sortedNode.end())
19082 sortedNode.push_back(*i);
19083 }
19084 }
19085
19086 if (nodevec.size() != sortedNode.size())
19087 {
19088 cerr<<"Fatal error in sortSgNodeListBasedOnAppearanceOrderInSource(): nodevec.size() != sortedNode.size()"<<endl;
19089 cerr<<"nodevec() have "<< nodevec.size()<<" elements. They are:"<<endl;
19090 for (vector<SgDeclarationStatement*>::const_iterator iter = nodevec.begin(); iter != nodevec.end(); iter++)
19091 {
19092 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19093 }
19094 cerr<<"sortedNode() have " << sortedNode.size() <<" elements. They are:"<<endl;
19095 for (vector<SgDeclarationStatement*>::const_iterator iter = sortedNode.begin(); iter != sortedNode.end(); iter++)
19096 {
19097 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19098 }
19099
19100 ROSE_ASSERT(nodevec.size() == sortedNode.size());
19101 }
19102 return sortedNode;
19103}
19104
19106// This function clears a history map transparently and return a sorted list of dependent declarations
19107std::vector<SgDeclarationStatement*>
19109 {
19110 // This function returns a list of the dependent declaration for any input statement.
19111 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19112#if 0
19113 printf ("\n\n********************************************************** \n");
19114 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19115 printf ("********************************************************** \n");
19116
19118 t.traverse(stmt,preorder);
19119
19120 return t.declarationList;
19121#else
19122 // share a single implementation for recursive lookup for dependent declaration
19123 visitedDeclMap.clear();
19124 vector<SgDeclarationStatement*> declarationList;
19125 vector<SgSymbol*> symbolList;
19126 getDependentDeclarations(stmt, declarationList, symbolList);
19127 declarationList = sortSgNodeListBasedOnAppearanceOrderInSource(declarationList);
19128#if 0
19129 printf ("\n\n ********************************************************** \n");
19130 cout<<"Found dependent decl: count="<<declarationList.size()<<endl;
19131 for ( vector<SgDeclarationStatement*>::const_iterator iter = declarationList.begin();
19132 iter != declarationList.end(); iter++)
19133 {
19134 cout<<"\t"<<(*iter)->class_name()<<" at line "<<(*iter)->get_file_info()->get_line()<<endl;
19135 if ((*iter)->variantT()== V_SgFunctionDeclaration)
19136 cout<<"func name is:"<<isSgFunctionDeclaration(*iter)->get_name().getString()<<endl;
19137 //<<(*iter)->unparseToString()<<endl; // unparseToString() won't work on outlined function
19138 }
19139 printf ("\n ********************************************************** \n");
19140#endif
19141
19142 return declarationList;
19143
19144#endif
19145 }
19146
19147
19148bool
19150 {
19151 bool returnValue = false;
19152
19153#if 0
19154 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());
19155#endif
19156
19157 if (functionName.is_null() == false)
19158 {
19159 // DQ (1/20/2019): Add operator~() to this list (see test2019_10.C).
19160 if ( functionName == "operator++" || functionName == "operator--" || functionName == "operator&" ||
19161 functionName == "operator!" || functionName == "operator*" || functionName == "operator+" ||
19162 functionName == "operator-" || functionName == "operator+" || functionName == "operator~")
19163 {
19164 returnValue = true;
19165 }
19166 }
19167
19168 return returnValue;
19169 }
19170
19171
19172// DQ (4/13/2013): We need these to support the unparing of operators defined by operator syntax or member function names.
19174bool
19176 {
19177 // DQ (4/21/2013): Reimplemented this function to support more of the prefix operators.
19178 // Also we now support when they are defined as member functions and non-member functions.
19179
19180 bool returnValue = false;
19181
19182 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(exp);
19183 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19184 // ROSE_ASSERT(memberFunctionRefExp != NULL);
19185
19186 SgName functionName;
19187 size_t numberOfOperands = 0;
19188
19189 if (memberFunctionRefExp != NULL)
19190 {
19191 ROSE_ASSERT(functionRefExp == NULL);
19192 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19193 if (memberFunctionDeclaration != NULL)
19194 {
19195 functionName = memberFunctionDeclaration->get_name();
19196 numberOfOperands = memberFunctionDeclaration->get_args().size();
19197 }
19198 }
19199 else
19200 {
19201 // This could be "friend bool operator!(const X & x);"
19202 if (functionRefExp != NULL)
19203 {
19204 SgFunctionDeclaration* functionDeclaration = functionRefExp->getAssociatedFunctionDeclaration();
19205 if (functionDeclaration != NULL)
19206 {
19207 functionName = functionDeclaration->get_name();
19208 numberOfOperands = functionDeclaration->get_args().size();
19209 }
19210 }
19211 else
19212 {
19213 // Note clear if this should be an error.
19214 printf ("In SageInterface::isPrefixOperator(): unknown case of exp = %p = %s \n",exp,exp->class_name().c_str());
19215 }
19216 }
19217
19218#if 0
19219 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);
19220#endif
19221
19222 if (isPrefixOperatorName(functionName) == true)
19223 {
19224 if (memberFunctionRefExp != NULL)
19225 {
19226 // This case is for member functions.
19227 ROSE_ASSERT(functionRefExp == NULL);
19228 if (numberOfOperands == 0)
19229 {
19230 // This is the C++ signature for the operator++() prefix operator.
19231 returnValue = true;
19232 }
19233 else
19234 {
19235 // This is the C++ signature for the operator++() postfix operator.
19236 returnValue = false;
19237 }
19238 }
19239 else
19240 {
19241 // This case is for non-member functions.
19242 ROSE_ASSERT(functionRefExp != NULL);
19243 ROSE_ASSERT(memberFunctionRefExp == NULL);
19244 if (numberOfOperands == 1)
19245 {
19246 // This is the C++ signature for the operator++() prefix operator.
19247 returnValue = true;
19248 }
19249 else
19250 {
19251 // This is the C++ signature for the operator++() postfix operator.
19252 ROSE_ASSERT(numberOfOperands == 2);
19253 returnValue = false;
19254 }
19255 }
19256 }
19257
19258#if 0
19259 printf ("Leaving SageInterface::isPrefixOperator(): returnValue = %s \n",returnValue ? "true" : "false");
19260#endif
19261
19262 return returnValue;
19263 }
19264
19265
19267bool
19269 {
19270 return ( (isPrefixOperator(exp) == false) && (isIndexOperator(exp) == false) );
19271 }
19272
19273
19275bool
19277 {
19278 bool returnValue = false;
19279 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19280 if (memberFunctionRefExp == NULL)
19281 return false;
19282
19283 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19284 if (memberFunctionDeclaration != NULL)
19285 {
19286 SgName functionName = memberFunctionDeclaration->get_name();
19287 if ( (functionName == "operator[]") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19288 {
19289 returnValue = true;
19290 }
19291 else
19292 {
19293 if ( (functionName == "operator()") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19294 {
19295 returnValue = true;
19296 }
19297 else
19298 {
19299 returnValue = false;
19300 }
19301 }
19302 }
19303
19304 return returnValue;
19305 }
19306
19307
19308// DQ (1/10/2014): Adding more general support for token based unparsing.
19310SageInterface::lastStatementOfScopeWithTokenInfo (SgScopeStatement* scope, std::map<SgNode*,TokenStreamSequenceToNodeMapping*> & tokenStreamSequenceMap)
19311 {
19312 // Return the last statement in the associated scope that has token information.
19313 SgStatement* lastStatement = NULL;
19314
19315 ROSE_ASSERT(scope != NULL);
19316
19317#if 0
19318 printf ("In SageInterface::lastStatementOfScopeWithTokenInfo(): scope = %p = %s \n",scope,scope->class_name().c_str());
19319#endif
19320
19321 SgIfStmt* ifStatement = isSgIfStmt(scope);
19322 if (ifStatement != NULL)
19323 {
19324 lastStatement = ifStatement->get_false_body();
19325 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19326 {
19327 lastStatement = ifStatement->get_true_body();
19328 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19329 {
19330 lastStatement = NULL;
19331 }
19332 }
19333
19334 printf ("Note: SgIfStmt scope in SageInterface::lastStatementOfScopeWithTokenInfo(): returning lastStatement = %p \n",lastStatement);
19335 if (lastStatement != NULL)
19336 {
19337 printf (" --- lastStatement = %p = %s \n",lastStatement,lastStatement->class_name().c_str());
19338 }
19339
19340 return lastStatement;
19341 }
19342
19343 SgStatementPtrList statementList = scope->generateStatementList();
19344 if (statementList.rbegin() != statementList.rend())
19345 {
19346 // Find the last statement with token stream information.
19347 SgStatementPtrList::reverse_iterator i = statementList.rbegin();
19348
19349 while (i != statementList.rend() && (tokenStreamSequenceMap.find(*i) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[*i] == NULL) )
19350 {
19351 i++;
19352 }
19353
19354 if (i == statementList.rend())
19355 {
19356 lastStatement = NULL;
19357 }
19358 else
19359 {
19360 lastStatement = *i;
19361 }
19362 }
19363
19364 return lastStatement;
19365 }
19366
19367
19368void
19370 {
19371 // DQ (8/12/2020): Check the access permissions of all defining and nodefining declarations (debugging support for Cxx_tests/test2020_28.C).
19372
19373 class DeclarationTraversal : public AstSimpleProcessing
19374 {
19375 public:
19376 // DeclarationTraversal() {}
19377
19378 void visit (SgNode* node)
19379 {
19380 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
19381 if (decl != NULL)
19382 {
19383 SgDeclarationStatement* definingDeclaration = isSgDeclarationStatement(decl->get_definingDeclaration());
19384 SgDeclarationStatement* firstNondefiningDeclaration = isSgDeclarationStatement(decl->get_firstNondefiningDeclaration());
19385 SgDeclarationStatement* otherDeclaration = NULL;
19386
19387 // Output access modifier information for each declaration.
19388 printf ("Found declaration = %p = %s name = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
19389 if (decl != definingDeclaration && decl != firstNondefiningDeclaration)
19390 {
19391 otherDeclaration = decl;
19392 }
19393
19394 if (definingDeclaration != NULL)
19395 {
19396 definingDeclaration->get_declarationModifier().get_accessModifier().display("definingDeclaration: accessModifier");
19397 }
19398
19399 if (firstNondefiningDeclaration != NULL)
19400 {
19401 firstNondefiningDeclaration->get_declarationModifier().get_accessModifier().display("firstNondefiningDeclaration: accessModifier");
19402 }
19403
19404 if (otherDeclaration != NULL)
19405 {
19406 otherDeclaration->get_declarationModifier().get_accessModifier().display("otherDeclaration: accessModifier");
19407 }
19408
19409 // Adding space for formatting.
19410 printf ("\n");
19411 }
19412 }
19413 };
19414
19415 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19416 DeclarationTraversal traversal;
19417 traversal.traverse(astNode, preorder);
19418 }
19419
19420
19421void
19423 {
19424 // DQ (8/14/2020): Check the symbol tables for specific scopes (debugging support).
19425
19426 class ScopeTraversal : public AstSimpleProcessing
19427 {
19428 public:
19429 void visit (SgNode* node)
19430 {
19431 SgScopeStatement* scope = isSgScopeStatement(node);
19432 if (scope != NULL)
19433 {
19434 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
19435 if (functionDefinition != NULL)
19436 {
19437 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
19438 ROSE_ASSERT(functionDeclaration != NULL);
19439
19440 string functionName = functionDeclaration->get_name();
19441
19442 printf ("functionName = %s \n",functionName.c_str());
19443
19444 if (functionName == "main")
19445 {
19446
19447 SgBasicBlock* functionBody = functionDefinition->get_body();
19448 ROSE_ASSERT(functionBody != NULL);
19449 SgSymbolTable* symbolTable = functionBody->get_symbol_table();
19450 ROSE_ASSERT(symbolTable != NULL);
19451
19452 // Print out the symbol table.
19453 symbolTable->print();
19454 }
19455 }
19456
19457 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
19458 if (namespaceDefinition != NULL)
19459 {
19460 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
19461 ROSE_ASSERT(namespaceDeclaration != NULL);
19462
19463 string namespaceName = namespaceDeclaration->get_name();
19464
19465 printf ("namespaceName = %s \n",namespaceName.c_str());
19466
19467 if (namespaceName == "B")
19468 {
19469 SgSymbolTable* symbolTable = namespaceDefinition->get_symbol_table();
19470 ROSE_ASSERT(symbolTable != NULL);
19471
19472 // Print out the symbol table.
19473 symbolTable->print();
19474 }
19475 }
19476 }
19477 }
19478 };
19479
19480 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19481 ScopeTraversal traversal;
19482 traversal.traverse(astNode, preorder);
19483 }
19484
19485//Jim Leek TODO (07/25/2023): After Dan merges his branch, please clean up all the #1f 0 stuff
19486void SageInterface::markNodeToBeUnparsed(SgNode* node, int physical_file_id)
19487 {
19488#if 0
19489 Sg_File_Info* fileInfo=node->get_file_info();
19490 if (fileInfo != NULL)
19491 {
19492 fileInfo->setTransformation();
19493 fileInfo->setOutputInCodeGeneration();
19494
19495 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19496 if (locatedNode != NULL)
19497 {
19498 // DQ (7/7/2015): Make the subtree as transformed.
19499 locatedNode->setTransformation();
19500 locatedNode->setOutputInCodeGeneration();
19501
19502 // DQ (7/8/2021): Added assertion.
19503 ROSE_ASSERT(locatedNode->get_file_info() != NULL);
19504#if 0
19505 printf ("In markNodeToBeUnparsed(): physical_file_id = %d \n",physical_file_id);
19506#endif
19507 // DQ (10/26/2020): Set the physical_file_id, required for ueader file unparsing (is it?).
19508 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19509#if 1
19510 printf ("Note: calling node markTransformationsForOutput(): node = %p = %s \n",node,node->class_name().c_str());
19511#endif
19512 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19513 // to call setTransformation() and setOutputInCodeGeneration().
19514 markTransformationsForOutput(node);
19515 }
19516 else
19517 {
19518#if 0
19519 printf ("Note: node is not a SgLocatedNode: node = %p = %s \n",node,node->class_name().c_str());
19520#endif
19521 }
19522 }
19523 else
19524 {
19525#if 0
19526 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19527#endif
19528 }
19529#else
19530 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19531 if (locatedNode != NULL)
19532 {
19533 locatedNode->setTransformation();
19534 locatedNode->setOutputInCodeGeneration();
19535
19536 // DQ (10/26/2020): Set the physical_file_id, required for header file unparsing (is it?).
19537 if (locatedNode->get_file_info() != NULL)
19538 {
19539#if 0
19540 printf ("In SageInterface::markNodeToBeUnparsed(): locatedNode = %p = %s calling set_physical_file_id(%d) \n",locatedNode,locatedNode->class_name().c_str(),physical_file_id);
19541#endif
19542 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19543 }
19544 else
19545 {
19546#if 1
19547 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19548#endif
19549 }
19550
19551 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19552 // to call setTransformation() and setOutputInCodeGeneration().
19553 // Jim Leek (07/25/2023) This doesn't seem to be redundant, it definately marks a bunch of the subtree as transformed
19554 // That otherwise isn't, but Reverse Type Dependence often fails to compile because too much gets unparsed.
19555 // markTransformationsForOutput(node);
19556 }
19557#endif
19558 }
19559
19560
19561
19562void SageInterface::markSubtreeToBeUnparsed(SgNode* root, int physical_file_id)
19563 {
19564 RoseAst ast(root);
19565 for (RoseAst::iterator i=ast.begin();i!=ast.end();++i)
19566 {
19567 markNodeToBeUnparsed(*i,physical_file_id);
19568 }
19569 }
19570
19571
19572
19574 {
19575 // DQ (7/13/2021): This function marks nodes in a subtree to be a transformation, but avoids marking subtrees of the SgCastExp.
19576 // This is important because currently the marking of an implicit cast will cause it to be unparsed, even though it is marked
19577 // as implicit. This detail of precedence of implicit flags over transformation flags needs to be fixed seperated.
19578 // This function has been implemented as part of debugging this issue.
19579
19580 class InheritedAttribute
19581 {
19582 public:
19583 int physical_file_id;
19584 bool isCastSubtree;
19585 InheritedAttribute(int file_id): physical_file_id(file_id), isCastSubtree(false) {}
19586 InheritedAttribute(const InheritedAttribute & X)
19587 {
19588 isCastSubtree = X.isCastSubtree;
19589 physical_file_id = X.physical_file_id;
19590 }
19591 };
19592
19593// DQ (7/21/21): This code construction does not work with the GNU 4.9.x compilers.
19594// #if !( ( (__GNUC__ == 4) && (__GNUC_MINOR__ <= 9) ) || (__GNUC__ < 4))
19595#if (__GNUC__ > 4)
19596
19597 class SubtreeTraversal : public SgTopDownProcessing<InheritedAttribute>
19598 {
19599 public:
19600 InheritedAttribute evaluateInheritedAttribute ( SgNode* node, InheritedAttribute inheritedAttribute)
19601 {
19602 InheritedAttribute returnAttribute(inheritedAttribute);
19603
19604 SgCastExp* castExpression = isSgCastExp(node);
19605 if (castExpression != NULL)
19606 {
19607 returnAttribute.isCastSubtree = true;
19608 }
19609
19610 if (returnAttribute.isCastSubtree == true)
19611 {
19612 // Nothing to do, unless we want to fixup the physical node id.
19613#if 0
19614 printf ("In markSubtreeToBeUnparsedTreeTraversal(): subtree of a SgCastExp: node = %p = %s physical_file_id = %d \n",
19615 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19616#endif
19617 }
19618 else
19619 {
19620#if 0
19621 printf ("In markSubtreeToBeUnparsedTreeTraversal(): Calling markNodeToBeUnparsed(): node = %p = %s physical_file_id = %d \n",
19622 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19623#endif
19624 // This logic will cause the SgCastExp node to NOT be marked as a transformation (not just its children).
19625 markNodeToBeUnparsed(node,inheritedAttribute.physical_file_id);
19626 }
19627
19628 return returnAttribute;
19629 }
19630 };
19631
19632 InheritedAttribute inheritedAttribute(physical_file_id);
19633
19634 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19635 SubtreeTraversal traversal;
19636
19637#if 0
19638 printf ("\nIn markSubtreeToBeUnparsedTreeTraversal(): calling traverse \n");
19639#endif
19640
19641 traversal.traverse(root, inheritedAttribute);
19642#else
19643 printf ("This function does not compile with GNU 4.9 or older compilers (part of ROSE used only with more modern compilers) \n");
19644#endif
19645
19646 }
19647
19648
19649
19650
19652vector<SgDeclarationStatement*>
19653generateCopiesOfDependentDeclarations (const vector<SgDeclarationStatement*>& dependentDeclarations, SgScopeStatement* targetScope)
19654//generateCopiesOfDependentDeclarations ( SgStatement* stmt, SgScopeStatement* targetScope )
19655 {
19656 // Liao suggests adding the target scope to the parameter list so that the constructed function
19657 // built using SageBuilder::buildNondefiningFunctionDeclaration() can be built to be in the
19658 // correct scope as soon as possible.
19659
19660 // This function uses the getDependentDeclarations() function to get the dependent declarations
19661 // and then returns a list of copies of each of them.
19662
19663#if 0
19664 printf ("\n\n********************************************************** \n");
19665 printf (" Inside of generateCopiesOfDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19666 printf ("********************************************************** \n");
19667#endif
19668
19669 vector<SgDeclarationStatement*> copiesOfDependentDeclarations;
19670 // avoiding call getDependentDeclarations() twice
19671// vector<SgDeclarationStatement*> dependentDeclarations = getDependentDeclarations(stmt);
19672
19673#if 0
19674 printf ("Output the dependentDeclarations: dependentDeclarations.size() = %" PRIuPTR " \n",dependentDeclarations.size());
19675 outputDeclarationList(dependentDeclarations);
19676#endif
19677#if 0
19678 printf ("************************************************ \n");
19679 printf ("*** Make all copies of dependentDeclarations *** \n");
19680 printf ("************************************************ \n");
19681#endif
19682
19683 // Should have a valid scope, so that symbol tables can be expected to be setup.
19684 ROSE_ASSERT(targetScope != NULL);
19685
19686 // DQ (2/25/2009): Initially this is always global scope so test this for now, at least.
19687 ROSE_ASSERT(isSgGlobal(targetScope) != NULL);
19688
19689 for (vector<SgDeclarationStatement*>::const_iterator i = dependentDeclarations.begin(); i != dependentDeclarations.end(); i++)
19690 {
19691#if 0
19692 printf ("Copying declaration = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
19693#endif
19694 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19695
19696 SgNode* copy_node = NULL;
19697 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
19698
19699 // For function declarations we don't want to do deep copies on defining declarations
19700 // since that would violate the One-time Definition Rule (ODR).
19701 if (functionDeclaration != NULL)
19702 {
19703 // the target scope may already have a declaration for this function.
19704 // This happens since SageInterface::appendStatementWithDependentDeclaration() is called in the end of outlining
19705 // and the original enclosing class of the outlined target has been changed already (replaced target with a call to OUT_xxx())
19706 // Also, getDependentDeclarations() recursively searches for declarations within the dependent class and hits OUT_xxx()
19707 // Liao, 5/8/2009
19708
19709 if ( SgProject::get_verbose() >= 1 )
19710 printf ("WARNING: In SageInterface -- generateCopiesOfDependentDeclarations(): I think this is the wrong lookup symbol function that is being used here! \n");
19711
19712 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
19713 // TV (2/4/2014): can be found in the project wide global scope...
19714 // So I removed it as we only build a nondef decl and it will only happen for function declared in global scope.`
19715#endif
19716#if 0
19717 printf ("In generateCopiesOfDependentDeclarations(): Copy mechanism appied to SgFunctionDeclaration functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19718
19719 printf ("functionDeclaration = %p \n",functionDeclaration);
19720 printf ("functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
19721 printf ("functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19722 printf ("functionDeclaration->get_scope() = %p \n",functionDeclaration->get_scope());
19723 printf ("targetScope = %p \n",targetScope);
19724#endif
19725 SgFunctionDeclaration* copy_functionDeclaration = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,targetScope);
19726 assert(copy_functionDeclaration != NULL);
19727
19728 copy_functionDeclaration->set_parent(targetScope);
19729
19730 assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != NULL);
19731
19732 // DQ (11/8/2020): This can not be asserted now that the buildSourceFile() has the
19733 // feature of clearing the symbol table used across multiple files.
19734 // assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != copy_functionDeclaration);
19735
19736 assert(copy_functionDeclaration->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table() != NULL);
19737
19738 assert(copy_functionDeclaration->get_scope() != NULL);
19739 assert(copy_functionDeclaration->get_scope() == targetScope);
19740 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19741 copy_functionDeclaration->get_type()) != NULL);
19742 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19743 copy_functionDeclaration->get_type())->get_symbol_basis() == copy_functionDeclaration->get_firstNondefiningDeclaration());
19744
19745 copy_node = copy_functionDeclaration;
19746#if 0
19747 printf ("In generateCopiesOfDependentDeclarations(): DONE: Copy mechanism appied to SgFunctionDeclaration \n");
19748 ROSE_ABORT();
19749#endif
19750 }
19751 else
19752 {
19753 // We only copy the non-defining declaration of a defining typedef declaration
19754 // since its defining body will be treated as a separate declaration and inserted to the new file.
19755 // This is also a workaround for an AST copy bug: losing defining body of a defining typedef declaration after copying.
19756 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(*i);
19757 if (tdecl)
19758 {
19759#if 0
19760 if (tdecl->get_definingDeclaration() == tdecl)
19761 cout<<"Copying a defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19762 else
19763 cout<<"Copying a non-defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19764#endif
19766 SgTypedefDeclaration* tdecl_copy = isSgTypedefDeclaration(copy_node);
19767 tdecl_copy->set_typedefBaseTypeContainsDefiningDeclaration (false); // explicit indicate this does not contain defining base type, Liao 12/14/2012
19768 }
19769 else
19770 copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19771
19772 // 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).
19773 SgDeclarationStatement* copy_declaration = isSgDeclarationStatement(copy_node);
19774 ROSE_ASSERT(copy_declaration != NULL);
19775
19776 // DQ (3/2/2009): This will be done later, but it is set above, so set it in this branch to be consistant.
19777 if (copy_declaration->hasExplicitScope() == true)
19778 copy_declaration->set_scope(targetScope);
19779 }
19780
19781 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19782 // Build a function prototype, but what scope should be used?
19783 // ROSE_ASSERT(functionDeclaration->get_scope() != NULL);
19784 // copy = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,functionDeclaration->get_scope());
19785
19786#if 0
19787 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());
19788#endif
19789
19790 ROSE_ASSERT(copy_node != NULL);
19791 ROSE_ASSERT(copy_node->get_file_info() != NULL);
19792
19793 // Note that the root of the does not have its file info set like its children.
19794 copy_node->get_file_info()->setTransformation();
19796 // copy_node->get_file_info()->display("CollectDependentDeclarationsTraversal::visit()");
19797
19798 SgDeclarationStatement* copy_definingDeclaration = isSgDeclarationStatement(copy_node);
19799 ROSE_ASSERT(copy_definingDeclaration != NULL);
19800
19801 ROSE_ASSERT( *i != NULL );
19802 ROSE_ASSERT(copy_definingDeclaration != NULL);
19803
19804 // DQ (2/26/2009): get_scope() will require a valid parent for some cases (see moreTest4.cpp).
19805 if (copy_definingDeclaration->get_parent() == NULL)
19806 {
19807 copy_definingDeclaration->set_parent(targetScope);
19808 }
19809 ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19810
19811#if 0
19812 printf ("DONE: Copying declaration: original scope = %p copied to scope = %p \n",(*i)->get_scope(),copy_definingDeclaration->get_scope());
19813#endif
19814
19815 // DQ (2/22/2009): I think we need to set these explicitly (it will be reset later).
19816 copy_definingDeclaration->set_parent(NULL);
19817
19818 // Now that we pass in the scope explicitly we can set the scope (above), so don't reset to NULL!
19819 // copy_definingDeclaration->set_scope(NULL);
19820
19821 // DQ (2/20/2009): Added assertion.
19822 ROSE_ASSERT(copy_definingDeclaration->get_parent() == NULL);
19823
19824#if 0
19825 // DQ (2/20/2009): Added assertion.
19826 // ROSE_ASSERT(copy_definingDeclaration->get_definingDeclaration() != NULL);
19827 if (copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL)
19828 {
19829 printf ("copy_definingDeclaration = %p \n",copy_definingDeclaration);
19830 printf ("copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL \n");
19831 printf ("copy_definingDeclaration->get_definingDeclaration() = %p \n",copy_definingDeclaration->get_definingDeclaration());
19832 }
19833#endif
19834
19835 // DQ (2/21/2009): Commented out as a test.
19836 if ((*i)->get_firstNondefiningDeclaration() != NULL)
19837 {
19838 ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
19839 }
19840
19841 // DQ (2/20/2009): Added asertion.
19842 // ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19843
19844 copiesOfDependentDeclarations.push_back(copy_definingDeclaration);
19845 }
19846
19847#if 0
19848 printf ("****************************************************** \n");
19849 printf ("*** DONE: Make all copies of dependentDeclarations *** \n");
19850 printf ("****************************************************** \n");
19851 printf ("copiesOfDependentDeclarations.size() = %" PRIuPTR " \n",copiesOfDependentDeclarations.size());
19852#endif
19853
19854 // The mapping of copies to original declarations should be 1-to-1.
19855 // Liao, not true anymore for getDependentDeclarations() using recursion: a depending class's body is searched for dependents also.
19856 // 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
19857 ROSE_ASSERT(copiesOfDependentDeclarations.size() <= dependentDeclarations.size());
19858
19859 return copiesOfDependentDeclarations;
19860 }
19861
19862
19863bool
19864declarationContainsDependentDeclarations( SgDeclarationStatement* decl, vector<SgDeclarationStatement*> & dependentDeclarationList )
19865 {
19866 // DQ (2/16/2009): This function finds the declarations in "decl" and checks if they match against those in dependentDeclarationList
19867 bool returnValue = false;
19868
19869#if 0
19870 printf ("\n\n********************************************************** \n");
19871 printf (" Inside of declarationContainsDependentDeclarations(decl = %p = %s) \n",decl,decl->class_name().c_str());
19872 printf ("********************************************************** \n");
19873#endif
19874
19875 vector<SgDeclarationStatement*> locallyDependentDeclarationList = SageInterface::getDependentDeclarations(decl);
19876
19877 // printf ("In declarationContainsDependentDeclarations(): locallyDependentDeclarationList: \n");
19878 // outputPreprocessingInfoList(locallyDependentDeclarationList);
19879
19880 for (size_t i = 0; i < locallyDependentDeclarationList.size(); i++)
19881 {
19882 SgDeclarationStatement* d = locallyDependentDeclarationList[i];
19883#if 0
19884 printf ("locallyDependentDeclarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
19885#endif
19886 vector<SgDeclarationStatement*>::iterator j = find(dependentDeclarationList.begin(),dependentDeclarationList.end(),d);
19887 if (j != dependentDeclarationList.end())
19888 {
19889 // These identified declaration must be output as members of the class when it is output in the separate header file.
19890 // infact ODR may require that the whole class be output! Actually I think we don't have any chioce here!
19891#if 0
19892 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());
19893#endif
19894 returnValue = true;
19895 }
19896 }
19897
19898#if 0
19899 printf ("**************************************************************************** \n");
19900 printf (" LEAVING: Inside of declarationContainsDependentDeclarations(decl = %p = %s) returnValue = %s \n",decl,decl->class_name().c_str(),returnValue ? "true" : "false");
19901 printf ("**************************************************************************** \n");
19902#endif
19903
19904 return returnValue;
19905 }
19908{
19909 ROSE_ASSERT (new_exp != NULL);
19910 ROSE_ASSERT (anchor_exp != NULL);
19911 ROSE_ASSERT (new_exp != anchor_exp);
19912
19913 SgNode* parent = anchor_exp->get_parent();
19914 ROSE_ASSERT (parent != NULL);
19915
19916 //TODO use deep copy may be a better way, avoid reusing the original anchor_exp
19917 SgCommaOpExp * result = buildCommaOpExp(new_exp, NULL);
19918 ROSE_ASSERT (result != NULL);
19919 replaceExpression (anchor_exp, result, true);
19920
19921 result->set_rhs_operand(anchor_exp);
19922 anchor_exp->set_parent(result);
19923 return result ;
19924}
19925
19926
19928SgCommaOpExp * SageInterface::insertAfterUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp, SgStatement** temp_decl /* = NULL */, SgVarRefExp** temp_ref /* = NULL */)
19929{
19930 ROSE_ASSERT (new_exp != NULL);
19931 ROSE_ASSERT (anchor_exp != NULL);
19932 ROSE_ASSERT (new_exp != anchor_exp);
19933
19934 SgNode* parent = anchor_exp->get_parent();
19935 ROSE_ASSERT (parent != NULL);
19936
19937 // insert TYPE T1; right before the enclosing statement of anchor_exp
19938 SgType * t = anchor_exp ->get_type();
19939 ROSE_ASSERT (t != NULL);
19940 SgStatement * enclosing_stmt = getEnclosingStatement(anchor_exp);
19941 ROSE_ASSERT (enclosing_stmt != NULL);
19942
19943 gensym_counter ++;
19944 string temp_name = "_t_"+ StringUtility::numberToString(gensym_counter);
19945 SgVariableDeclaration* t_decl = buildVariableDeclaration(temp_name, t, NULL, enclosing_stmt->get_scope());
19946 insertStatementBefore (enclosing_stmt, t_decl);
19947 SgVariableSymbol * temp_sym = getFirstVarSym (t_decl);
19948 ROSE_ASSERT (temp_sym != NULL);
19949 if (temp_decl)
19950 *temp_decl = t_decl;
19951
19952 // build ((T1 = anchor_exp, new_exp),T1) )
19953 SgVarRefExp * first_ref = buildVarRefExp(temp_sym);
19954 if (temp_ref)
19955 * temp_ref = first_ref;
19956 SgCommaOpExp * result = buildCommaOpExp ( buildCommaOpExp (buildAssignOp ( first_ref, deepCopy(anchor_exp)), new_exp) , buildVarRefExp(temp_sym));
19957 replaceExpression (anchor_exp, result, false);
19958
19959 return result;
19960}
19961
19962void
19964 {
19965 // Put out a message in the separate file to lable the dependent CPP directives.
19966 // --- PreprocessingInfo(DirectiveType, const std::string & inputString, const std::string & filenameString, int line_no, int col_no, int nol, RelativePositionType relPos );
19967 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
19968 string fileName = "separate-outlined-file";
19969 PreprocessingInfo* messageToUser = new PreprocessingInfo(PreprocessingInfo::C_StyleComment,message,fileName,0,0,1,PreprocessingInfo::before);
19970 // requiredDirectivesList.push_back(messageToUser);
19971 stmt->addToAttachedPreprocessingInfo(messageToUser,PreprocessingInfo::before);
19972
19973 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
19974 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
19975 // when multiple files are used on the command line.
19976 messageToUser->get_file_info()->setTransformation();
19977 }
19978
19979
19980// DQ (2/6/2009): Added function to support outlining into separate file.
19981// 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)
19982void
19984 {
19985 // New function to support outlining of functions into separate files (with their required declarations).
19986
19987#if 0
19988 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl = %p \n",decl);
19989 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_parent() = %p \n",decl->get_parent());
19990 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_scope() = %p \n",decl->get_scope());
19991 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): original_statement = %p \n",original_statement);
19992 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (decl) = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
19993 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_firstNondefiningDeclaration() = %p \n",decl->get_firstNondefiningDeclaration());
19994 if (decl->get_firstNondefiningDeclaration() != NULL)
19995 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
19996 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_definingDeclaration() = %p \n",decl->get_definingDeclaration());
19997 if (decl->get_definingDeclaration() != NULL)
19998 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_definingDeclaration())->getFileName().c_str());
19999#endif
20000
20001#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20002 // Make sure that the input declaration (decl" is consistent in it's representation across more
20003 // than one file (only a significant test when outlining to a separate file; which is what this
20004 // function supports).
20005 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20006 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20007 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20008
20009 // DQ (2/6/2009): I need to write this function to support the
20010 // insertion of the function into the specified scope. If the
20011 // file associated with the scope is marked as compiler generated
20012 // (or as a transformation) then the declarations referenced in the
20013 // function must be copied as well (those not in include files)
20014 // and the include files must be copies also. If the SgFile
20015 // is not compiler generated (or a transformation) then we just
20016 // append the function to the scope (trivial case).
20017
20018 // This code will be based on the work in:
20019 // developersScratchSpace/Dan/translator_tests/reverseTraversal.C
20020
20021 // To test this run: "rm moreTest2.o ; make moreTest2.o"
20022 // in directory: tests/nonsmoke/functional/roseTests/astOutliningTests
20023
20024 // ***** Also move different loop IR nodes into a common base class *****
20025
20026 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20027
20028 // DQ (3/2/2009): This now calls a newer function which returns a list of declarations and a list of symbols.
20029 // The declarations are sometimes outer declarations of nested references to dependent declaration in inner
20030 // scopes (see moreTest3.cpp). The Symbol list are the symbols in the old AST that will be mapped to newer
20031 // symbols generated in the copied AST.
20032 // Collect the declaration that the input declaration depends upon.
20033 vector<SgDeclarationStatement*> dependentDeclarationList_inOriginalFile;
20034
20035 dependentDeclarationList_inOriginalFile = getDependentDeclarations(decl);
20036
20037 // Generate the copies of all the dependent statements
20038// printf ("Fixme: this currently causes the getDependentDeclarations(decl) function to be called twice \n");
20039// vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(decl,scope);
20040 vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(dependentDeclarationList_inOriginalFile,scope);
20041 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20042
20043 // Make sure that the input declaration (decl" is consistent in it's representation across more
20044 // than one file (only a significant test when outlining to a separate file; which is what this
20045 // function supports).
20046 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20047 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20048 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20049
20050 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
20051 std::map<SgNode*, SgNode*> replacementMap;
20052
20053 // DQ (3/2/2009): Now use the collectDependentDeclarationsCopyType object to generate the mapping
20054 // from the symbols in the old AST to the new symbols in the new AST (generated as part of the AST
20055 // copy mechanism).
20056 SgCopyHelp::copiedNodeMapType copyNodeMap = collectDependentDeclarationsCopyType.get_copiedNodeMap();
20057 SgCopyHelp::copiedNodeMapType::iterator copyNodeMapItrator = copyNodeMap.begin();
20058 while (copyNodeMapItrator != copyNodeMap.end())
20059 {
20060 // Loop over all the nodes generated in the AST copy mechanism (accumulated result over multiple copies).
20061 // const SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20062 // SgNode* first = copyNodeMapItrator->first;
20063 SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20064 SgNode* second = copyNodeMapItrator->second;
20065#if 0
20066 printf ("copyNodeMapItrator.first = %p = %s second = %p = %s \n",first,first->class_name().c_str(),second,second->class_name().c_str());
20067#endif
20068 // Add the SgGlobal referenece to the replacementMap
20069 if (isSgSymbol(first) != NULL)
20070 {
20071#if 0
20072 printf ("Adding to replacementMap (first = %p = %s = %s , second = %p \n",first,first->class_name().c_str(),SageInterface::get_name(first).c_str(),second);
20073#endif
20074 replacementMap.insert(pair<SgNode*,SgNode*>(first,second));
20075 }
20076
20077 copyNodeMapItrator++;
20078 }
20079
20080#if 0
20081 printf ("Exiting after test of new functionality \n");
20082 ROSE_ABORT();
20083#endif
20084
20085 // DQ (2/22/2009): We need all the declarations! (moreTest3.cpp demonstrates this, since it drops
20086 // the "#define SIMPLE 1" which causes it to be treated a "0" (causing errors in the generated code).
20087 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(original_statement);
20088 vector<PreprocessingInfo*> requiredDirectivesList = collectCppDirectives(sourceFile);
20089
20090 SgFunctionDeclaration* outlinedFunctionDeclaration = isSgFunctionDeclaration(decl);
20091 ROSE_ASSERT(outlinedFunctionDeclaration != NULL);
20092 SgGlobal* originalFileGlobalScope = TransformationSupport::getGlobalScope(original_statement);
20093 ROSE_ASSERT(originalFileGlobalScope != NULL);
20094 if ( SgProject::get_verbose() >= 1 )
20095 printf ("WARNING: In SageInterface::appendStatementWithDependentDeclaration(): I think this is the wrong lookup symbol function that is being used here! \n");
20096
20097 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
20098 // SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name()));
20099 SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name(),NULL,NULL));
20100
20101 // SgSymbol* outlinedFunctionSymbolFromOutlinedFile = scope->lookup_symbol(outlinedFunctionDeclaration->get_name());
20102 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20103 SgFunctionSymbol* outlinedFunctionSymbolFromOutlinedFile = isSgFunctionSymbol(decl->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table());
20104#if 0
20105 printf ("outlinedFunctionSymbolFromOriginalFile = %p outlinedFunctionSymbolFromOutlinedFile = %p \n",outlinedFunctionSymbolFromOriginalFile,outlinedFunctionSymbolFromOutlinedFile);
20106
20107 printf ("TransformationSupport::getSourceFile(decl)->getFileName() = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20108 printf ("TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName() = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20109 printf ("TransformationSupport::getSourceFile(original_statement)->getFileName() = %s \n",TransformationSupport::getSourceFile(original_statement)->getFileName().c_str());
20110#endif
20111
20112 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile != NULL);
20113 ROSE_ASSERT(outlinedFunctionSymbolFromOutlinedFile != NULL);
20114
20115 // TV (07/24/2013): Symbol are unified across files through the project wide global scope
20116 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile == outlinedFunctionSymbolFromOutlinedFile);
20117
20118 // Add the SgGlobal referenece to the replacementMap
20119 replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
20120
20121 // Add the non-defining declarations of the outlined function to the replacementMap
20122 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOriginalFile = isSgFunctionDeclaration(outlinedFunctionSymbolFromOriginalFile->get_declaration());
20123 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOutlinedFile = isSgFunctionDeclaration(decl->get_firstNondefiningDeclaration());
20124 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOriginalFile != NULL);
20125 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOutlinedFile != NULL);
20126 replacementMap.insert(pair<SgNode*,SgNode*>(outlinedNondefiningFunctionDeclarationFromOriginalFile,outlinedNondefiningFunctionDeclarationFromOutlinedFile));
20127
20128
20129 // list<SgDeclarationStatement>::iterator i = declarationList.begin();
20130 // while (i != declarationList.end())
20131 // for (list<SgDeclarationStatement>::iterator i = declarationList.begin(); i != declarationList.end(); i++)
20132
20133// cout<<"\n*******************************************\n"<<endl;
20134// cout<<"Inserting dependent decls: count="<<dependentDeclarationList.size()<<endl;
20135 for (size_t i = 0; i < dependentDeclarationList.size(); i++)
20136 {
20137 SgDeclarationStatement* d = dependentDeclarationList[i]; // copies of dependent declarations
20138#if 0
20139 SgDeclarationStatement* originalDeclaration = dependentDeclarationList_inOriginalFile[i];
20140 printf ("declarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20141 printf ("originalDeclaration = %p \n",originalDeclaration);
20142
20143 d->get_file_info()->display("SageInterface::appendStatementWithDependentDeclaration()");
20144#endif
20145
20146 // DQ (2/20/2009): Added assertion.
20147 ROSE_ASSERT(d->get_parent() == NULL);
20148
20149 // scope->append_declaration(d);
20150 // scope->insert_statement (decl, d, /* bool inFront= */ true);
20151 ROSE_ASSERT(decl->get_scope() == scope);
20152 ROSE_ASSERT(find(scope->getDeclarationList().begin(),scope->getDeclarationList().end(),decl) != scope->getDeclarationList().end());
20153 scope->insert_statement (decl, d, /* bool inFront= */ true);
20154 d->set_parent (scope);
20155
20156#if 0
20157 printf ("Add the required symbol information to the symbol table: scope = %p = %s \n",scope,scope->class_name().c_str());
20158#endif
20159
20160 // For whatever type of declaration we add to the global scope in the new separate
20161 // file we have to add the required symbol information to the symbol table.
20162 switch(d->variantT())
20163 {
20164 case V_SgClassDeclaration:
20165 {
20166 if ( declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20167 printf ("Warning: This class contains dependent declarations (not implemented) \n");
20168 break;
20169 }
20170
20171 case V_SgMemberFunctionDeclaration:
20172 printf ("Sorry, support for dependent member function declarations not implemented! \n");
20173 ROSE_ABORT();
20174
20175 case V_SgTemplateInstantiationDecl:
20176 printf ("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration \n");
20177 d->get_file_info()->display("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration");
20178
20179 printf ("Case of SgTemplateInstantiationDecl not implemented. \n");
20180 ROSE_ABORT();
20181
20182 case V_SgNamespaceDeclarationStatement:
20183 if (declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20184 printf ("Warning: This namespace contains dependent declarations (not supported) \n");
20185 break;
20186
20187 case V_SgFunctionDeclaration:
20188 case V_SgTypedefDeclaration:
20189 case V_SgEnumDeclaration:
20190 break;
20191
20192 default:
20193 printf ("default case in SageInterface::appendStatementWithDependentDeclaration() (handling dependentDeclarationList) d = %p = %s \n",d,d->class_name().c_str());
20194 ROSE_ABORT();
20195 }
20196
20197
20198 // Collect include directives that are already attached to this dependent declaration.
20199 vector<PreprocessingInfo*> cppDirectivesAlreadyAttachedToDependentDeclarations = collectCppDirectives(d);
20200
20201#if 0
20202 printf ("directives BEFORE excluding those already present in dependent declarations \n");
20203 outputPreprocessingInfoList(requiredDirectivesList);
20204
20205 printf ("directives already attached to dependent declarations \n");
20206 outputPreprocessingInfoList(cppDirectivesAlreadyAttachedToDependentDeclarations);
20207#endif
20208
20209 // Remove these include directives from the requiredDirectivesList (to prevent redundant output in the generated file)
20210 vector<PreprocessingInfo*>::iterator j = cppDirectivesAlreadyAttachedToDependentDeclarations.begin();
20211 while ( j != cppDirectivesAlreadyAttachedToDependentDeclarations.end() )
20212 {
20213 // Remove this directive from the requiredDirectivesList (to avoid having them output redundently).
20214 vector<PreprocessingInfo*>::iterator entry = find(requiredDirectivesList.begin(),requiredDirectivesList.end(),*j);
20215 ROSE_ASSERT(entry != requiredDirectivesList.end());
20216
20217 requiredDirectivesList.erase(entry);
20218
20219 j++;
20220 }
20221
20222#if 0
20223 printf ("directives AFTER excluding those already present in dependent declarations \n");
20224 outputPreprocessingInfoList(requiredDirectivesList);
20225#endif
20226 }
20227
20228 // Add a message to the top of the outlined function that has been added
20229 addMessageStatement(decl,"/* OUTLINED FUNCTION */");
20230
20231 // Insert the dependent declarations ahead of the input "decl".
20232 SgStatement* firstStatmentInFile = NULL;
20233 if (dependentDeclarationList.empty() == true)
20234 {
20235 firstStatmentInFile = decl;
20236 }
20237 else
20238 {
20239 firstStatmentInFile = dependentDeclarationList[0];
20240 }
20241
20242 ROSE_ASSERT(firstStatmentInFile != NULL);
20243
20244 // Add a message to the top of the dependent declarations that have been added
20245 addMessageStatement(firstStatmentInFile,"/* REQUIRED DEPENDENT DECLARATIONS */");
20246
20247 // DQ (3/6/2009): Added support to permit exclusion of "#include<header.h>" files since they can make it
20248 // much more difficult for external tools. Later we will check if there are remaining unsatisfied dependent
20249 // declarations (which must be in the header file) so we can automate this step.
20250 if (excludeHeaderFiles == false)
20251 {
20252 // Include all the "#include<header.h>" cpp directives obtained from the original file.
20253 vector<PreprocessingInfo*>::reverse_iterator j = requiredDirectivesList.rbegin();
20254 while ( j != requiredDirectivesList.rend() )
20255 {
20256 firstStatmentInFile->addToAttachedPreprocessingInfo(*j,PreprocessingInfo::before);
20257 j++;
20258 }
20259 }
20260
20261 // Add a message to the top of the CPP directives that have been added
20262 addMessageStatement(firstStatmentInFile,"/* REQUIRED CPP DIRECTIVES */");
20263
20264 // ****************************************************************************
20265 // **************** Fixup AST to Reset References To IR nodes ***************
20266 // ****************************************************************************
20267 // This traversal of the replacement map modified the AST to reset pointers to subtrees that will be shared.
20268 // The whole AST is traversed (using the memory pool traversal) and the data member pointers to IR nodes that
20269 // are found in the replacement map are used to lookup the replacement values that are used to reset the
20270 // pointers in the AST. As the replacement is computed the pointer values that are marked in the replacement
20271 // list for update are added to the intermediateDeleteSet.
20272
20273 SgSourceFile* outlinedFile = TransformationSupport::getSourceFile(scope);
20274 ROSE_ASSERT(outlinedFile != NULL);
20275
20276 // This replacement will be done over the entire file (parts of it are redundant with what has already
20277 // been done by the AST copy (so this step need not do as much and may be reduced to just operating
20278 // on the outlined function, I think).
20279#if 0
20280 printf ("\n\n************************************************************\n");
20281 printf ("Calling Utils::edgePointerReplacement() \n");
20282#endif
20283
20284 Rose::AST::Utility::edgePointerReplacement(outlinedFile,replacementMap);
20285
20286#if 0
20287 printf ("Calling Utils::edgePointerReplacement(): DONE \n");
20288 printf ("************************************************************\n\n");
20289
20290 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
20291 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
20292#endif
20293
20294 // Repeated test from above
20295 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20296
20297// endif for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20298#endif
20299
20300#if 0
20301 // The replacementMap should include the symbols associated with the dependentDeclarationList
20302 // and the outlined function (so dependentDeclarationList.size() + 1).
20303 printf ("replacementMap.size() = %" PRIuPTR " dependentDeclarationList.size() = %" PRIuPTR " \n",replacementMap.size(),dependentDeclarationList.size());
20304 // ROSE_ASSERT(replacementMap.size() == dependentDeclarationList.size() + 1);
20305#endif
20306 }
20307
20308void
20310 {
20311//Tan, August/25/2010: //Re-implement DeleteAST function
20312
20313 //Use MemoryPoolTraversal to count the number of references to a certain symbol
20314 //This class defines the visitors for the MemoryPoolTraversal
20315
20316 class ClassicVisitor : public ROSE_VisitorPattern
20317 {
20318 private:
20319 int SgVariableSymbol_count;
20320 int SgFunctionSymbol_count;
20321 int SgClassDeclaration_count;
20322 int SgTypedefSymbol_count;
20323 int SgMemFuncSymbol_count;
20324 int SgTemplateSymbol_count;
20325 int SgEnumFieldSymbol_count;
20326
20327 SgVariableSymbol* SgVariableSymbolPtr;
20328 SgFunctionSymbol* SgFunctionSymbolPtr;
20329 SgClassSymbol * SgClassSymbolPtr;
20330 SgTypedefSymbol * SgTypedefPtr;
20331 SgEnumFieldSymbol * SgEnumFieldSymbolPtr;
20332 SgMemberFunctionSymbol * SgMemFuncSymbolPtr;
20333 SgTemplateSymbol * SgTemplateSymbolPtr;
20334 SgClassDeclaration * class_defining;
20335 SgTemplateDeclaration * template_defining;
20337 SgTypedefDeclaration * typedef_defining;
20338 SgFunctionDeclaration * function_decl;
20339 SgTemplateInstantiationDecl * templateInstantiate_defining;
20340
20341 public:
20342 ClassicVisitor(SgVariableSymbol* symbol){
20343 SgVariableSymbol_count = 0;
20344 SgVariableSymbolPtr = symbol;
20345 SgFunctionSymbolPtr =NULL;
20346 SgClassSymbolPtr =NULL;
20347 SgTypedefPtr = NULL;
20348 SgMemFuncSymbolPtr =NULL;
20349 class_defining = NULL;
20350 memFunc =NULL;
20351 typedef_defining =NULL;
20352 function_decl = NULL;
20353 SgTemplateSymbolPtr = NULL;
20354 template_defining = NULL;
20355 SgEnumFieldSymbolPtr = NULL;
20356 templateInstantiate_defining =NULL;
20357 }
20358
20359 ClassicVisitor(SgFunctionSymbol* symbol){
20360 SgFunctionSymbol_count = 0;
20361 SgFunctionSymbolPtr = symbol;
20362
20363 // DQ (5/2/2013): Added to fix test2013_141.C.
20364 SgMemFuncSymbol_count =0;
20365
20366 SgVariableSymbolPtr = NULL;
20367 SgClassSymbolPtr =NULL;
20368 SgTypedefPtr = NULL;
20369 SgMemFuncSymbolPtr =NULL;
20370 class_defining = NULL;
20371 memFunc =NULL;
20372 typedef_defining =NULL;
20373 function_decl = NULL;
20374 SgTemplateSymbolPtr = NULL;
20375 template_defining = NULL;
20376 SgEnumFieldSymbolPtr = NULL;
20377 templateInstantiate_defining =NULL;
20378 }
20379
20380 ClassicVisitor(SgClassSymbol* symbol){
20381 SgClassDeclaration_count = 0;
20382 SgClassSymbolPtr = symbol;
20383 SgFunctionSymbolPtr = NULL;
20384 SgVariableSymbolPtr = NULL;
20385 SgTypedefPtr = NULL;
20386 SgMemFuncSymbolPtr =NULL;
20387 class_defining = NULL;
20388 memFunc =NULL;
20389 typedef_defining =NULL;
20390 function_decl = NULL;
20391 SgTemplateSymbolPtr = NULL;
20392 template_defining = NULL;
20393 SgEnumFieldSymbolPtr = NULL;
20394 templateInstantiate_defining =NULL;
20395 }
20396
20397 ClassicVisitor(SgTypedefSymbol* symbol){
20398 SgTypedefSymbol_count =0;
20399 SgTypedefPtr = symbol;
20400 SgClassSymbolPtr = NULL;
20401 SgFunctionSymbolPtr = NULL;
20402 SgVariableSymbolPtr = NULL;
20403 SgMemFuncSymbolPtr =NULL;
20404 class_defining = NULL;
20405 memFunc =NULL;
20406 typedef_defining =NULL;
20407 function_decl = NULL;
20408 SgTemplateSymbolPtr = NULL;
20409 template_defining = NULL;
20410 SgEnumFieldSymbolPtr = NULL;
20411 templateInstantiate_defining =NULL;
20412 }
20413
20414 ClassicVisitor(SgMemberFunctionSymbol* symbol){
20415 SgMemFuncSymbolPtr = symbol;
20416 SgMemFuncSymbol_count =0;
20417 SgTypedefPtr = NULL;
20418 SgClassSymbolPtr = NULL;
20419 SgFunctionSymbolPtr = NULL;
20420 SgVariableSymbolPtr = NULL;
20421 class_defining = NULL;
20422 memFunc =NULL;
20423 typedef_defining =NULL;
20424 function_decl = NULL;
20425 SgTemplateSymbolPtr = NULL;
20426 template_defining = NULL;
20427 SgEnumFieldSymbolPtr = NULL;
20428 templateInstantiate_defining =NULL;
20429 }
20430
20431 ClassicVisitor(SgTemplateSymbol* symbol){
20432 SgTemplateSymbolPtr = symbol;
20433 SgTemplateSymbol_count =0;
20434 SgMemFuncSymbolPtr = NULL;
20435 SgTypedefPtr = NULL;
20436 SgClassSymbolPtr = NULL;
20437 SgFunctionSymbolPtr = NULL;
20438 SgVariableSymbolPtr = NULL;
20439 class_defining = NULL;
20440 memFunc =NULL;
20441 typedef_defining =NULL;
20442 function_decl = NULL;
20443 template_defining = NULL;
20444 SgEnumFieldSymbolPtr = NULL;
20445 templateInstantiate_defining =NULL;
20446 }
20447
20448 ClassicVisitor(SgEnumFieldSymbol* symbol){
20449 SgEnumFieldSymbolPtr = symbol;
20450 SgEnumFieldSymbol_count =0;
20451 SgTemplateSymbolPtr = NULL;
20452 SgMemFuncSymbolPtr = NULL;
20453 SgTypedefPtr = NULL;
20454 SgClassSymbolPtr = NULL;
20455 SgFunctionSymbolPtr = NULL;
20456 SgVariableSymbolPtr = NULL;
20457 class_defining = NULL;
20458 memFunc =NULL;
20459 typedef_defining =NULL;
20460 function_decl = NULL;
20461 template_defining = NULL;
20462 templateInstantiate_defining =NULL;
20463 }
20464
20465
20466 ClassicVisitor(SgClassDeclaration* node){
20467 class_defining = node;
20468 SgMemFuncSymbolPtr = NULL;
20469 SgTypedefPtr = NULL;
20470 SgClassSymbolPtr = NULL;
20471 SgFunctionSymbolPtr = NULL;
20472 SgVariableSymbolPtr = NULL;
20473 memFunc =NULL;
20474 typedef_defining =NULL;
20475 function_decl = NULL;
20476 SgTemplateSymbolPtr = NULL;
20477 template_defining = NULL;
20478 SgEnumFieldSymbolPtr = NULL;
20479 templateInstantiate_defining =NULL;
20480 }
20481
20482 ClassicVisitor(SgTemplateDeclaration* node){
20483 template_defining = node;
20484 class_defining = NULL;
20485 SgMemFuncSymbolPtr = NULL;
20486 SgTypedefPtr = NULL;
20487 SgClassSymbolPtr = NULL;
20488 SgFunctionSymbolPtr = NULL;
20489 SgVariableSymbolPtr = NULL;
20490 memFunc =NULL;
20491 typedef_defining =NULL;
20492 function_decl = NULL;
20493 SgTemplateSymbolPtr = NULL;
20494 SgEnumFieldSymbolPtr = NULL;
20495 templateInstantiate_defining =NULL;
20496 }
20497 ClassicVisitor(SgFunctionDeclaration* node){
20498 function_decl =node;
20499 class_defining = NULL;
20500 SgMemFuncSymbolPtr = NULL;
20501 SgTypedefPtr = NULL;
20502 SgClassSymbolPtr = NULL;
20503 SgFunctionSymbolPtr = NULL;
20504 SgVariableSymbolPtr = NULL;
20505 memFunc =NULL;
20506 typedef_defining =NULL;
20507 SgTemplateSymbolPtr = NULL;
20508 template_defining = NULL;
20509 SgEnumFieldSymbolPtr = NULL;
20510 templateInstantiate_defining =NULL;
20511 }
20512
20513 ClassicVisitor(SgMemberFunctionDeclaration* node){
20514 memFunc = node;
20515 function_decl =NULL;
20516 class_defining = NULL;
20517 SgMemFuncSymbolPtr = NULL;
20518 SgTypedefPtr = NULL;
20519 SgClassSymbolPtr = NULL;
20520 SgFunctionSymbolPtr = NULL;
20521 SgVariableSymbolPtr = NULL;
20522 typedef_defining =NULL;
20523 SgTemplateSymbolPtr = NULL;
20524 template_defining = NULL;
20525 SgEnumFieldSymbolPtr = NULL;
20526 templateInstantiate_defining =NULL;
20527 }
20528
20529 ClassicVisitor(SgTypedefDeclaration* node){
20530 typedef_defining = node;
20531 memFunc = NULL;
20532 function_decl =NULL;
20533 class_defining = NULL;
20534 SgMemFuncSymbolPtr = NULL;
20535 SgTypedefPtr = NULL;
20536 SgClassSymbolPtr = NULL;
20537 SgFunctionSymbolPtr = NULL;
20538 SgVariableSymbolPtr = NULL;
20539 SgTemplateSymbolPtr = NULL;
20540 template_defining = NULL;
20541 SgEnumFieldSymbolPtr = NULL;
20542 templateInstantiate_defining =NULL;
20543 }
20544
20545 ClassicVisitor(SgTemplateInstantiationDecl* node){
20546 templateInstantiate_defining =node;
20547 typedef_defining = NULL;
20548 memFunc = NULL;
20549 function_decl =NULL;
20550 class_defining = NULL;
20551 SgMemFuncSymbolPtr = NULL;
20552 SgTypedefPtr = NULL;
20553 SgClassSymbolPtr = NULL;
20554 SgFunctionSymbolPtr = NULL;
20555 SgVariableSymbolPtr = NULL;
20556 SgTemplateSymbolPtr = NULL;
20557 template_defining = NULL;
20558 SgEnumFieldSymbolPtr = NULL;
20559 }
20560
20561
20562 // SgVariableSymbol and SgEnumFieldSymbol
20563 void visit(SgInitializedName* node)
20564 {
20565 if(SgVariableSymbolPtr !=NULL)
20566 {
20567 if(node->get_scope()!=NULL)
20568 {
20569 // DQ (5/21/2013): We want to restrict access to the symbol table.
20570 if(node->get_scope()->get_symbol_table()!=NULL)
20571 {
20573 if (isSgVariableSymbol(s) == SgVariableSymbolPtr) SgVariableSymbol_count++;
20574 }
20575 }
20576 }
20577
20578 if(SgEnumFieldSymbolPtr !=NULL)
20579 {
20580 if(node->get_scope()!=NULL)
20581 {
20582 // DQ (5/21/2013): We want to restrict access to the symbol table.
20583 if(node->get_scope()->get_symbol_table()!=NULL)
20584 {
20586 if (isSgEnumFieldSymbol(s) == SgEnumFieldSymbolPtr) SgEnumFieldSymbol_count++;
20587 }
20588 }
20589 }
20590 }
20591
20592 void visit(SgVarRefExp* node)
20593 {
20594 if(SgVariableSymbolPtr !=NULL){
20595 SgVariableSymbol* s = node->get_symbol();
20596 if (s == SgVariableSymbolPtr) SgVariableSymbol_count++;
20597 }
20598 }
20599
20600 int get_num_variable_pointers(){return SgVariableSymbol_count;}
20601
20602 int get_num_EnumField_pointers(){return SgEnumFieldSymbol_count;}
20603
20604
20605 // SgFunctionSymbol
20606 void visit(SgFunctionDeclaration* node) {
20607 if(SgFunctionSymbolPtr !=NULL){
20608 if(node->get_scope()!=NULL){
20609 // DQ (5/21/2013): We want to restrict access to the symbol table.
20610 if(node->get_scope()->get_symbol_table()!=NULL)
20611 {
20613 if ((SgFunctionSymbol *)s == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20614 }
20615 }
20616 }
20617#if 0
20618 if(function_decl!=NULL){
20619 if(node->get_symbol_from_symbol_table() == NULL){
20622 if(node!=function_decl && (define==function_decl || first_nondefine==function_decl)) delete node;
20623 }
20624 }
20625#endif
20626 }
20627
20628 void visit(SgFunctionRefExp* node)
20629 {
20630#if 0
20631 printf ("In visit(SgFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20632#endif
20633 if (SgFunctionSymbolPtr !=NULL)
20634 {
20635 SgFunctionSymbol* s = node->get_symbol_i();
20636 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20637 {
20638 SgFunctionSymbol_count++;
20639#if 0
20640 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20641#endif
20642 }
20643 }
20644 }
20645
20646 // DQ (5/2/2013): Added support for SgMemberFunctionRefExp which is not derived from SgFunctionRefExp.
20647 void visit(SgMemberFunctionRefExp* node)
20648 {
20649#if 0
20650 printf ("In visit(SgMemberFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20651#endif
20652 if (SgFunctionSymbolPtr !=NULL)
20653 {
20654 SgFunctionSymbol* s = node->get_symbol_i();
20655 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20656 {
20657 SgFunctionSymbol_count++;
20658#if 0
20659 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20660#endif
20661 }
20662 }
20663 }
20664
20665 void visit(SgUserDefinedBinaryOp* node)
20666 {
20667 if (SgFunctionSymbolPtr !=NULL){
20668 SgFunctionSymbol* s = node->get_symbol();
20669 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20670 }
20671 }
20672
20673 int get_num_Function_pointers(){return SgFunctionSymbol_count;}
20674
20675 // SgClassSymbol
20676 void visit(SgClassDeclaration* node)
20677 {
20678 if(SgClassSymbolPtr !=NULL){
20679 if(node->get_scope()!=NULL){
20680 if(node->get_scope()->get_symbol_table()!=NULL)
20681 {
20683 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20684 }
20685 }
20686 }
20687
20688 if(class_defining!=NULL) {
20689 if(node->get_symbol_from_symbol_table() == NULL){
20692 if((class_decl==class_defining||class_decl1==class_defining) && node!=class_defining )
20693 delete node;
20694 }
20695 }
20696 }
20697
20698 void visit(SgTemplateInstantiationDecl* node)
20699 {
20700 if(SgClassSymbolPtr !=NULL){
20701 if(node->get_scope()!=NULL){
20702 if(node->get_scope()->get_symbol_table()!=NULL)
20703 {
20705 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20706 }
20707 }
20708 }
20709
20710 if(templateInstantiate_defining!=NULL) {
20711 if(node->get_scope()!=NULL){
20712 if(node->get_scope()->get_symbol_table()!=NULL)
20713 {
20714 if(node->get_symbol_from_symbol_table() == NULL){
20717 if((template_decl==templateInstantiate_defining||template_decl1==templateInstantiate_defining) && node!=templateInstantiate_defining){
20718 /*vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
20719 foreach (SgTemplateArgument* element, tempargs){
20720 SgTemplateArgument* temparg = isSgTemplateArgument(element);
20721 if(temparg){
20722 delete temparg;
20723 }
20724 printf("SgTemplateArg in Memory Pool traversal\n");
20725 }*/
20726 delete node;
20727 //printf("SgTemplateInstantiationDecl in Memory Pool traversal\n");
20728 }
20729 }
20730 }
20731 }
20732 }
20733 }
20734
20735 void visit(SgThisExp* node)
20736 {
20737 if (SgClassSymbolPtr !=NULL){
20738 SgSymbol* s = node->get_class_symbol();
20739 if (s == SgClassSymbolPtr) SgClassDeclaration_count++;
20740 }
20741 }
20742
20743 void visit(SgClassNameRefExp* node)
20744 {
20745 if (SgClassSymbolPtr !=NULL){
20746 SgSymbol* s = node->get_symbol();
20747 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20748 }
20749 }
20750
20751
20752 int get_num_Class_pointers(){return SgClassDeclaration_count;}
20753
20754
20755 // SgMemberFunctionSymbol
20756 void visit(SgCtorInitializerList* node)
20757 {
20758 if(memFunc !=NULL){
20760 if(func == memFunc){
20761 delete node;
20762 }
20763 }
20764 }
20765
20766
20767 void visit(SgMemberFunctionDeclaration* node)
20768 {
20769 if (SgMemFuncSymbolPtr !=NULL){
20770 if(node->get_scope()!=NULL){
20771 if(node->get_scope()->get_symbol_table()!=NULL)
20772 {
20773 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20774 if(symbol == SgMemFuncSymbolPtr){
20775 SgMemFuncSymbol_count++;
20776 }
20777 }
20778 }
20779 }
20780 }
20781
20783 {
20784 if (SgMemFuncSymbolPtr !=NULL){
20785 if(node->get_scope()!=NULL){
20786 if(node->get_scope()->get_symbol_table()!=NULL)
20787 {
20788 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
20789 if(symbol == SgMemFuncSymbolPtr){
20790 SgMemFuncSymbol_count++;
20791 }
20792 }
20793 }
20794 }
20795 }
20796
20797
20798
20799 int get_num_memFunc_pointers(){return SgMemFuncSymbol_count;}
20800
20801
20802 // SgTypedefSymbol
20803 void visit(SgTypedefDeclaration* node)
20804 {
20805 if(SgTypedefPtr!=NULL){
20806 if(node->get_scope()!=NULL){
20807 if(node->get_scope()->get_symbol_table()!=NULL)
20808 {
20810 if ((SgTypedefSymbol *)s == SgTypedefPtr) SgTypedefSymbol_count++;
20811 }
20812 }
20813 }
20814 if(typedef_defining!=NULL){
20816 if(typedef_define == typedef_defining && node != typedef_defining ) {
20817 delete node;
20818 }
20819 }
20820 }
20821
20822 int get_num_Typedef_pointers(){return SgTypedefSymbol_count;}
20823
20824
20825
20826 void visit(SgTemplateDeclaration* node)
20827 {
20828 if (SgTemplateSymbolPtr !=NULL){
20829 if(node->get_scope()!=NULL){
20830 if(node->get_scope()->get_symbol_table()!=NULL)
20831 {
20832 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
20833 if(symbol == SgTemplateSymbolPtr){
20834 SgTemplateSymbol_count++;
20835 }
20836 }
20837 }
20838 }
20839
20840 if(template_defining !=NULL) {
20841 if(node->get_scope()!=NULL){
20842 if(node->get_scope()->get_symbol_table()!=NULL)
20843 {
20844 if(node->get_symbol_from_symbol_table() == NULL){
20847 if((template_decl==template_defining||template_decl1==template_defining) && node!=template_defining) {
20848 delete node;
20849
20850 }
20851 }
20852 }
20853 }
20854 }
20855 }
20856
20857 int get_num_Template_pointers(){return SgTemplateSymbol_count;}
20858
20859 };
20860
20861
20862 //Tan August,25,2010 //Traverse AST in post order, delete nodes and their symbols if it's safe to do so
20863 class DeleteAST : public SgSimpleProcessing, ROSE_VisitTraversal
20864 {
20865 public:
20866
20867 void visit (SgNode* node)
20868 {
20869 //These nodes are manually deleted because they cannot be visited by the traversal
20871 //remove SgVariableDefinition, SgVariableSymbol and SgEnumFieldSymbol
20873#if 0
20874 printf ("In DeleteAST::visit(): node = %p = %s \n",node,node->class_name().c_str());
20875#endif
20876#if 0
20877 // DQ (3/2/2014): I think this might be a problem...
20878 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
20879 if (isSgScopeStatement(node) !=NULL)
20880 {
20881 SgScopeStatement* scope = isSgScopeStatement(node);
20882#if 1
20883 printf ("Deleting the scopes type table: scope->get_type_table() = %p \n",scope->get_type_table());
20884#endif
20885 delete scope->get_type_table();
20886 }
20887#endif
20888#if 0
20889 // DQ (3/2/2014): I think this might be a problem...
20890 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
20891 if (isSgTypeTable(node) !=NULL)
20892 {
20893 SgTypeTable* typeTable = isSgTypeTable(node);
20894#if 1
20895 printf ("Deleting the type table (SgSymbolTable): typeTable->get_type_table() = %p \n",typeTable->get_type_table());
20896#endif
20897 delete typeTable->get_type_table();
20898 }
20899#endif
20900 if(isSgInitializedName(node) !=NULL){
20901 //remove SgVariableDefinition
20902 SgDeclarationStatement* var_def;
20903 var_def = ((SgInitializedName *)node)->get_definition();
20904 if(isSgVariableDefinition(var_def) !=NULL){
20905 delete var_def;
20906 //printf("A SgVariableDefinition was deleted\n");
20907 }
20908
20909
20910 //remove SgVariableSymbol
20911 if(isSgInitializedName(node)->get_scope()!=NULL){
20912 if(isSgInitializedName(node)->get_scope()->get_symbol_table()!=NULL)
20913 {
20914 SgSymbol* symbol = ((SgInitializedName *)node)->get_symbol_from_symbol_table();
20915 if(isSgVariableSymbol(symbol) !=NULL){
20916 ClassicVisitor visitor((SgVariableSymbol*)symbol);
20917 traverseMemoryPoolVisitorPattern(visitor);
20918 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20919 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20920 delete symbol;
20921 //printf("A SgVariableSymbol was deleted\n");
20922 }
20923 }
20924
20925 if(isSgEnumFieldSymbol(symbol) !=NULL){
20926 ClassicVisitor visitor((SgEnumFieldSymbol*)symbol);
20927 traverseMemoryPoolVisitorPattern(visitor);
20928 if(visitor.get_num_EnumField_pointers()==1){
20929 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20930 delete symbol;
20931 //printf("A SgEnumFieldSymbol was deleted\n");
20932 }
20933 }
20934
20935 }
20936 }
20937 }
20938
20939 if(isSgVarRefExp(node) !=NULL){
20940 SgVariableSymbol *symbol = ((SgVarRefExp*)node)->get_symbol();
20941 ClassicVisitor visitor(symbol);
20942 traverseMemoryPoolVisitorPattern(visitor);
20943 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20944 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20945 delete symbol;
20946 //printf("A SgVariableSymbol was deleted\n");
20947 }
20948 }
20949
20950 /*////////////////////////////////////////////////
20951 /remove SgFunctionSymbol
20953
20954 {
20955 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(node);
20956 if (funcDecl != NULL){
20957 if (isSgMemberFunctionDeclaration(node) == NULL) {
20958 if (funcDecl->get_scope() != NULL) {
20959 if (funcDecl->get_scope()->get_symbol_table() != NULL) {
20960 SgSymbol* symbol = ((SgFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20961 ClassicVisitor visitor((SgFunctionSymbol *)symbol);
20962 traverseMemoryPoolVisitorPattern(visitor);
20963 if (visitor.get_num_Function_pointers()==1) { //only one reference to this FunctionSymbol => safe to delete
20964 ((SgFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
20965 delete symbol;
20966 //printf("A SgFunctionSymbol was deleted\n");
20967 }
20968 ClassicVisitor visitor1((SgFunctionDeclaration *)node);
20969 traverseMemoryPoolVisitorPattern(visitor1);
20970 }
20971 }
20972 }
20973 }
20974 }
20975
20976 if(isSgFunctionRefExp(node) !=NULL)
20977 {
20978#if 0
20979 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(node);
20980 ROSE_ASSERT(functionRefExp->get_symbol_i() != NULL);
20981 printf ("In DeleteAST::visit(): functionRefExp->get_symbol_i() = %p = %s \n",functionRefExp->get_symbol_i(),functionRefExp->get_symbol_i()->class_name().c_str());
20982#endif
20983 SgFunctionSymbol *symbol = ((SgFunctionRefExp*)node)->get_symbol_i();
20984 ClassicVisitor visitor(symbol);
20985 traverseMemoryPoolVisitorPattern(visitor);
20986 if(visitor.get_num_Function_pointers()==1)
20987 {
20988 // only one reference to this FunctionSymbol => safe to delete
20989 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20990 delete symbol;
20991 //printf("A SgFunctionSymbol was deleted\n");
20992 }
20993
20994 }
20995
20996 if(isSgUserDefinedBinaryOp(node) !=NULL){
20997 SgFunctionSymbol *symbol = ((SgUserDefinedBinaryOp*)node)->get_symbol();
20998 ClassicVisitor visitor(symbol);
20999 traverseMemoryPoolVisitorPattern(visitor);
21000 if(visitor.get_num_Function_pointers()==1){ //only one reference to this FunctionSymbol => safe to delete
21001 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21002 delete symbol;
21003 //printf("A SgFunctionSymbol was deleted\n");
21004 }
21005 }
21006
21007 /*/
21008 /remove SgTypedefSymbol
21010
21011 if(isSgTypedefDeclaration(node) !=NULL){
21012 if(((SgTypedefDeclaration*)node)->get_scope()!=NULL){
21013 if(((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21014 {
21015 SgSymbol* symbol = ((SgTypedefDeclaration*)node)->get_symbol_from_symbol_table();
21016 if(isSgTypedefSymbol(symbol)){
21017 ClassicVisitor visitor((SgTypedefSymbol*) symbol);
21018 traverseMemoryPoolVisitorPattern(visitor);
21019 if(visitor.get_num_Typedef_pointers()==1){ //only one reference to this SgTypedefSymbol => safe to delete
21020 ((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21021 delete symbol;
21022 //printf("A SgTypedefSymbol was deleted\n");
21023 }
21024 }
21025 }
21026 }
21027
21028 if(node == isSgTypedefDeclaration(node)->get_definingDeclaration()){
21029 ClassicVisitor visitor1((SgTypedefDeclaration*) node);
21030 traverseMemoryPoolVisitorPattern(visitor1);
21031 }
21032 }
21033
21034 /*////////////////////////////////////////////////
21035 /remove SgNamespaceDeclarationSymbol
21037
21038 if(isSgNamespaceDeclarationStatement(node) !=NULL){
21039 if(((SgNamespaceDeclarationStatement*)node)->get_scope()!=NULL){
21040 if(((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21041 {
21042 SgSymbol* symbol = ((SgNamespaceDeclarationStatement*)node)->get_symbol_from_symbol_table();
21043 if(isSgNamespaceSymbol(symbol)){
21044 ((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21045 delete symbol;
21046 //printf("A SgNamespaceSymbol was deleted\n");
21047 }
21048 }
21049 }
21050 }
21051
21052
21053 if(isSgNamespaceAliasDeclarationStatement(node) !=NULL){
21054 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()!=NULL){
21055 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21056 {
21057 SgSymbol* symbol = ((SgNamespaceAliasDeclarationStatement*)node)->get_symbol_from_symbol_table();
21058 if(isSgNamespaceSymbol(symbol)){
21059 ((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21060 delete symbol;
21061 //printf("A SgNamespaceSymbol was deleted\n");
21062 }
21063 }
21064 }
21065 }
21066
21067
21068 /*/
21069 /remove SgLabelSymbol
21071
21072 if(isSgLabelStatement(node) !=NULL){
21073 if(((SgLabelStatement*)node)->get_scope()!=NULL){
21074 if(((SgLabelStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21075 {
21076 SgSymbol* symbol = ((SgLabelStatement*)node)->get_symbol_from_symbol_table();
21077 if(isSgLabelSymbol(symbol)){
21078 ((SgLabelStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21079 delete symbol;
21080 //printf("A SgLabelSymbol was deleted\n");
21081 }
21082 }
21083 }
21084 }
21085
21086 if(isSgLabelRefExp(node) !=NULL){
21087 SgLabelSymbol* symbol = ((SgLabelRefExp*)node)->get_symbol();
21088 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21089 delete symbol;
21090 //printf("A SgLabelSymbol was deleted\n");
21091 }
21092
21093
21094 /*////////////////////////////////////////////////
21095 /remove SgEnumSymbol
21097
21098 if(isSgEnumDeclaration(node) !=NULL){
21099 if(((SgEnumDeclaration*)node)->get_scope()!=NULL){
21100 if(((SgEnumDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21101 {
21102 SgSymbol* symbol = ((SgEnumDeclaration*)node)->get_symbol_from_symbol_table();
21103 if(isSgEnumSymbol(symbol) !=NULL){
21104 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21105 delete symbol;
21106 //printf("A SgEnumSymbol was deleted\n");
21107 }
21108 }
21109 }
21110 SgEnumType* type= ((SgEnumDeclaration*)node)->get_type();
21111 if(type !=NULL){
21112 delete type;
21113 //printf("A SgEnumType was deleted\n");
21114 }
21115 }
21116
21117
21118 /*/
21119 /remove SgClassSymbol
21121
21122 if(isSgClassDeclaration(node) !=NULL && isSgTemplateInstantiationDecl(node) ==NULL){
21123 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21124 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21125 {
21126 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21127 if(isSgClassSymbol(symbol) !=NULL){
21128 ClassicVisitor visitor((SgClassSymbol*)symbol);
21129 traverseMemoryPoolVisitorPattern(visitor);
21130 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21131 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21132 delete symbol;
21133 //printf("A SgClassSymbol was deleted\n");
21134 }
21135 }
21136 }
21137 }
21138
21139 ClassicVisitor visitor((SgClassDeclaration*) node );
21140 traverseMemoryPoolVisitorPattern(visitor);
21141
21142 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21143 if(type !=NULL){
21144 delete type;
21145 //printf("A SgClassType was deleted\n");
21146 }
21147 }
21148
21149 if(isSgThisExp(node) !=NULL){
21150 SgSymbol* symbol = ((SgThisExp*)node)->get_class_symbol();
21151 ClassicVisitor visitor((SgClassSymbol*)symbol);
21152 traverseMemoryPoolVisitorPattern(visitor);
21153 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21154 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21155 delete symbol;
21156 //printf("A SgClassSymbol was deleted\n");
21157 }
21158
21159 }
21160
21161 if(isSgClassNameRefExp(node) !=NULL){
21162 SgSymbol* symbol = ((SgClassNameRefExp*)node)->get_symbol();
21163 if(isSgClassSymbol(symbol) !=NULL)
21164 {
21165 ClassicVisitor visitor((SgClassSymbol*)symbol);
21166 traverseMemoryPoolVisitorPattern(visitor);
21167 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21168 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21169 delete symbol;
21170 //printf("A SgClassSymbol was deleted\n");
21171 }
21172 }
21173 }
21174
21175 /*////////////////////////////////////////////////
21176 /remove SgMemberFunctionSymbol
21178
21179
21180 if(isSgMemberFunctionDeclaration(node) !=NULL){
21181 if(((SgMemberFunctionDeclaration*)node)->get_scope()!=NULL){
21182 if(((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21183 {
21184 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21185 if(isSgMemberFunctionSymbol(symbol)){
21186 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21187 traverseMemoryPoolVisitorPattern(visitor);
21188 if(visitor.get_num_memFunc_pointers()==1){
21189 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21190 delete symbol;
21191 //printf("A SgMemberFunctionSymbol was deleted\n");
21192 }
21193 }
21194 }
21195 }
21196 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21197 traverseMemoryPoolVisitorPattern(visitor);
21198
21199 }
21200//Tan: I have no idea why the codes below cannot work. Perhaps it conflicts with some prior works
21201#if 0
21202 if(isSgMemberFunctionRefExp(node) !=NULL){
21203 SgMemberFunctionSymbol* symbol = ((SgMemberFunctionRefExp*)node)->get_symbol_i();
21204 ClassicVisitor visitor(symbol);
21205 traverseMemoryPoolVisitorPattern(visitor);
21206 if(visitor.get_num_memFunc_pointers()==1){ //only one reference to this symbol => safe to delete
21207 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21208 delete symbol;
21209 //printf("A SgClassSymbol was deleted\n");
21210 }
21211
21212 }
21213
21214 if(isSgFunctionType(node) !=NULL){
21215 SgSymbol* symbol = ((SgFunctionType*)node)->get_symbol_from_symbol_table();
21216 if(isSgFunctionTypeSymbol(symbol)){
21217 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21218 delete symbol;
21219 //printf("A SgFunctionTypeSymbol was deleted\n");
21220 }
21221 }
21222#endif
21223
21224 /*/
21227
21228 if(isSgInterfaceStatement(node) !=NULL){
21229 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21230 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21231 {
21232 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21233 if(isSgInterfaceSymbol(symbol)){
21234 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21235 delete symbol;
21236 //printf("A SgInterfaceSymbol was deleted\n");
21237 }
21238 }
21239 }
21240
21241 }
21242
21243
21244 if(isSgModuleStatement(node) !=NULL){
21245 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21246 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21247 {
21248 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21249 if(isSgModuleSymbol(symbol)){
21250 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21251 delete symbol;
21252 //printf("A SgModuleSymbol was deleted\n");
21253 }
21254 }
21255 }
21256
21257 }
21258
21259
21260//Tan: I got stuck in deleting the SgTemplateArgument
21261#if 0
21262 if(isSgTemplateInstantiationMemberFunctionDecl(node) !=NULL){
21263 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()!=NULL){
21264 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21265 {
21266 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
21267 if(isSgMemberFunctionSymbol(symbol)){
21268 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21269 traverseMemoryPoolVisitorPattern(visitor);
21270 if(visitor.get_num_memFunc_pointers()==1){
21271 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21272 delete symbol;
21273 //printf("A SgMemberFunctionSymbol was deleted\n");
21274 }
21275 }
21276 }
21277 }
21278 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21279 traverseMemoryPoolVisitorPattern(visitor);
21280 }
21281
21282 if(isSgTemplateDeclaration(node) !=NULL){
21283 if(((SgTemplateDeclaration*)node)->get_scope()!=NULL){
21284 if(((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21285 {
21286 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
21287 ClassicVisitor visitor((SgTemplateSymbol*)symbol);
21288 traverseMemoryPoolVisitorPattern(visitor);
21289 if(visitor.get_num_Template_pointers()==1){
21290 ((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21291 delete symbol;
21292 printf("A SgTemplateSymbol was deleted\n");
21293 }
21294 }
21295 }
21296 //if(isSgTemplateDeclaration(node) == ((SgTemplateDeclaration*)node)->get_firstNondefiningDeclaration()){
21297 ClassicVisitor visitor1((SgTemplateDeclaration*) node );
21298 traverseMemoryPoolVisitorPattern(visitor1);
21299 //}
21300
21301 }
21302
21303 if(isSgInterfaceStatement(node) !=NULL){
21304 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21305 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21306 {
21307 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21308 if(isSgInterfaceSymbol(symbol)){
21309 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21310 delete symbol;
21311 //printf("A SgInterfaceSymbol was deleted\n");
21312 }
21313 }
21314 }
21315
21316 }
21317
21318
21319 if(isSgModuleStatement(node) !=NULL){
21320 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21321 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21322 {
21323 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21324 if(isSgModuleSymbol(symbol)){
21325 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21326 delete symbol;
21327 //printf("A SgModuleSymbol was deleted\n");
21328 }
21329 }
21330 }
21331
21332 }
21333
21334 if(isSgTemplateInstantiationDecl(node) !=NULL){
21335 if(((SgTemplateInstantiationDecl*)node)->get_scope()!=NULL){
21336 if(((SgTemplateInstantiationDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21337 {
21338 SgSymbol* symbol = ((SgTemplateInstantiationDecl*)node)->get_symbol_from_symbol_table();
21339 if(isSgClassSymbol(symbol)){
21340 ClassicVisitor visitor((SgClassSymbol*)symbol);
21341 traverseMemoryPoolVisitorPattern(visitor);
21342 if(visitor.get_num_Class_pointers()==1){
21343 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21344 delete symbol;
21345 }
21346 }
21347 }
21348 }
21349 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21350 if(type !=NULL){
21351 delete type;
21352 //printf("A SgClassType was deleted\n");
21353 }
21354
21355 vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
21356 foreach (SgTemplateArgument* element, tempargs){
21357 SgTemplateArgument* temparg = isSgTemplateArgument(element);
21358 if(temparg){
21359 delete temparg;
21360 }
21361 printf("SgTemplateArg in normal traversal\n");
21362 }
21363 printf("SgTemplateInstantiationDecl in normal traversal\n");
21364
21365 ClassicVisitor visitor((SgTemplateInstantiationDecl*) node);
21366 traverseMemoryPoolVisitorPattern(visitor);
21367 }
21368
21369#endif
21370#if 0
21371 printf ("Deleting node = %p = %s = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
21372#endif
21373 // Normal nodes will be removed in a post-order way
21374 delete node;
21375#if 0
21376 printf ("After delete node: node = %p = %s \n",node,node->class_name().c_str());
21377#endif
21378 }
21379 };
21380
21381
21382 DeleteAST deleteTree;
21383
21384 // Deletion must happen in post-order to avoid traversal of (visiting) deleted IR nodes
21385 deleteTree.traverse(n,postorder);
21386
21387#if 0
21388 printf ("Leaving SageInterface::deleteAST(): n = %p = %s \n",n,n->class_name().c_str());
21389#endif
21390 }
21391
21392
21393
21394
21395#ifndef USE_ROSE
21396// DQ (9/25/2011): The deleteAST() function will not remove original expression trees behind constant folded expressions.
21397// These exist in the AST within the internal construction of the AST until they are simplified in the AST post-processing.
21398// In the post-processing either:
21399// 1) the constant folded values are kept and the original expression trees deleted (optional, controled by default parameter to function "frontend()", OR
21400// 2) the constant folded values are replaced by the original expression trees, and the constant folded values are deleted (default).
21401// Either way, after the AST post-processing the AST is simplified. Until then the expression trees can contain constant
21402// folded values and the values will have a pointer to the original expression tree. Before (9/16/2011) the original
21403// tree would also sometimes (not uniformally) be traversed as part of the AST. This was confusing (to people and
21404// to numerous forms of analysis), so this is being fixed to be uniform (using either of the methods defined above).
21405// However, the fact that until post-processing the AST has this complexity, and that the AST traversal does not
21406// traverse the original expression trees (now uniform); means that we need a special delete function for subtrees
21407// that are not use post-processed. This is the special purpose function that we need.
21408//
21409// NOTE: This function is called from the SgArrayType::createType() member function and in the constant folding AST post-processing.
21410//
21412 {
21413 struct Visitor: public AstSimpleProcessing
21414 {
21415 virtual void visit(SgNode* n)
21416 {
21417 SgExpression* expression = isSgExpression(n);
21418 if (expression != NULL)
21419 {
21420 Visitor().traverse(expression->get_originalExpressionTree(), postorder);
21421 }
21422
21423 delete (n);
21424 }
21425 };
21426
21427 Visitor().traverse(root, postorder);
21428 }
21429#endif
21430 // move symbol table from one scope to another
21431static void moveSymbolTableBetweenBlocks(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, std::vector <SgInitializedName*>& initname_vec)
21432{
21433 // Move the symbol table
21434 SgSymbolTable* s_table = sourceBlock->get_symbol_table();
21435 ASSERT_not_null(sourceBlock->get_symbol_table());
21436 // Liao, 11/26/2019 make sure the symbol table has symbols for init names before and after the move
21437 for (SgInitializedName* iname : initname_vec)
21438 {
21439 SgSymbol* symbol = s_table->find(iname);
21440 ASSERT_not_null(symbol);
21441 }
21442 // entirely move source block's symbol table to target block
21443 targetBlock->set_symbol_table(sourceBlock->get_symbol_table());
21444
21445 ASSERT_not_null(sourceBlock);
21446 ASSERT_not_null(targetBlock);
21447 ASSERT_not_null(targetBlock->get_symbol_table());
21448 ASSERT_not_null(sourceBlock->get_symbol_table());
21449 targetBlock->get_symbol_table()->set_parent(targetBlock);
21450
21451 ASSERT_not_null(sourceBlock->get_symbol_table());
21452 sourceBlock->set_symbol_table(nullptr);
21453
21454 // Reset with a valid symbol table
21455 sourceBlock->set_symbol_table(new SgSymbolTable());
21456 sourceBlock->get_symbol_table()->set_parent(sourceBlock);
21457
21458 ASSERT_require(targetBlock->get_symbol_table() == s_table);
21459 for (SgInitializedName* iname : initname_vec)
21460 {
21461 SgSymbol* symbol = s_table->find(iname);
21462 ASSERT_not_null(symbol);
21463 }
21464
21465 // Liao, 11/26/2019 make sure init names have symbols after the move.
21466 for (SgInitializedName* iname : initname_vec)
21467 {
21468 SgSymbol* symbol = iname->get_symbol_from_symbol_table();
21469 ASSERT_not_null(symbol);
21470 }
21471}
21472
21473// helper function to move a single statement or declaration from a block to another
21474static void moveOneStatement(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, SgStatement* stmt, std::vector <SgInitializedName*>& initname_vec)
21475{
21476 // append statement to the target block
21477 targetBlock->append_statement(stmt);
21478
21479 // Make sure that the parents are set.
21480 ASSERT_require(stmt->get_parent() == targetBlock);
21481 if (stmt->hasExplicitScope())
21482 {
21483 if (stmt->get_scope() != targetBlock)
21484 {
21485 if (SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt))
21486 {
21487 // why only move if it is a first nondefining declaration?
21488 // We have a case to move both defining and nondefining function declarations of Ada package body to namespace definition.
21489 // comment out the if condition for now. 1/20/2021
21490 //
21491 // A call to a undeclared function will introduce a hidden func prototype declaration in the enclosing scope .
21492 // The func declaration should be moved along with the call site.
21493 // The scope should be set to the new block also
21494 // Liao 1/14/2011
21495 func->set_scope(targetBlock);
21496 // This is needed to move functions in Ada package body into C++ namespace
21497 // We may have compiler generated first nondefining declaration. We need to move its scope also
21498 SgFunctionDeclaration* nondef_decl= isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
21499 if (func != nondef_decl)
21500 {
21501 ASSERT_not_null(nondef_decl);
21502 ASSERT_not_null(nondef_decl->get_file_info());
21503 if (nondef_decl->get_file_info()->isCompilerGenerated()) {
21504 nondef_decl->set_scope(targetBlock);
21505 }
21506 }
21507 }
21508 else if (auto labelStmt = isSgLabelStatement(stmt))
21509 {
21510 if (labelStmt->get_scope() == sourceBlock) {
21511 labelStmt->set_scope(targetBlock);
21512 // Make sure the labelStmt is in the enclosing function scope of targetBlock
21513 SageInterface::fixLabelStatement(labelStmt, targetBlock);
21514 }
21515 }
21516 else if (isSgJovialTableStatement(stmt) || isSgTypedefDeclaration(stmt) || isSgEnumDeclaration(stmt))
21517 {
21518 // Rasmussen 9/21/2020,10/27/2020,11/4/2020: Uncovered by issues RC-135 and RC-227.
21519 // The issues are fixed in the switch statement below but this test is needed
21520 // so that the warning message immediately below is not triggered.
21521 }
21522 else
21523 {
21524 mlog[Rose::Diagnostics::WARN] << "test failing stmt->get_scope() == targetBlock in SageInterface::moveStatementsBetweenBlocks(): class: "
21525 << stmt->class_name() << "\n";
21526 }
21527 }
21528 }
21529
21530 SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
21531 if (declaration != nullptr)
21532 {
21533 // Need to reset the scope from sourceBlock to targetBlock.
21534 switch(declaration->variantT())
21535 {
21536 // There will be other cases to handle, but likely not all declaration will be possible to support.
21537
21538 case V_SgVariableDeclaration:
21539 {
21540 // Reset the scopes on any SgInitializedName objects.
21541 SgVariableDeclaration* varDecl = isSgVariableDeclaration(declaration);
21542 SgInitializedNamePtrList & l = varDecl->get_variables();
21543 for (SgInitializedNamePtrList::iterator ii = l.begin(); ii != l.end(); ii++)
21544 {
21545 // reset the scope, but make sure it was set to sourceBlock to make sure.
21546 // This might be an issue for extern variable declaration that have a scope
21547 // in a separate namespace of a static class member defined external to
21548 // its class, etc. I don't want to worry about those cases right now.
21549
21550 SgInitializedName * init_name = (*ii);
21551
21552 // Rasmussen (3/16/2021): Use the base type in case type is modified (i.e., const)
21553 SgType* var_type = init_name->get_type();
21554 if (SgModifierType* mod_type = isSgModifierType(var_type))
21555 {
21556 var_type = mod_type->get_base_type();
21557 }
21558
21559 // Rasmussen (6/29/2020) and (10/19/2020): Variable declarations related to anonymous types are not
21560 // moved. This is fixed below. Note that SgJovialTableType derives from SgClassType, it may
21561 // be that class types are not moved correctly either.
21562 //
21563 if (isSgEnumType(var_type))
21564 {
21565 SgEnumType* enum_type = isSgEnumType(var_type);
21566 SgEnumDeclaration* decl = isSgEnumDeclaration(enum_type->get_declaration());
21567 SgEnumDeclaration* def_decl = isSgEnumDeclaration(decl->get_definingDeclaration());
21568 SgEnumDeclaration* nondef_decl = isSgEnumDeclaration(decl->get_firstNondefiningDeclaration());
21569
21570 if (decl->get_scope() == sourceBlock)
21571 {
21572 // Needs to be moved
21573 def_decl->set_scope(targetBlock);
21574 nondef_decl->set_scope(targetBlock);
21575 nondef_decl->set_parent(targetBlock);
21576
21577 // Move the scope of the enumerators to the new block as well
21578 for (SgInitializedName* enumerator : def_decl->get_enumerators())
21579 {
21580 enumerator->set_scope(targetBlock);
21581 }
21582 }
21583 }
21584 else if (isSgJovialTableType(var_type))
21585 {
21586 SgJovialTableType* table_type = isSgJovialTableType(var_type);
21587 SgDeclarationStatement* decl = table_type->get_declaration();
21588 if (decl->get_scope() == sourceBlock)
21589 {
21590 // Needs to be moved
21593 def_decl->set_scope(targetBlock);
21594 nondef_decl->set_scope(targetBlock);
21595 nondef_decl->set_parent(targetBlock);
21596 }
21597 }
21598
21599 // Must also move the symbol into the source block, Liao 2019/8/14
21600 SgVariableSymbol* var_sym = isSgVariableSymbol(init_name -> search_for_symbol_from_symbol_table ()) ;
21601 ASSERT_not_null(var_sym);
21602 SgScopeStatement * old_scope = var_sym -> get_scope();
21603#if 1 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21604 if (old_scope != sourceBlock)
21605 {
21606 old_scope->remove_symbol (var_sym);
21607 sourceBlock ->insert_symbol(init_name->get_name(), var_sym);
21608 }
21609#endif
21610 init_name->set_scope(targetBlock);
21611 initname_vec.push_back(init_name);
21612 }
21613 break;
21614 }
21615 case V_SgFunctionDeclaration: // Liao 1/15/2009, I don't think there is any extra things to do here
21616 {
21617 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(declaration);
21618 ASSERT_not_null(funcDecl);
21619#if 0 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21620 // move function symbols also: search_for_symbol_from_symbol_table()
21622 if (func_sym)
21623 {
21624 SgScopeStatement * old_scope = func_sym -> get_scope();
21625 if (old_scope != sourceBlock)
21626 {
21627 old_scope->remove_symbol (func_sym);
21628 sourceBlock ->insert_symbol(func_sym->get_name(), func_sym);
21629 }
21630 }
21631#endif
21632 break;
21633 }
21634 // needed to move Ada record into definition of C++ namespace
21635 case V_SgProgramHeaderStatement:
21636 case V_SgProcedureHeaderStatement:
21637 case V_SgClassDeclaration:
21638 case V_SgEnumDeclaration:
21639 {
21640 SgDeclarationStatement* nondef_decl = declaration->get_firstNondefiningDeclaration();
21641 ASSERT_not_null(nondef_decl);
21642
21643 nondef_decl->set_parent(targetBlock);
21644 nondef_decl->set_scope(targetBlock);
21645
21646 SgDeclarationStatement* def_decl = declaration->get_definingDeclaration();
21647 if (def_decl)
21648 {
21649 def_decl->set_parent(targetBlock);
21650 def_decl->set_scope(targetBlock);
21651 }
21652 else
21653 {
21654 // Set the scope of the function arguments
21655 if (auto proc = isSgProcedureHeaderStatement(nondef_decl)) {
21656 for (auto arg : proc->get_parameterList()->get_args()) {
21657 if (arg->get_scope() != proc->get_scope()) {
21658 // Note: arg (is an SgInitializedName) from the parameter list does not have
21659 // a symbol in the scope of the procedure declaration (proc). Should add
21660 // arg to initname_vec, which will check for missing symbols [GL-387, Rasmussen 7/22/2024].
21661 arg->set_scope(proc->get_scope());
21662 }
21663 }
21664 }
21665 }
21666
21667 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(stmt);
21668 if (enum_decl)
21669 {
21670 // Set the scope of the enumerators [Rasmussen 12/23/2020]
21671 for (SgInitializedName* name : enum_decl->get_enumerators())
21672 {
21673 name->set_scope(targetBlock);
21674 }
21675 }
21676 break;
21677 }
21678 case V_SgJovialTableStatement:
21679 {
21680 // [RC-135, Rasmussen 9/21/2020]
21681 SgJovialTableStatement* table = isSgJovialTableStatement(declaration);
21682 ROSE_ASSERT (table);
21683
21686 nondef_decl->set_parent(targetBlock);
21687 nondef_decl->set_scope(targetBlock);
21688 def_decl->set_scope(targetBlock);
21689 break;
21690 }
21691 case V_SgTypedefDeclaration:
21692 {
21693 // [RC-227, Rasmussen 10/19/2020]
21694 SgTypedefDeclaration* typedef_decl = isSgTypedefDeclaration(declaration);
21695 ASSERT_not_null(typedef_decl);
21696 typedef_decl->set_parent(targetBlock);
21697 typedef_decl->set_scope(targetBlock);
21698 break;
21699 }
21700 case V_SgAttributeSpecificationStatement:
21701 case V_SgEmptyDeclaration:
21702 case V_SgFortranIncludeLine:
21703 case V_SgImplicitStatement: // Rasmussen 5/13/2021: TODO: implicit statement with letter-list
21704 case V_SgJovialDefineDeclaration:
21705 case V_SgJovialDirectiveStatement:
21706 case V_SgJovialLabelDeclaration:
21707 case V_SgJovialOverlayDeclaration:
21708 case V_SgPragmaDeclaration:
21709 case V_SgAdaAttributeClause:
21710 break;
21711 default:
21712 {
21713 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());
21714 declaration->get_file_info()->display("file info");
21715 ROSE_ABORT();
21716 }
21717 }
21718 } // end if
21719}
21720
21721// different handling for scopes with declarations only
21722template <class T1, class T2>
21723void moveDeclarationsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21724{
21725 // This function moves statements from one block to another (used by the outliner).
21726 // printf ("***** Moving statements from sourceBlock %p to targetBlock %p ***** \n",sourceBlock,targetBlock);
21727 ROSE_ASSERT (sourceBlock && targetBlock);
21728 ROSE_ASSERT (sourceBlock->containsOnlyDeclarations() && targetBlock->containsOnlyDeclarations());
21729 if ((void*)sourceBlock == (void*)targetBlock)
21730 {
21731 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21732 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21733 return;
21734 }
21735
21736 SgDeclarationStatementPtrList& srcStmts = sourceBlock->get_declarations ();
21737 std::vector <SgInitializedName*> initname_vec;
21738
21739 for (auto stmt : srcStmts)
21740 {
21741 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21742 }
21743
21744 // Remove the statements in the sourceBlock
21745 srcStmts.clear();
21746 ROSE_ASSERT(srcStmts.empty() == true);
21747 ROSE_ASSERT(sourceBlock->get_declarations().empty() == true);
21748
21749 // move symbol table from one scope to another
21750 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21751
21752 // Liao 2/4/2009
21753 // Finally , move preprocessing information attached inside the source block to the target block
21754 // Outliner uses this function to move a code block to the outlined function.
21755 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21756 // to the target block to match #if (which is attached
21757 // before some statement moved to the target block)
21758 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21759}
21760
21761
21762// source and destination class, both are derived classes of scope statement but with support of get_statements()
21763template <class T1, class T2>
21764void moveStatementsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21765{
21766 // This function moves statements from one block to another (used by the outliner).
21767 ROSE_ASSERT (sourceBlock && targetBlock);
21768 if ((void*)sourceBlock == (void*)targetBlock)
21769 {
21770 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21771 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21772 return;
21773 }
21774
21775 SgStatementPtrList & srcStmts = sourceBlock->get_statements();
21776 std::vector <SgInitializedName*> initname_vec;
21777
21778 for (SgStatement* stmt : srcStmts)
21779 {
21780 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21781 }
21782
21783 // Remove the statements in the sourceBlock
21784 srcStmts.clear();
21785 ROSE_ASSERT(srcStmts.empty() == true);
21786 ROSE_ASSERT(sourceBlock->get_statements().empty() == true);
21787
21788 // move symbol table from one scope to another
21789 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21790
21791 // Liao 2/4/2009
21792 // Finally , move preprocessing information attached inside the source block to the target block
21793 // Outliner uses this function to move a code block to the outlined function.
21794 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21795 // to the target block to match #if (which is attached
21796 // before some statement moved to the target block)
21797 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21798
21799}
21800
21801static void createAliasSymbols (SgNamespaceDeclarationStatement* decl)
21802{
21803 ASSERT_not_null(decl);
21805 SgNamespaceDefinitionStatement* global_def = local_def->get_global_definition();
21806
21807 ASSERT_require(local_def && global_def && (local_def!=global_def));
21808
21809 for (auto symbol : local_def->get_symbol_table()->get_symbols())
21810 {
21811 SgSymbol *orig_sym = isSgSymbol(symbol);
21812 ASSERT_not_null(orig_sym);
21813 SgAliasSymbol* asym = new SgAliasSymbol (orig_sym);
21814 global_def->get_symbol_table()->insert (asym->get_name(), asym);
21815 }
21816}
21817
21818//TODO: now with more types, we need to use template functions
21820{
21821 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21822 //create alias symbols in its global definition
21823 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21824}
21825
21827{
21828 moveStatementsBetweenScopes(sourceBlock, targetBlock);
21829 //create alias symbols in its global definition
21830 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21831}
21832
21834{
21835 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21836}
21837
21838void
21840{
21841 moveStatementsBetweenScopes (sourceBlock, targetBlock);
21842}
21843
21845// TODO, expose to SageInterface namespace
21847{
21848 bool rt = false;
21849 ROSE_ASSERT (func != NULL);
21850 SgNode* p = func->get_parent();
21851 ROSE_ASSERT (p != NULL);
21852 SgLambdaExp* le = isSgLambdaExp (p);
21853 if (le && le->get_lambda_function() == func)
21854 rt = true;
21855 return rt;
21856}
21857
21858// check if a variable reference is this->a[i] inside of a lambda function
21859// SgArrowExp <SgThisExp, SgVarRefExp>, both are compiler generated nodes
21860// class symbol of ThisExp 's declaration is AutonomousDeclaration SgClassDeclaration
21861// its parent is SgLambdaExp, and lambda_closure_class points back to this class declaration
21863{
21864 bool rt = false;
21865#ifdef _MSC_VER
21866 #pragma message ("WARNING: MSVC does not handle isLambdaCapturedVariable() properly.")
21867#else
21868 ROSE_ASSERT (varRef!= NULL);
21869 SgNode* parent = varRef->get_parent();
21870 if (SgArrowExp *p = isSgArrowExp(parent))
21871 {
21872 SgThisExp* te = isSgThisExp(p->get_lhs_operand_i());
21873 if (te != NULL)
21874 {
21875 SgClassSymbol* csym = te->get_class_symbol();
21876 ROSE_ASSERT (csym!= NULL);
21877 SgClassDeclaration* xdecl = isSgClassDeclaration(csym->get_declaration());
21878 // each this exp should have a class decl
21879 ROSE_ASSERT (xdecl != NULL);
21880 SgLambdaExp* le = isSgLambdaExp(xdecl->get_parent());
21881 if (le != NULL)
21882 {
21883 if (le->get_lambda_closure_class() == xdecl ) // the class is a lambda closure class
21884 rt = true;
21885 }
21886 }
21887 }
21888#endif
21889 return rt;
21890}
21891
21894//TODO consult AstInterface::IsVarRef() for more cases
21896{
21897 SgInitializedName* name = NULL;
21898 SgExpression* nameExp = NULL;
21899 ROSE_ASSERT(current != NULL);
21900
21901 if (isSgInitializedName(current))
21902 {
21903 name = isSgInitializedName(current);
21904 }
21905 else if (isSgPntrArrRefExp(current) != NULL)
21906 {
21907 bool suc=false;
21908 SgExpression* exp = isSgExpression(current);
21909 ROSE_ASSERT(exp != NULL);
21910 suc = SageInterface::isArrayReference(exp,&nameExp);
21911 ROSE_ASSERT(suc == true);
21912 // has to resolve this recursively
21913 return convertRefToInitializedName(nameExp, coarseGrain);
21914 }
21915 else if (isSgVarRefExp(current) != NULL)
21916 {
21917 if (coarseGrain)
21918 {
21919 // Outliner needs coarse grain mem objects to work. Always returning fine grain objects will cause problems.
21920 SgNode* parent = current->get_parent();
21921 if (isSgDotExp(parent))
21922 {
21923 if (isSgDotExp(parent)->get_rhs_operand() == current)
21924 return convertRefToInitializedName(parent, coarseGrain);
21925 }
21926 // avoid backtracking to parent if this is part of lambda function
21927 else if(isSgArrowExp(parent) && ! isLambdaCapturedVariable ( isSgVarRefExp(current) ) )
21928 {
21929 if (isSgArrowExp(parent)->get_rhs_operand() == current)
21930 return convertRefToInitializedName(parent, coarseGrain);
21931 }
21932 }
21933 name = isSgVarRefExp(current)->get_symbol()->get_declaration();
21934 }
21935 else if (isSgFunctionRefExp(current) != NULL ||
21936 isSgTemplateFunctionRefExp(current) != NULL ||
21937 isSgMemberFunctionRefExp(current) != NULL ||
21938 isSgTemplateMemberFunctionRefExp(current) != NULL)
21939 {
21940 //If a function is here it's probably related to a function pointer, it can't be converted to an SgInitailizedName
21941 return NULL;
21942 }
21943 else if (isSgNonrealRefExp(current) != NULL)
21944 {
21945 //SgNonrealRefExp is not a reasonable thing to convert to an SgInitializedName (I think) -Jim Leek
21946 return NULL;
21947 }
21948 else if (isSgDotExp(current))
21949 {
21950 SgExpression* child = NULL;
21951 if (coarseGrain)
21952 child= isSgDotExp(current)->get_lhs_operand();
21953 else
21954 child= isSgDotExp(current)->get_rhs_operand();
21955 ROSE_ASSERT(child);
21956 // has to resolve this recursively
21957 return convertRefToInitializedName(child, coarseGrain);
21958 }
21959 else if (isSgArrowExp(current))
21960 {
21961 SgExpression* child = NULL;
21962 if (coarseGrain)
21963 {
21964 SgExpression* lhs = isSgArrowExp(current)->get_lhs_operand();
21965 ROSE_ASSERT(lhs);
21966 // Liao 9/12/2016, special handling for variables inside of C++11 lambda functions
21967 // They capture variables outside of the lambda function.
21968 // They are represented as a class variable of an anonymous class, this->a[i]
21969 // So, we have to recognize this pattern, and pass the rhs variable to obtain initialized name.
21970 // has to resolve this recursively
21972
21973 if (isLambdaFunction (efunc) )
21974 child= isSgArrowExp(current)->get_rhs_operand();
21975 else
21976 child = lhs;
21977 }
21978 else
21979 child = isSgArrowExp(current)->get_rhs_operand();
21980 ROSE_ASSERT(child);
21981 // has to resolve this recursively
21982
21983 return convertRefToInitializedName(child, coarseGrain);
21984 } // The following expression types are usually introduced by left hand operands of DotExp, ArrowExp
21985 else if (isSgThisExp(current))
21986 {
21987 //SgThisExp* texp = isSgThisExp(current);
21988 name = NULL; // inside a class, there is no initialized name at all!! what to do??
21989 }
21990 else if (isSgPointerDerefExp(current))
21991 {
21992 return convertRefToInitializedName(isSgPointerDerefExp(current)->get_operand(), coarseGrain);
21993 }
21994 else if(isSgUnaryOp(current)) { //Written for SgAddressOfOp, but seems generally aplicable to all Unary Ops (replace above?) -JL
21995 return convertRefToInitializedName(isSgUnaryOp(current)->get_operand(), coarseGrain);
21996 }
21997 else if (isSgCastExp(current))
21998 {
21999 return convertRefToInitializedName(isSgCastExp(current)->get_operand(), coarseGrain);
22000 }
22001 // Scientific applications often use *(address + offset) to access array elements
22002 // If a pointer dereferencing is applied to AddOp, we assume the left operand is the variable of our interests
22003 else if (isSgAddOp(current))
22004 {
22005 SgExpression* lhs = isSgAddOp(current)->get_lhs_operand();
22006 return convertRefToInitializedName(lhs, coarseGrain);
22007 }
22008 else if (isSgSubtractOp(current))
22009 {
22010 SgExpression* lhs = isSgSubtractOp(current)->get_lhs_operand();
22011 return convertRefToInitializedName(lhs, coarseGrain);
22012 }
22013 // operator->() may be called upon a class object.
22014 // e.g. we need to get the function: it a SgDotExp node, (lhs is the class object, rhs is its member function)
22015 else if (SgFunctionCallExp * func_call = isSgFunctionCallExp(current))
22016 {
22017 return convertRefToInitializedName(func_call->get_function(), coarseGrain);
22018 }
22019 else if (isSgIntVal(current))
22020 {
22021 //It is very rare, but sometimes a constant is treated as a
22022 //variable. In which case we don't need an SgInitializdName
22023 return NULL;
22024 }
22025
22026 else
22027 {
22028 // side effect analysis will return rhs of Class A a = A(); as a read ref exp. SgConstructorInitializer
22029 if (!isSgConstructorInitializer(current))
22030 {
22031 mlog[Sawyer::Message::Common::WARN] <<
22032 "convertRefToInitializedName: " <<
22033 current->get_file_info()->get_filename() << ":" <<
22034 current->get_file_info()->get_line() << "-" << current->get_file_info()->get_col()<<endl;
22035 cerr<<"In SageInterface::convertRefToInitializedName(): unhandled reference type:"<<current->class_name()<<endl;
22036 ROSE_ABORT();
22037 }
22038 }
22039 //ROSE_ASSERT(name != NULL);
22040 return name;
22041}
22042
22045{
22046#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22047 printf ("AbstractHandle support is disabled for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT \n");
22048 ROSE_ABORT();
22049#else
22051
22052 // trim off the possible leading handle for project: "Project<numbering,1>::"
22053 size_t pos = input_string.find("SourceFile<");
22054 ROSE_ASSERT (pos != string::npos);
22055 string trimed_string = input_string.substr(pos);
22056 AbstractHandle::abstract_handle * handle = new AbstractHandle::abstract_handle(project_handle, trimed_string);
22057 if (handle)
22058 {
22059 if (handle->getNode()!=NULL)
22060 {
22061#ifdef _MSC_VER
22062 // DQ (11/28/2009): This is related to the use of covariant return types (I think).
22063 SgNode* result = NULL; // (SgNode*)(handle->getNode()->getNode());
22064#pragma message ("WARNING: covariant return type for get_node() not supported in MSVC.")
22065 printf ("ERROR: covariant return type for get_node() not supported in MSVC. \n");
22066 ROSE_ABORT();
22067#else
22068 SgNode* result = (SgNode*)(handle->getNode()->getNode());
22069#endif
22070 // deallocate memory, should not do this!!
22071 // May corrupt the internal std maps used in abstract handle namespace
22072 //delete handle->getNode();
22073 //delete handle;
22074 return result;
22075 }
22076 }
22077#endif
22078
22079 return NULL;
22080}
22081
22082
22084// unparseToString() is too strict for debugging purpose
22085// we provide this instead.
22086void SageInterface::dumpInfo(SgNode* node, std::string desc/*=""*/)
22087{
22088 ROSE_ASSERT(node != NULL);
22089 cout<<desc<<endl;
22090 // base information for all SgNode:
22091 cout<<"///////////// begin of SageInterface::dumpInfo() ///////////////"<<endl;
22092 cout<<"--------------base info. for SgNode---------------"<<endl;
22093 cout<<node<<" "<<node->class_name()<<endl;
22094 SgLocatedNode* snode = isSgLocatedNode(node);
22095 if (snode)
22096 {
22097 // source file info. dump
22098 cout<<"--------------source location info. for SgNode---------------"<<endl;
22099 cout<<snode->get_file_info()->get_filename()
22100 << ":"<<snode->get_file_info()->get_line()<<"-"
22101 << snode->get_file_info()->get_col()<<endl;
22102 // preprocessing info dump
22103 AttachedPreprocessingInfoType *comments = snode->getAttachedPreprocessingInfo ();
22104 if (comments)
22105 {
22106 cout<<"--------------preprocessing info. for SgNode---------------"<<endl;
22107 AttachedPreprocessingInfoType::iterator i;
22108 cout<<"Total attached preprocessingInfo count="<<comments->size()<<endl;
22109 for (i = comments->begin (); i != comments->end (); i++)
22110 {
22111 PreprocessingInfo * pinfo = *i;
22112 pinfo->display("");
22113 }
22114 }
22115 cout<<"--------------name info. for SgNode---------------"<<endl;
22116 // print out namea for named nodes
22117 SgFunctionDeclaration * decl = isSgFunctionDeclaration(snode);
22118 if (decl)
22119 cout<<"\tqualified name="<<decl->get_qualified_name().getString()<<endl;
22120 SgVarRefExp * varRef = isSgVarRefExp(snode);
22121 if (varRef)
22122 cout<<"\treferenced variable name= "<<varRef->get_symbol()->get_name().getString()<<endl;
22123 }
22124 SgInitializedName * iname = isSgInitializedName(snode);
22125 if (iname)
22126 cout<<"\tvariable name= "<<iname->get_qualified_name().getString()<<endl;
22127
22128 cout<<endl;
22129 cout<<"///////////// end of SageInterface::dumpInfo() ///////////////"<<endl;
22130}
22131
22137bool
22138SageInterface::collectReadWriteRefs(SgStatement* stmt, std::vector<SgNode*>& readRefs, std::vector<SgNode*>& writeRefs, bool useCachedDefUse)
22139{ // The type cannot be SgExpression since variable declarations have SgInitializedName as the reference, not SgVarRefExp.
22140 bool retVal = true;
22141
22142 ROSE_ASSERT(stmt !=NULL);
22143
22144#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22145 // We should allow accumulate the effects for multiple statements
22146 // ROSE_ASSERT(readRefs.size() == 0);
22147 // ROSE_ASSERT(writeRefs.size() == 0);
22148
22149 // convert a request for a defining function declaration to its function body
22150 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(stmt);
22151 if (funcDecl != NULL)
22152 {
22153 funcDecl= isSgFunctionDeclaration(funcDecl->get_definingDeclaration ());
22154 if (funcDecl == NULL)
22155 {
22156 cerr<<"In collectReadWriteRefs(): cannot proceed without a function body!"<<endl;
22157 }
22158 else
22159 stmt = funcDecl->get_definition()->get_body();
22160 }
22161
22162 // get function level information
22163 SgFunctionDefinition* funcDef = isSgFunctionDefinition(stmt);
22164 if (!funcDef)
22166
22167 ROSE_ASSERT(funcDef != NULL);
22168 SgBasicBlock* funcBody = funcDef->get_body();
22169 ROSE_ASSERT(funcBody!= NULL);
22170
22171 // prepare Loop transformation environment
22172 AstInterfaceImpl faImpl(funcBody);
22173 AstInterface fa(&faImpl);
22174 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
22175 if( useCachedDefUse ){
22176 ArrayInterface* array_interface = ArrayInterface::get_inst(*annot, fa, funcDef, AstNodePtrImpl(funcDef));
22177 LoopTransformInterface::set_arrayInfo(array_interface);
22178 } else {
22179 ArrayInterface array_interface(*annot);
22180 // Alias analysis and value propagation are called in initialize(). Turn both off for now.
22181// array_interface.initialize(fa, AstNodePtrImpl(funcDef));
22182 array_interface.observe(fa);
22183 LoopTransformInterface::set_arrayInfo(&array_interface);
22184 }
22185 LoopTransformInterface::set_astInterface(fa);
22186 // Liao, 3/27/2015. connect to annotations for function side effect
22187 LoopTransformInterface::set_sideEffectInfo(annot);
22188
22189 // variables to store results
22190 DoublyLinkedListWrap<AstNodePtr> rRef1, wRef1;
22191 CollectDoublyLinkedList<AstNodePtr> crRef1(rRef1),cwRef1(wRef1);
22192 AstNodePtr s1 = AstNodePtrImpl(stmt);
22193
22194 // Actual side effect analysis
22195 if (!AnalyzeStmtRefs(fa, s1, cwRef1, crRef1))
22196 {
22197 //False returned here just means that the function called a
22198 //function that was not annotated with Qing's RWset annotation
22199 //method. This doesn't matter for my tool. -Jim Leek 03/21/2023
22200 mlog[Sawyer::Message::Common::DEBUG] << "Function: " << funcDef->get_declaration()->get_qualified_name() << " calls at least one function that has not been annotated." << endl;
22201 retVal = false;
22202 }
22203
22204 // transfer results into STL containers.
22205 for (DoublyLinkedEntryWrap<AstNodePtr>* p = rRef1.First(); p != 0; )
22206 {
22207 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22208 p = rRef1.Next(p);
22209 AstNodePtr cur = p1->GetEntry();
22210 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22211 ROSE_ASSERT(sgRef != NULL);
22212 readRefs.push_back(sgRef);
22213 //cout<<"read reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22214 // " sage type:"<< sgRef->class_name()<< endl;
22215 }
22216
22217 for (DoublyLinkedEntryWrap<AstNodePtr>* p = wRef1.First(); p != 0; )
22218 {
22219 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22220 p = wRef1.Next(p);
22221 AstNodePtr cur = p1->GetEntry();
22222 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22223 ROSE_ASSERT(sgRef != NULL);
22224 writeRefs.push_back(sgRef);
22225 // cout<<"write reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22226 // " sage type:"<< sgRef->class_name()<< endl;
22227 }
22228
22229#endif
22230
22231 return retVal;
22232}
22233#if 0
22234// The side effect analysis will report three references for a statement like this->x = ...
22235// 1.SgThisExp 2. SgArrowExp 3. SgVarRefExp
22236// We only need to keep SgVarRefExp and skip the other two.
22237static bool skipSomeRefs(SgNode* n)
22238{
22239 ROSE_ASSERT (n);
22240 return (isSgThisExp(n)||isSgArrowExp(n)||isSgDotExp(n));
22241}
22242#endif
22244bool SageInterface::collectReadWriteVariables(SgStatement* stmt, set<SgInitializedName*>& readVars, set<SgInitializedName*>& writeVars, bool coarseGrain/*=true*/)
22245{
22246 ROSE_ASSERT(stmt != NULL);
22247 vector <SgNode* > readRefs, writeRefs;
22248
22249 bool retVal = collectReadWriteRefs(stmt, readRefs, writeRefs);
22250 // process read references
22251 vector<SgNode*>::iterator iter = readRefs.begin();
22252 for (; iter!=readRefs.end();iter++)
22253 {
22254 SgNode* current = *iter;
22255 //if (skipSomeRefs(current)) continue;
22256
22257 ROSE_ASSERT (current != NULL);
22258 SgInitializedName* name= convertRefToInitializedName(current, coarseGrain);
22259 //ROSE_ASSERT (name); // this pointer will return NULL
22260 if (!name) continue;
22261 // Only insert unique ones
22262 // We use std::set to ensure uniqueness now
22263 readVars.insert(name);
22264 }
22265 // process write references
22266 vector<SgNode*>::iterator iterw = writeRefs.begin();
22267 for (; iterw!=writeRefs.end();iterw++)
22268 {
22269 SgNode* current = *iterw;
22270 ROSE_ASSERT (current != NULL);
22271 SgInitializedName* name = convertRefToInitializedName(current, coarseGrain);
22272 if (!name) continue;
22273 //ROSE_ASSERT (name); // this pointer will return NULL
22274 // Only insert unique ones
22275 // We use std::set to ensure uniqueness now
22276 writeVars.insert(name);
22277 }
22278 return retVal;
22279}
22280
22282void SageInterface::collectReadOnlyVariables(SgStatement* stmt, std::set<SgInitializedName*>& readOnlyVars, bool coarseGrain/*=true*/)
22283{
22284 ROSE_ASSERT(stmt != NULL);
22285 set<SgInitializedName*> readVars, writeVars;
22286 // Only collect read only variables if collectReadWriteVariables() succeeded.
22287 if (collectReadWriteVariables(stmt, readVars, writeVars, coarseGrain))
22288 {
22289 // read only = read - write
22290 set_difference(readVars.begin(), readVars.end(),
22291 writeVars.begin(), writeVars.end(),
22292 std::inserter(readOnlyVars, readOnlyVars.begin()));
22293 }
22294 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
22295 {
22296 RoseAst ast(stmt);
22297
22298 for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
22299 if (SgVarRefExp* v_ref = isSgVarRefExp(*i))
22300 {
22301 if (isConstType(v_ref->get_type()))
22302 readOnlyVars.insert (v_ref->get_symbol()->get_declaration());
22303 }
22304 } // end for
22305 } // end else
22306}
22307
22308
22310void SageInterface::collectReadOnlySymbols(SgStatement* stmt, std::set<SgVariableSymbol*>& readOnlySymbols, bool coarseGrain/*=true*/)
22311{
22312 set<SgInitializedName*> temp;
22313 collectReadOnlyVariables(stmt, temp, coarseGrain);
22314
22315 for (set<SgInitializedName*>::const_iterator iter = temp.begin();
22316 iter!=temp.end(); iter++)
22317 {
22318 SgSymbol* symbol = (*iter)->get_symbol_from_symbol_table () ;
22319 ROSE_ASSERT(symbol != NULL );
22320 ROSE_ASSERT(isSgVariableSymbol(symbol));
22321 readOnlySymbols.insert(isSgVariableSymbol(symbol));
22322 }
22323
22324}
22325
22328{
22329 bool result = false;
22330 ROSE_ASSERT(ref != NULL);
22331 ROSE_ASSERT(ref->get_parent() != NULL);
22332 // case 1: ref is used as an operator for & (SgAddressofOp)
22333 // TODO tolerate possible type casting operations in between ?
22334 if (isSgAddressOfOp(ref->get_parent()))
22335 {
22336 result = true;
22337 }
22338 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22339 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22340 {
22341 SgNode* grandparent = ref->get_parent()->get_parent();
22342 ROSE_ASSERT(grandparent);
22343 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22344 {
22345 // find which parameter ref is in SgExpressionPtrList
22346
22347 // DQ (8/12/2020): This is a compiler warning where it is used below in comparision between signed and unsigned types.
22348 // int param_index = 0;
22349 size_t param_index = 0;
22350
22351 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22352 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22353 for (; iter!=expList.end(); iter++)
22354 {
22355 if (*iter == ref)
22356 break;
22357 else
22358 param_index++;
22359 }
22360 // find the parameter type of the corresponding function declaration
22361 SgExpression* func_exp = isSgFunctionCallExp(grandparent)->get_function();
22362 ROSE_ASSERT (func_exp);
22363 SgFunctionRefExp * funcRef = isSgFunctionRefExp(func_exp);
22364 if (funcRef) // regular functions
22365 {
22366 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22367 SgInitializedNamePtrList nameList = funcDecl->get_args();
22368 //TODO tolerate typedef chains
22369 // printf() has only two arguments to express variable arguments.
22370 // The third argument index ==2 will be out of bounds for nameList[index]
22371 // So we must check the bound first.
22372 if (param_index >= nameList.size() ||isSgTypeEllipse(nameList[param_index]->get_type()) )
22373 {
22374 if (isSgReferenceType(ref))
22375 result = true;
22376 }
22377 else // now within the bound: two situations,
22378 if (isSgReferenceType(nameList[param_index]->get_type()))
22379 {
22380 result = true;
22381 }
22382 } //It also could be a dot or arrow expression where its right hand operand is a SgMemberFunctionRefExp
22383 else if (isSgDotExp (func_exp) || isSgArrowExp(func_exp)) // ArrowExp TODO
22384 {
22385 SgBinaryOp* binOp = isSgBinaryOp(func_exp);
22386 ROSE_ASSERT (binOp);
22387 SgMemberFunctionRefExp* mfuncRef = isSgMemberFunctionRefExp(binOp->get_rhs_operand_i());
22388 ROSE_ASSERT (mfuncRef);
22389 SgMemberFunctionDeclaration * mfuncDecl = isSgMemberFunctionSymbol (mfuncRef->get_symbol())->get_declaration();
22390 ROSE_ASSERT (mfuncDecl);
22391 SgInitializedNamePtrList nameList = mfuncDecl->get_args();
22392 //TODO tolerate typedef chains
22393 if (isSgReferenceType(nameList[param_index]->get_type()))
22394 {
22395 result = true;
22396 }
22397 }
22398
22399 }
22400 }
22401 return result;
22402}
22403
22404
22406void SageInterface::collectUseByAddressVariableRefs (const SgStatement* s, std::set<SgVarRefExp* >& varSetB)
22407{
22408 Rose_STL_Container <SgNode*> var_refs = NodeQuery::querySubTree (const_cast<SgStatement *> (s), V_SgVarRefExp);
22409
22410 Rose_STL_Container<SgNode*>::iterator iter = var_refs.begin();
22411 for (; iter!=var_refs.end(); iter++)
22412 {
22413 SgVarRefExp* ref = isSgVarRefExp(*iter);
22414 ROSE_ASSERT(ref != NULL);
22415 ROSE_ASSERT(ref->get_parent() != NULL);
22416#if 0
22417 // case 1: ref is used as an operator for & (SgAddressofOp)
22418 // TODO tolerate possible type casting operations in between ?
22419 if (isSgAddressOfOp(ref->get_parent()))
22420 {
22421 varSetB.insert(ref);
22422 }
22423 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22424 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22425 {
22426 SgNode* grandparent = ref->get_parent()->get_parent();
22427 ROSE_ASSERT(grandparent);
22428 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22429 {
22430 // find which parameter ref is in SgExpressionPtrList
22431 int param_index =0;
22432 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22433 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22434 for (; iter!=expList.end(); iter++)
22435 {
22436 if (*iter == ref)
22437 break;
22438 else
22439 param_index++;
22440 }
22441 // find the parameter type of the corresponding function declaration
22442 SgFunctionRefExp * funcRef = isSgFunctionRefExp(isSgFunctionCallExp(grandparent)->get_function());
22443 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22444 SgInitializedNamePtrList nameList = funcDecl->get_args();
22445 //TODO tolerate typedef chains
22446 if (isSgReferenceType(nameList[param_index]->get_type()))
22447 {
22448 varSetB.insert(ref);
22449 }
22450 }
22451 }
22452#endif
22454 varSetB.insert(ref);
22455 }
22456}
22457
22458#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22460LivenessAnalysis * SageInterface::call_liveness_analysis(SgProject* project, bool debug/*=false*/)
22461{
22462 // We expect this function to be called multiple times but always return the result generated from the first execution.
22463 static LivenessAnalysis* liv = NULL; // one instance
22464 if (liv!=NULL)
22465 return liv;
22466
22467 static DFAnalysis * defuse = NULL; // only one instance
22468 // Prepare def-use analysis
22469 if (defuse==NULL)
22470 {
22471 ROSE_ASSERT(project != NULL);
22472 defuse = new DefUseAnalysis(project);
22473 }
22474
22475 ROSE_ASSERT(defuse != NULL);
22476 defuse->run(debug);
22477
22478 if (debug)
22479 defuse->dfaToDOT();
22480
22481 //Prepare variable liveness analysis
22482 liv = new LivenessAnalysis(debug,(DefUseAnalysis*)defuse);
22483 ROSE_ASSERT(liv != NULL);
22484
22485 std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions;
22486 NodeQuerySynthesizedAttributeType vars =
22487 NodeQuery::querySubTree(project, V_SgFunctionDefinition);
22488 NodeQuerySynthesizedAttributeType::const_iterator i;
22489 bool abortme=false;
22490 // run liveness analysis on each function body
22491 for (i= vars.begin(); i!=vars.end();++i)
22492 {
22493 SgFunctionDefinition* func = isSgFunctionDefinition(*i);
22494 ROSE_ASSERT(func != NULL);
22495 if (debug)
22496 {
22497 std::string name = func->class_name();
22498 string funcName = func->get_declaration()->get_qualified_name().str();
22499 cout<< " .. running liveness analysis for function: " << funcName << endl;
22500 }
22501 FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
22502 // propagate results to statement level
22503 liv->fixupStatementsINOUT(func);
22504 if (rem_source.getNode()!=NULL)
22505 dfaFunctions.push_back(rem_source);
22506 if (abortme)
22507 break;
22508 } // end for ()
22509 if(debug)
22510 {
22511 cout << "Writing out liveness analysis results into var.dot... " << endl;
22512 std::ofstream f2("var.dot");
22513 dfaToDot(f2, string("var"), dfaFunctions, (DefUseAnalysis*)defuse, liv);
22514 f2.close();
22515 }
22516 if (abortme) {
22517 cerr<<"Error: Liveness analysis is ABORTING ." << endl;
22518 ROSE_ABORT();
22519 }
22520 return liv;
22521 //return !abortme;
22522}
22523#endif
22524
22525#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22527void SageInterface::getLiveVariables(LivenessAnalysis * liv, SgForStatement* loop, std::set<SgInitializedName*>& liveIns, std::set<SgInitializedName*> & liveOuts)
22528{
22529 ROSE_ASSERT(liv != NULL);
22530 ROSE_ASSERT(loop != NULL);
22531 SgForStatement *forstmt = loop;
22532 std::vector<SgInitializedName*> liveIns0, liveOuts0; // store the original one
22533
22534 // Jeremiah's hidden constructor parameter value '2' to grab the node for forStmt's
22535 // Several CFG nodes are used for the same SgForStatement, only one of the is needed.
22536 // We have to check the full control flow graph to find all SgForStatement's nodes,
22537 // check the index numbers from 0 , find the one with two out edges (true, false)
22538 // The CFG node should have a caption like" <SgForStatement> @ 8: 1",
22539 // which means this is a CFG node for a for statement at source line 8, with an index 1.
22540 // For SgForStatement, there are 5 cfg nodes, 0 and 4 are for begin and end CFG nodes
22541 // 1: after init statement, 2: after test expression (the remaining one after filtering), 3: before increment
22542 CFGNode cfgnode(forstmt,2);
22543 FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (cfgnode);
22544 // This one does not return the one we want even its getNode returns the
22545 // right for statement
22546 //FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (forstmt->cfgForBeginning());
22547 ROSE_ASSERT(filternode.getNode()==forstmt);
22548
22549 // Check out edges
22550 vector<FilteredCFGEdge < IsDFAFilter > > out_edges = filternode.outEdges();
22551 ROSE_ASSERT(out_edges.size()==2);
22552 vector<FilteredCFGEdge < IsDFAFilter > >::iterator iter= out_edges.begin();
22553
22554 for (; iter!=out_edges.end();iter++)
22555 {
22556 FilteredCFGEdge < IsDFAFilter > edge= *iter;
22557 //SgForStatement should have two outgoing edges based on the loop condition
22558 // one true(going into the loop body) and one false (going out the loop)
22559 //x. Live-in (loop) = live-in (first-stmt-in-loop)
22560 if (edge.condition()==eckTrue)
22561 {
22562 SgNode* firstnode= edge.target().getNode();
22563 liveIns0 = liv->getIn(firstnode);
22564 // cout<<"Live-in variables for loop:"<<endl;
22565 for (std::vector<SgInitializedName*>::iterator iter = liveIns0.begin();
22566 iter!=liveIns0.end(); iter++)
22567 {
22568 // SgInitializedName* name = *iter;
22569 liveIns.insert(*iter);
22570 // cout<< name->get_qualified_name().getString()<<endl;
22571 }
22572 }
22573 //x. live-out(loop) = live-in (first-stmt-after-loop)
22574 else if (edge.condition()==eckFalse)
22575 {
22576 SgNode* firstnode= edge.target().getNode();
22577 liveOuts0 = liv->getIn(firstnode);
22578 // cout<<"Live-out variables for loop:"<<endl;
22579 for (std::vector<SgInitializedName*>::iterator iter = liveOuts0.begin();
22580 iter!=liveOuts0.end(); iter++)
22581 {
22582 // SgInitializedName* name = *iter;
22583 // cout<< name->get_qualified_name().getString()<<endl;
22584 liveOuts.insert(*iter);
22585 }
22586 }
22587 else
22588 {
22589 cerr<<"Unexpected CFG out edge type for SgForStmt!"<<endl;
22590 ROSE_ABORT();
22591 }
22592 } // end for (edges)
22593
22594}
22595#endif
22596
22597//Check if two references form an idiom like: x= x op expr, x = expr op x (except for subtraction)
22598static bool isAssignReduction (SgVarRefExp* ref_exp1, SgVarRefExp* ref_exp2, OmpSupport::omp_construct_enum& optype)
22599{
22600 bool isReduction = false;
22601 // Sanity check
22602 ROSE_ASSERT (ref_exp1!= NULL);
22603 ROSE_ASSERT (ref_exp2!= NULL);
22604 ROSE_ASSERT (ref_exp1-> get_symbol() == ref_exp2-> get_symbol());
22605 // must be scalar type
22606 ROSE_ASSERT (SageInterface::isScalarType(ref_exp1-> get_symbol()->get_type() ) );
22607
22610 if (stmt != stmt2) return false; // early return false;
22611
22612 // must be assignment statement using
22613 // x= x op expr, x = expr op x (except for subtraction)
22614 // one reference on left hand, the other on the right hand of assignment expression
22615 // the right hand uses associative operators +, *, -, &, ^ ,|, &&, ||
22616 SgExprStatement* exp_stmt = isSgExprStatement(stmt);
22617 if (exp_stmt && isSgAssignOp(exp_stmt->get_expression()))
22618 {
22619 SgExpression* assign_lhs=NULL, * assign_rhs =NULL;
22620 assign_lhs = isSgAssignOp(exp_stmt->get_expression())->get_lhs_operand();
22621 assign_rhs = isSgAssignOp(exp_stmt->get_expression())->get_rhs_operand();
22622 ROSE_ASSERT(assign_lhs && assign_rhs);
22623 // x must show up in both lhs and rhs in any order:
22624 // e.g.: ref1 = ref2 op exp or ref2 = ref1 op exp
22625 if (((assign_lhs==ref_exp1)&&SageInterface::isAncestor(assign_rhs,ref_exp2))
22626 ||((assign_lhs==ref_exp2)&&SageInterface::isAncestor(assign_rhs,ref_exp1)))
22627 {
22628 // assignment's rhs must match the associative binary operations
22629 // +, *, -, &, ^ ,|, &&, ||
22630 SgBinaryOp * binop = isSgBinaryOp(assign_rhs);
22631 if (binop!=NULL){
22632 SgExpression* op_lhs = binop->get_lhs_operand();
22633 SgExpression* op_rhs = binop->get_rhs_operand();
22634
22635 // double check that the binary expression has either ref1 or ref2 as one operand
22636 if( !((op_lhs==ref_exp1)||(op_lhs==ref_exp2))
22637 && !((op_rhs==ref_exp1)||(op_rhs==ref_exp2)))
22638 return false; // early return false;
22639
22640 bool isOnLeft = false; // true if it has form (refx op exp), instead (exp or refx)
22641 if ((op_lhs==ref_exp1)|| // TODO might have in between !!
22642 (op_lhs==ref_exp2))
22643 isOnLeft = true;
22644 switch (binop->variantT())
22645 {
22646 case V_SgAddOp:
22647 {
22648 optype = OmpSupport::e_reduction_plus;
22649 isReduction = true;
22650 break;
22651 }
22652 case V_SgMultiplyOp:
22653 {
22654 optype = OmpSupport::e_reduction_mul;
22655 isReduction = true;
22656 break;
22657 }
22658 case V_SgSubtractOp: // special handle here!!
22659 {
22660 optype = OmpSupport::e_reduction_minus;
22661 if (isOnLeft) // cannot allow (exp - x)a
22662 {
22663 isReduction = true;
22664 }
22665 break;
22666 }
22667 case V_SgBitAndOp:
22668 {
22669 optype = OmpSupport::e_reduction_bitand ;
22670 isReduction = true;
22671 break;
22672 }
22673 case V_SgBitXorOp:
22674 {
22675 optype = OmpSupport::e_reduction_bitxor;
22676 isReduction = true;
22677 break;
22678 }
22679 case V_SgBitOrOp:
22680 {
22681 optype = OmpSupport::e_reduction_bitor;
22682 isReduction = true;
22683 break;
22684 }
22685 case V_SgAndOp:
22686 {
22687 optype = OmpSupport::e_reduction_logand;
22688 isReduction = true;
22689 break;
22690 }
22691 case V_SgOrOp:
22692 {
22693 optype = OmpSupport::e_reduction_logor;
22694 isReduction = true;
22695 break;
22696 }
22697 default:
22698 break;
22699 }
22700 } // end matching associative operations
22701 }
22702 } // end if assignop
22703 return isReduction;
22704}
22705// A helper function for reduction recognition
22706// check if two references to the same variable form a reduction idiom using if-statement
22707// example 1: if (array[i]> maxV) maxV = array[i]
22708// example 2: if (array[i]< minV) minV = array[i]
22709// If it matches, return true and the reduction operator type
22710static bool isIfReduction(SgVarRefExp* ref1, SgVarRefExp* ref2, OmpSupport::omp_construct_enum& optype)
22711{
22712 bool matchStmt1 = false;
22713 bool matchStmt2 = false;
22714
22715 //TODO: ensure ref1, ref2 are ordered as pre-order manner in AST
22716 // SgExpression* reduction_var_ref = NULL;
22717 // SgExpression* source_var_ref = NULL; //array[i] is the source var ref
22718
22719 // Sanity check
22720 ROSE_ASSERT (ref1 != NULL);
22721 ROSE_ASSERT (ref2 != NULL);
22722 ROSE_ASSERT (ref1-> get_symbol() == ref2-> get_symbol());
22723 // must be scalar type
22724 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22725
22728
22729 //early return if the same stmt
22730 if (stmt1 == stmt2) return false;
22731
22732 // check stmt2 first. It is easier.
22733 // stmt2 should be an assignment stmt like:
22734 // reduction_variable = else;
22735 // minV = array[i];
22736 SgExpression* lhs2 = NULL;
22737 SgExpression* rhs2 = NULL;
22738 if (SageInterface::isAssignmentStatement (stmt2, &lhs2, &rhs2 ))
22739 {
22740 // lhs2 must be ref2
22741 if (lhs2 == ref2 )
22742 {
22743 matchStmt2 = true;
22744 // reduction_var_ref = lhs2;
22745 // source_var_ref= rhs2;
22746 }
22747 } // end assignment stmt
22748
22749 // stmt1 should be a if-stmt's conditional expression stmt
22750 // and its body should be stmt2
22751 if (SgExprStatement* if_cond_stmt = isSgExprStatement(stmt1))
22752 {
22753 bool matchBody = false;
22754 bool matchCondition= false;
22755 if (SgIfStmt * if_stmt = isSgIfStmt (if_cond_stmt->get_parent()) )
22756 {
22757 if (SgStatement* body = if_stmt->get_true_body())
22758 {
22759 if (SgBasicBlock* block = isSgBasicBlock (body))
22760 {
22761 // stmt2 must be the only child of the if true body
22762 ROSE_ASSERT(stmt2 != NULL);
22763 if ( ((block->get_statements()).size() == 1) && stmt2->get_scope() == block )
22764 matchBody = true;
22765 }
22766 else
22767 {
22768 if (body == stmt2)
22769 matchBody = true;
22770 }
22771 } // body match test
22772
22773 // match condition SgExprStatement ref1 SgLessThanOp source_var
22774 if (SgExprStatement* cond_exp_stmt = isSgExprStatement (if_stmt->get_conditional()) )
22775 {
22776 SgExpression* cond_exp = cond_exp_stmt->get_expression();
22777 if (SgBinaryOp * binop = isSgBinaryOp (cond_exp))
22778 {
22779 if (ref1 == binop->get_lhs_operand_i())
22780 {
22781 // minV > array[i] ;
22782 if (isSgLessThanOp (binop))
22783 {
22784 optype = OmpSupport::e_reduction_max;
22785 matchCondition= true;
22786 }
22787 else if (isSgGreaterThanOp(binop))
22788 {
22789 optype = OmpSupport::e_reduction_min;
22790 matchCondition= true;
22791 }
22792 }
22793 else if ( ref1 == binop->get_rhs_operand_i() )
22794 {
22795 // array[i] < minV
22796 if (isSgLessThanOp (binop))
22797 {
22798 optype = OmpSupport::e_reduction_min;
22799 matchCondition= true;
22800 }
22801 else if (isSgGreaterThanOp(binop))
22802 {
22803 optype = OmpSupport::e_reduction_max;
22804 matchCondition= true;
22805 }
22806 }
22807 } // end if binary op
22808 // TODO the source_var should match the source_var from stmt2
22809 }
22810 }
22811 matchStmt1 = matchBody && matchCondition;
22812 } // end if-stmt
22813
22814
22815 return (matchStmt2 && matchStmt1);
22816}
22817
22818// check if a var ref is a form of
22819// --x, x--, ++x, x++
22820// x+= .., x-= ..., etc.
22821// The reduction variable appears only once in the reduction idiom.
22822static bool isSingleAppearanceReduction(SgVarRefExp* ref1, OmpSupport::omp_construct_enum& optype )
22823{
22824 bool isReduction = false;
22825
22826 ROSE_ASSERT (ref1 != NULL);
22827 // must be scalar type
22828 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22829
22831
22832 if (isSgExprStatement(stmt))
22833 {
22834 SgExpression* exp = isSgExprStatement(stmt)->get_expression();
22835 SgExpression* binop = isSgBinaryOp(exp);
22836 if (isSgPlusPlusOp(exp)) // x++ or ++x
22837 { // Could have multiple reduction clause with different operators!!
22838 // So the variable list is associated with each kind of operator
22839 optype = OmpSupport::e_reduction_plus;
22840 isReduction = true;
22841 }
22842 else if (isSgMinusMinusOp(exp)) // x-- or --x
22843 {
22844 optype = OmpSupport::e_reduction_minus;
22845 isReduction = true;
22846 }
22847 else
22848 // x binop= expr where binop is one of + * - & ^ |
22849 // x must be on the left hand side
22850 if (binop!=NULL) {
22851 SgExpression* lhs= isSgBinaryOp(exp)->get_lhs_operand ();
22852 if (lhs==ref1)
22853 {
22854 switch (exp->variantT())
22855 {
22856 case V_SgPlusAssignOp:
22857 {
22858 optype = OmpSupport::e_reduction_plus;
22859 isReduction = true;
22860 break;
22861 }
22862 case V_SgMultAssignOp:
22863 {
22864 optype = OmpSupport::e_reduction_mul;
22865 isReduction = true;
22866 break;
22867 }
22868 case V_SgMinusAssignOp:
22869 {
22870 optype = OmpSupport::e_reduction_minus;
22871 isReduction = true;
22872 break;
22873 }
22874 case V_SgAndAssignOp:
22875 {
22876 optype = OmpSupport::e_reduction_bitand;
22877 isReduction = true;
22878 break;
22879 }
22880 case V_SgXorAssignOp:
22881 {
22882 optype = OmpSupport::e_reduction_bitxor;
22883 isReduction = true;
22884 break;
22885 }
22886 case V_SgIorAssignOp:
22887 {
22888 optype = OmpSupport::e_reduction_bitor;
22889 isReduction = true;
22890 break;
22891 }
22892 default:
22893 break;
22894 } // end
22895 }// end if on left side
22896 }
22897 }
22898 return isReduction;
22899}
22900
22902/* This code is refactored from project/autoParallelization/autoParSupport.C
22903 std::vector<SgInitializedName*>
22904 RecognizeReduction(SgNode *loop, OmpSupport::OmpAttribute* attribute, std::vector<SgInitializedName*>& candidateVars/)
22905 * Algorithms:
22906 * for each scalar candidate which are both live-in and live-out for the loop body
22907 * (We don't use liveness analysis here for simplicity)
22908 * and which is not the loop invariant variable (loop index).
22909 * Consider those with only 1 or 2 references
22910 * 1 reference
22911 * the operation is one of x++, ++x, x--, --x, x binop= expr
22912 * 2 references belonging to the same operation
22913 * operations: one of x= x op expr, x = expr op x (except for subtraction)
22914 * The reduction description from the OpenMP 3.0 specification.
22915 * x is not referenced in exp
22916 * expr has scalar type (no array, objects etc)
22917 * x: scalar only, aggregate types (including arrays), pointer types and reference types may not appear in a reduction clause.
22918 * op is not an overloaded operator, but +, *, -, &, ^ ,|, &&, ||
22919 * binop is not an overloaded operator, but: +, *, -, &, ^ ,|
22920 */
22921void SageInterface::ReductionRecognition(SgForStatement* loop, std::set< std::pair <SgInitializedName*, OmpSupport::omp_construct_enum > > & results)
22922{
22923 //x. Collect variable references of scalar types as candidates, excluding loop index
22924 SgInitializedName* loopindex;
22925 if (!(isCanonicalForLoop(loop, &loopindex)))
22926 {
22927// cerr<<"Skip reduction recognition for non-canonical for loop"<<endl;
22928 return;
22929 }
22930 std::set<SgInitializedName*> candidateVars; // scalar variables used within the loop
22931 //Store the references for each scalar variable
22932 std::map <SgInitializedName*, vector<SgVarRefExp* > > var_references;
22933
22934 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(loop, V_SgVarRefExp);
22935 SgStatement* lbody= loop->get_loop_body();
22936 ROSE_ASSERT(lbody != NULL);
22937 Rose_STL_Container<SgNode*>::iterator iter = reflist.begin();
22938 for (; iter!=reflist.end(); iter++)
22939 {
22940 SgVarRefExp* ref_exp = isSgVarRefExp(*iter);
22941 SgInitializedName* initname= ref_exp->get_symbol()->get_declaration();
22942 // candidates are of scalar types and are not the loop index variable
22943 // And also should be live-in:
22944 // not declared locally (var_scope equal or lower than loop body )
22945 // or redefined (captured by ref count)
22946 SgScopeStatement* var_scope = initname->get_scope();
22947 ROSE_ASSERT(var_scope != NULL);
22948 if ((isScalarType(initname->get_type())) &&(initname !=loopindex)
22949 && !(SageInterface::isAncestor(lbody, var_scope)||(lbody==var_scope)))
22950 {
22951 candidateVars.insert(initname);
22952 var_references[initname].push_back(ref_exp);
22953 }
22954 }
22955
22956 //Consider variables referenced at most twice
22957 std::set<SgInitializedName*>::iterator niter=candidateVars.begin();
22958 for (; niter!=candidateVars.end(); niter++)
22959 {
22960 SgInitializedName* initname = *niter;
22961 bool isReduction = false;
22962 OmpSupport::omp_construct_enum optype;
22963 // referenced once only
22964 if (var_references[initname].size()==1)
22965 {
22966 mlog[Sawyer::Message::Common::DEBUG] << "Debug: SageInterface::ReductionRecognition() A candidate used once:"<<initname->get_name().getString()<<endl;
22967 SgVarRefExp* ref_exp = *(var_references[initname].begin());
22968 if (isSingleAppearanceReduction (ref_exp, optype))
22969 isReduction = true;
22970 }
22971 // referenced twice within a same statement
22972 else if (var_references[initname].size()==2)
22973 {
22974 mlog[Sawyer::Message::Common::DEBUG] << "Debug: A candidate used twice:"<<initname->get_name().getString()<<endl;
22975 SgVarRefExp* ref_exp1 = *(var_references[initname].begin());
22976 SgVarRefExp* ref_exp2 = *(++var_references[initname].begin());
22977 // TODO: recognize maxV = array[i]>maxV? array[i]:maxV // this can be normalized to if () stmt
22978 // TODO: recognize maxV = max (maxV, array[i])
22979 if (isAssignReduction (ref_exp1, ref_exp2, optype) || isIfReduction (ref_exp1, ref_exp2, optype) )
22980 {
22981 isReduction = true;
22982 }
22983
22984 }// end referenced twice
22985
22986 if (isReduction)
22987 results.insert(make_pair(initname,optype));
22988 }// end for ()
22989}
22990
22993{
22994 ROSE_ASSERT(r!=NULL);
22995#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22996 ConstantFolding::constantFoldingOptimization(r,false);
22997#endif
22998}
22999
23002{
23004 {
23005 public:
23006 virtual void visit (SgNode * n)
23007 {
23008 SgExpression* exp = isSgExpression(n);
23009 if (exp)
23010 {
23011 string u_name = generateUniqueName(exp,false)+"-"+exp->class_name();
23012 AstAttribute * name_attribute = new UniqueNameAttribute(u_name);
23013 ROSE_ASSERT (name_attribute != NULL);
23014 exp->addNewAttribute("UniqueNameAttribute",name_attribute);
23015 }
23016 }
23017 };
23018 visitorTraversal exampleTraversal;
23019 //Sriram FIX: should traverse using the traverse function
23020 // exampleTraversal.traverseInputFiles(project,preorder);
23021 exampleTraversal.traverse(project, preorder);
23022}
23023
23024
23025 //
23026 // wrap free-standing function body in another function
23027
23029 {
23030 ROSE_ASSERT(vardecl.get_variables().size());
23031
23032 return *vardecl.get_variables().front();
23033 }
23034
23035#if 0
23036 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23037 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23038
23046 static
23048 cloneParameterList(const SgFunctionParameterList& params, SgFunctionDefinition* fundef = NULL)
23049 {
23050 namespace SB = SageBuilder;
23051
23052 SgFunctionParameterList& copy = *SB::buildFunctionParameterList();
23053 const SgInitializedNamePtrList& orig_decls = params.get_args();
23054
23055 std::transform( orig_decls.begin(), orig_decls.end(), sg::sage_inserter(copy), sg::InitNameCloner(copy, fundef) );
23056
23057 return copy;
23058 }
23059#endif
23060
23061#if 0
23062 // DQ (2/16/2017): This is a static function that is defined but not used in this file (compiler waring).
23063
23065 static
23066 void swapDefiningElements(SgFunctionDeclaration& ll, SgFunctionDeclaration& rr)
23067 {
23068 // swap definitions
23069 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_definition, &SgFunctionDeclaration::set_definition);
23070 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_parameterList, &SgFunctionDeclaration::set_parameterList);
23071
23072 // \todo do we need to swap also exception spec, decorator_list, etc. ?
23073 }
23074#endif
23075
23076#if 0
23077 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23078 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23079
23080 std::pair<SgStatement*, SgInitializedName*>
23081 SageInterface::wrapFunction(SgFunctionDeclaration& definingDeclaration, SgName newName)
23082 {
23083 namespace SB = SageBuilder;
23084
23085 // handles freestanding functions only
23086 ROSE_ASSERT(typeid(SgFunctionDeclaration) == typeid(definingDeclaration));
23087 ROSE_ASSERT(definingDeclaration.get_definingDeclaration() == &definingDeclaration);
23088
23089 // clone function parameter list
23090 SgFunctionParameterList& param_list = cloneParameterList(*definingDeclaration.get_parameterList());
23091
23092 // create new function definition/declaration in the same scope
23093 SgScopeStatement* containing_scope = definingDeclaration.get_scope();
23094 SgType* result_type = definingDeclaration.get_type()->get_return_type();
23095 SgExprListExp* decorators = deepCopy( definingDeclaration.get_decoratorList() );
23096
23097 // DQ (4/9/2015): Suggested fix for this function.
23098 // SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope, decorators);
23099 SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope);
23100
23101 SgFunctionDefinition* wrapperdef = wrapperfn->get_definition();
23102 ROSE_ASSERT(wrapperdef);
23103
23104 // copy the exception specification
23105 wrapperfn->set_exceptionSpecification(definingDeclaration.get_exceptionSpecification());
23106
23107 // swap the original's function definition w/ the clone's function def
23108 // and the original's func parameter list w/ the clone's parameters
23109 swapDefiningElements(definingDeclaration, *wrapperfn);
23110
23111 // call original function from within the defining decl's body
23112 SgBasicBlock* body = wrapperdef->get_body();
23113 SgExprListExp* args = SB::buildExprListExp();
23114 SgInitializedNamePtrList& param_decls = param_list.get_args();
23115
23116 std::transform( param_decls.begin(), param_decls.end(), sg::sage_inserter(*args), sg::VarRefBuilder(*wrapperdef) );
23117
23118 SgFunctionCallExp* callWrapped = SB::buildFunctionCallExp( newName, result_type, args, body );
23119 SgInitializedName* resultName = NULL;
23120 SgStatement* callStatement = NULL;
23121
23122 // \todo skip legal qualifiers that could be on top of void
23123 if (!isSgTypeVoid(result_type))
23124 {
23125 // add call to original function and assign result to variable
23126 SgVariableDeclaration* res = SB::buildVariableDeclaration( "res", result_type, SB::buildAssignInitializer(callWrapped), body );
23127 SgVarRefExp* resref = SB::buildVarRefExp( res );
23128
23129 appendStatement(res, body);
23130
23131 // add return statement, returning result
23132 resultName = &getFirstVariable(*res);
23133 callStatement = res;
23134
23135 appendStatement(SB::buildReturnStmt(resref), body);
23136 }
23137 else
23138 {
23139 // add function call statement to original function
23140 callStatement = SB::buildExprStatement(callWrapped);
23141 appendStatement(callStatement, body);
23142 }
23143
23144 ROSE_ASSERT(callStatement);
23145
23146 // create non defining declaration
23147 SgExprListExp* decorator_proto = deepCopy( decorators );
23148 SgFunctionDeclaration* wrapperfn_proto = SB::buildNondefiningFunctionDeclaration(wrapperfn, containing_scope, decorator_proto);
23149
23150 // add the new functions at the proper location of the surrounding scope
23151 insertStatementBefore(&definingDeclaration, wrapperfn_proto);
23152 insertStatementAfter (&definingDeclaration, wrapperfn);
23153
23154 return std::make_pair(callStatement, resultName);
23155 }
23156#endif
23157
23158 //
23159 // flatten C/C++ array dimensions
23160 namespace
23161 {
23162 struct VarrefBuilder
23163 {
23164 virtual SgVarRefExp* get() const = 0;
23165
23166 static
23167 SgVarRefExp* build(const SgVarRefExp& n)
23168 {
23169 return SageInterface::deepCopy(&n);
23170 }
23171
23172 static
23174 {
23175 SgScopeStatement* scope = sg::ancestor<SgStatement>(n).get_scope();
23176
23177 return SageBuilder::buildVarRefExp(&n, scope);
23178 }
23179 };
23180
23181 template <class AstNode>
23182 struct VarrefCreator : VarrefBuilder
23183 {
23184 AstNode& origin;
23185
23186 explicit
23187 VarrefCreator(AstNode& orig)
23188 : origin(orig)
23189 {}
23190
23191 SgVarRefExp* get() const { return VarrefBuilder::build(origin); }
23192 };
23193
23194 template <class AstNode>
23195 VarrefCreator<AstNode>
23196 varrefCreator(AstNode& n)
23197 {
23198 return VarrefCreator<AstNode>(n);
23199 }
23200
23201 SgExpression* create_mulop(SgExpression* lhs, const SgExpression* rhs)
23202 {
23203 namespace SB = SageBuilder;
23204 namespace SI = SageInterface;
23205
23206 // we own the lhs (intermediate result),
23207 // but we do not own the rhs (another top-level expression)
23208 return SB::buildMultiplyOp(lhs, SI::deepCopy(rhs));
23209 }
23210
23211 std::pair<std::vector<SgExpression*>, SgType*>
23212 get_C_array_dimensions_aux(const SgArrayType& arr_type)
23213 {
23214 namespace SB = SageBuilder;
23215 namespace SI = SageInterface;
23216
23217 const SgArrayType* arrtype = &arr_type;
23218 std::vector<SgExpression*> indices;
23219 SgType* undertype = NULL;
23220
23221 // \todo when get_index() does not return a nullptr anymore
23222 // the condition can be removed
23223 if (arrtype->get_index() == NULL)
23224 {
23225 indices.push_back(SB::buildNullExpression());
23226 undertype = arrtype->get_base_type();
23227 arrtype = isSgArrayType(undertype);
23228 }
23229
23230 while (arrtype)
23231 {
23232 SgExpression* indexexpr = arrtype->get_index();
23233 ROSE_ASSERT(indexexpr);
23234
23235 indices.push_back(SI::deepCopy(indexexpr));
23236 undertype = arrtype->get_base_type();
23237 arrtype = isSgArrayType(undertype);
23238 }
23239
23240 ROSE_ASSERT((!indices.empty()) && undertype);
23241 return std::make_pair(indices, undertype);
23242 }
23243
23245 std::vector<SgExpression*>
23246 get_C_array_dimensions_aux(const SgArrayType& arrtype, const VarrefBuilder& varrefBuilder)
23247 {
23248 namespace SB = SageBuilder;
23249
23250 std::pair<std::vector<SgExpression*>, SgType*> res = get_C_array_dimensions_aux(arrtype);
23251 const std::vector<SgExpression*>::iterator first = res.first.begin();
23252
23253 // if the first dimension was open, create the expression for it
23254 if (isSgNullExpression(*first))
23255 {
23256 // handle implicit first dimension for array initializers
23257 // for something like
23258 // int p[][2][3] = {{{ 1, 2, 3 }, { 4, 5, 6 }}}
23259 // we can calculate the first dimension as
23260 // sizeof( p ) / ( sizeof( int ) * 2 * 3 )
23261
23262 const std::vector<SgExpression*>::iterator aa = first+1;
23263 const std::vector<SgExpression*>::iterator zz = res.first.end();
23264
23265 SgExpression* sz_undertype = SB::buildSizeOfOp(res.second);
23266 SgExpression* denominator = std::accumulate(aa, zz, sz_undertype, create_mulop);
23267 SgSizeOfOp* sz_var = SB::buildSizeOfOp(varrefBuilder.get());
23268 SgExpression* sz = SB::buildDivideOp(sz_var, denominator);
23269
23270 std::swap(*first, sz);
23271 delete sz;
23272 }
23273
23274 return res.first;
23275 }
23276 }
23277
23278 std::vector<SgExpression*>
23280 {
23281 return get_C_array_dimensions_aux(arrtype).first;
23282 }
23283
23284 std::vector<SgExpression*>
23286 {
23287 return get_C_array_dimensions_aux(arrtype, varrefCreator(varref));
23288 }
23289
23290 std::vector<SgExpression*>
23292 {
23293 return get_C_array_dimensions_aux(arrtype, varrefCreator(initname));
23294 }
23295
23296// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23298 {
23299 public:
23300 set<unsigned int> sourceSequenceSet;
23301
23302 void visit ( SgNode* astNode );
23303 };
23304
23305// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23306void
23308 {
23309 Sg_File_Info* fileInfo = astNode->get_file_info();
23310 if (fileInfo != NULL)
23311 {
23312 unsigned int source_sequence_number = fileInfo->get_source_sequence_number();
23313#if 0
23314 printf ("In CollectSourceSequenceNumbers::visit(): source_sequence_number = %" PRIuPTR " \n",source_sequence_number);
23315#endif
23316 sourceSequenceSet.insert(source_sequence_number);
23317 }
23318 }
23319
23320// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23321set<unsigned int>
23323 {
23325
23326 traversal.traverse(astNode,preorder);
23327
23328 return traversal.sourceSequenceSet;
23329
23330 }
23331
23332/*Winnie, loop collapse, collapse nested for loops into one large for loop
23333 * return a SgExprListExp *, which will contain a list of SgVarRefExp * to variables newly created, inserted outside of the
23334 * loop scope, and used inside the loop scope.
23335 * If the target_loop comes with omp target directive, these variables should be added in map in clause in
23336 * transOmpCollpase(..) function in omp_lowering.cpp.
23337 *
23338 * The input loop pointer is changed to the generated collapsed loop after the transformation.
23339 *
23340 *
23341 * Loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
23342 *
23343 * to collapse two level of loops:
23344 * iteration_count_one= (ub1-lb1+1)%step1 ==0?(ub1-lb1+1)/step1: (ub1-lb1+1)/step1+1
23345 * iteration_count_two= (ub2-lb2+1)%step2 ==0?(ub2-lb2+1)/step2: (ub2-lb2+1)/step2+1
23346 * total_iteration_count = iteration_count_one * iteration_count_two
23347 *
23348 * Decide incremental/decremental loop by checking operator of test statement(ub), <=/>=, this is done in isCanonicalForLoop()
23349 *
23350 * Example 1:
23351 * for (int i=lb2;i<ub2;i+=inc2) //incremental
23352 * {
23353 * for (int j=lb1;j>ub1;i+=inc1) //decremental
23354 * {
23355 * for (int l=lb2;l<ub2;l+=inc2) //incremental
23356 * {
23357 * a[i][j][l]=i+j+l;
23358 * }
23359 * }
23360 * }
23361 *
23362 *==> translated output code ==>
23363 * int i_nom_1_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23364 * 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;
23365 * int l_nom_3_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23366 * int final_total_iters = 1 * i_nom_1_total_iters* j_nom_2_total_iters* l_nom_3_total_iters;
23367 * int i_nom_1_interval = j_nom_2_total_iters * (l_nom_3_total_iters* 1);
23368 * int j_nom_2_interval = l_nom_3_total_iters * 1;
23369 * int l_nom_3_interval = 1;
23370 *
23371 * for (int new_index = 0; new_index <= final_total_iters- 1; new_index += 1) {
23372 * i_nom_1 = new_index / i_nom_1_interval* inc2 + lb2;
23373 * int i_nom_1_remainder = new_index % i_nom_1_interval;
23374 * j_nom_2 = -(i_nom_1_remainder / j_nom_2_interval* (inc1 * -1)) + lb1;
23375 * l_nom_3 = i_nom_1_remainder % j_nom_2_interval* inc2 + lb2;
23376 * a[i_nom_1][j_nom_2][l_nom_3] = i_nom_1 + j_nom_2 + l_nom_3;
23377 * }
23378 *
23379 * Example 2 with concrete numbers:
23380 *
23381 * // collapse the following two level of for loops:
23382 * for (i=1; i<=9; i+=1) //incremental for loop
23383 * {
23384 * for(j=10; j>=1; j+=-2) //decremental for loop
23385 * {
23386 * a[i][j]=i+j;
23387 * }
23388 * }
23389 * // it becomes
23390 * // total iteration count = ((9 - 1 + 1)/1) * ((10 - 1 + 1)/2) = 45
23391 * // ub = 45
23392 * // lb = 0
23393 *
23394 * int i_nom_1_total_iters = 9;
23395 * int j_nom_1_total_iters = 5; // 10 % (-2 * -1) == 0 ? 10 / (-2 * -1) : 10 /(-2 * -1) + 1;
23396 * int final_total_iters = 45; // i_nom_1_total_iters * j_nom_2_total_iters;
23397 *
23398 * int i_nom_1_interval = 5;
23399 *
23400 * for (z=0; z<=44; z+=1)
23401 * {
23402 * i_nom_1 = z / 5 + 1;
23403 * j_nom_2 = -(z % 5 * 2) + 10;
23404 * a[i_nom_1][j_nom_2]=i_nom_1 + j_nom_2;
23405 * }
23406 * // for the generated loop, a few compiler generated variables are introduced
23407 * final_total_iters for the collapsed loop
23408 * i_interval for each of the n-1 loops
23409 **
23410*/
23411
23412#ifndef USE_ROSE
23414{
23415#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23416 //Handle 0 and 1, which means no collapsing at all
23417 if (collapsing_factor <= 1)
23418 return NULL;
23419
23420 SgExprListExp * new_var_list = buildExprListExp(); //expression list contains all the SgVarRefExp * to variables that need to be added in the mapin clause
23421
23422 /*
23423 *step 1: grab the target loops' header information
23424 */
23425 SgForStatement *& target_loop = loop;
23426
23427 // we use global scope to help generate unique variable name later
23428 // local scope-based unique names may cause conflicts if the declarations are moved around (in OpenMP target data promotion)
23429 SgGlobal* global_scope = getGlobalScope (loop);
23430 ROSE_ASSERT (global_scope != NULL);
23431 SgInitializedName** ivar = new SgInitializedName*[collapsing_factor];
23432 SgExpression** lb = new SgExpression*[collapsing_factor];
23433 SgExpression** ub = new SgExpression*[collapsing_factor];
23434 SgExpression** step = new SgExpression*[collapsing_factor];
23435 SgStatement** orig_body = new SgStatement*[collapsing_factor];
23436
23437 SgExpression** total_iters = new SgExpression*[collapsing_factor]; //Winnie, the real iteration counter in each loop level
23438 SgExpression** interval = new SgExpression*[collapsing_factor]; //Winnie, this will be used to calculate i_nom_1_remainder
23439 bool *isPlus = new bool[collapsing_factor]; //Winnie, a flag indicates incremental or decremental for loop
23440
23441
23442 //Winnie, get loops info first
23443 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(target_loop,V_SgForStatement);
23444 ROSE_ASSERT(loops.size()>=collapsing_factor);
23445
23446 SgForStatement* temp_target_loop = NULL;
23447 SgExpression* temp_range_exp = NULL; //Raw iteration range
23448 SgExpression* temp_range_d_step_exp = NULL; //temp_range_exp / step[i]
23449 SgExpression* temp_condition_1 = NULL; //Check whether temp_range_exp % step[i] == 0
23450 SgExpression* temp_total_iter = NULL;
23451 SgExpression* ub_exp = buildIntVal(1); //Winnie, upbound
23452
23453 /*
23454 * get lb, ub, step information for each level of the loops
23455 * ub_exp is the final iterantion range(starting from 0) after loop collapsing
23456 * total_iters[i], = (ub[i] - lb[i] + 1)/step[i] is the total iter num in each level of loop before loop collapsing
23457 */
23458
23459 SgStatement* parent = isSgStatement(getScope(target_loop)->get_parent()); //Winnie, the scope that include target_loop
23460 ROSE_ASSERT(getScope(target_loop)->get_parent()!= NULL);
23461
23462 SgScopeStatement* scope = isSgScopeStatement(parent); //Winnie, the scope that include target_loop
23463
23464 while(scope == NULL)
23465 {
23466 parent = isSgStatement(parent->get_parent());
23467 scope = isSgScopeStatement(parent);
23468 }
23469
23470 SgStatement* insert_target = findLastDeclarationStatement(scope);
23471 if (insert_target != NULL)
23472 insert_target = getNextStatement(insert_target);
23473 else
23474 insert_target = getFirstStatement(scope);
23475
23476 ROSE_ASSERT(scope != NULL);
23477
23478
23479 for(size_t i = 0; i < collapsing_factor; i ++)
23480 {
23481 temp_target_loop = loops[i];
23482
23483 // normalize the target loop first // adjust to numbering starting from 0
23484 forLoopNormalization(temp_target_loop);
23485
23486 if (!isCanonicalForLoop(temp_target_loop, &ivar[i], &lb[i], &ub[i], &step[i], &orig_body[i], &isPlus[i]))
23487 {
23488 cerr<<"Error in SageInterface::loopCollapsing(): target loop is not canonical."<<endl;
23489 dumpInfo(target_loop);
23490
23491 // release memory
23492 delete[] ivar;
23493 delete[] lb;
23494 delete[] ub;
23495 delete[] step;
23496 delete[] orig_body;
23497 delete[] total_iters;
23498 delete[] interval;
23499 delete[] isPlus;
23500
23501 return NULL;
23502 }
23503
23504 ROSE_ASSERT(ivar[i]&& lb[i] && ub[i] && step[i]);
23505
23506
23507//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]
23508 if(isPlus[i] == true)
23509 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(ub[i]), copyExpression(lb[i])), buildIntVal(1));
23510 else{
23511 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(lb[i]), copyExpression(ub[i])), buildIntVal(1));
23512 step[i] = buildMultiplyOp(step[i], buildIntVal(-1));
23513 }
23514 temp_range_d_step_exp = buildDivideOp(temp_range_exp,copyExpression(step[i]));//(ub[i]-lb[i]+1)/step[i]
23515
23516 temp_condition_1 = buildEqualityOp(buildModOp(copyExpression(temp_range_exp),copyExpression(step[i])),buildIntVal(0)); //(ub[i]-lb[i]+1)%step[i] ==0
23517
23518 temp_total_iter = buildConditionalExp(temp_condition_1,temp_range_d_step_exp, buildAddOp(copyExpression(temp_range_d_step_exp),buildIntVal(1)));
23519
23520 //build variables to store iteration numbers in each loop, simplify the calculation of "final_total_iters"
23521 //insert the new variable (store real iteration number of each level of the loop) before the target loop
23522 string iter_var_name= "_total_iters";
23523 //iter_var_name = ivar[i]->get_name().getString() + iter_var_name + generateUniqueName(temp_total_iter, false);
23524 iter_var_name = "__"+ivar[i]->get_name().getString() + iter_var_name+ generateUniqueVariableName (global_scope,"");
23525 SgVariableDeclaration* total_iter = buildVariableDeclaration(iter_var_name, buildIntType(), buildAssignInitializer(temp_total_iter, buildIntType()), scope);
23526 insertStatementBefore(insert_target, total_iter);
23527 constantFolding (total_iter);
23528 total_iters[i] = buildVarRefExp(iter_var_name, scope);
23529 ub_exp = buildMultiplyOp(ub_exp, total_iters[i]); //Winnie, build up the final iteration range
23530 }
23531
23532
23533 /*
23534 * step 2: build new variables (new_index, final_total_iters, remainders...) for the new loop
23535 */
23536
23537 /*Winnie, build another variable to store final total iteration counter of the loop after collapsing*/
23538 //string final_iter_counter_name = "final_total_iters" + generateUniqueName(ub_exp, false);
23539 string final_iter_counter_name = "__final_total_iters" + generateUniqueVariableName(global_scope,"");
23540 SgVariableDeclaration * final_total_iter = buildVariableDeclaration(final_iter_counter_name, buildIntType(), buildAssignInitializer(copyExpression(ub_exp), buildIntType()), scope);
23541 insertStatementBefore(insert_target, final_total_iter);
23542 ub_exp = buildVarRefExp(final_iter_counter_name, scope);
23543 new_var_list->append_expression(isSgVarRefExp(ub_exp));
23544
23545 /*Winnie, interval[i] will make the calculation of remainders simpler*/
23546 for(unsigned int i = 0; i < collapsing_factor; i++)
23547 {
23548 interval[i] = buildIntVal(1);
23549 for(unsigned int j = collapsing_factor - 1; j > i; j--)
23550 {
23551 interval[i] = buildMultiplyOp(total_iters[j], interval[i]);
23552 }
23553 //string interval_name = ivar[i]->get_name().getString() + "_interval" + generateUniqueName(interval[i], false);
23554 string interval_name = "__"+ ivar[i]->get_name().getString() + "_interval" + generateUniqueVariableName (global_scope,"");
23555 SgVariableDeclaration* temp_interval = buildVariableDeclaration(interval_name, buildIntType(), buildAssignInitializer(copyExpression(interval[i]), buildIntType()), scope);
23556 insertStatementBefore(insert_target, temp_interval);
23557 interval[i] = buildVarRefExp(interval_name, scope);
23558 new_var_list->append_expression(isSgVarRefExp(interval[i]));
23559 }
23560
23561
23562 //Winnie, starting from here, we are dealing with variables inside loop, update scope
23563 scope = getScope(target_loop);
23564
23565 //Winnie, init statement of the loop header, copy the lower bound, we are dealing with a range, the lower bound should always be "0"
23566 //Winnie, declare a brand new var as the new index
23567 string ivar_name = "__collapsed_index"+ generateUniqueVariableName (global_scope,"");
23568 ROSE_ASSERT(insert_target != NULL);
23569 SgVariableDeclaration* new_index_decl = buildVariableDeclaration(ivar_name, buildIntType(), NULL, insert_target->get_scope());
23570 SgVariableSymbol * collapsed_index_symbol = getFirstVarSym (new_index_decl);
23571 insertStatementBefore(insert_target, new_index_decl);
23572 SgVarRefExp * clps_index_ref = buildVarRefExp(collapsed_index_symbol);
23573 new_var_list->append_expression(clps_index_ref);
23574
23575// SgVariableDeclaration* init_stmt = buildVariableDeclaration(ivar_name, buildIntType(), buildAssignInitializer(buildIntVal(0), buildIntType()), scope);
23576
23577
23578 SgBasicBlock* body = isSgBasicBlock(deepCopy(temp_target_loop->get_loop_body())); // normalized loop has a BB body
23579 ROSE_ASSERT(body != NULL);
23580 SgExpression* new_exp = NULL;
23581 SgExpression* remain_exp_temp = buildVarRefExp(ivar_name, scope);
23582 std::vector<SgStatement*> new_stmt_list;
23583
23584 SgExprStatement* assign_stmt = NULL;
23585
23586 /* Winnie
23587 * express old iterator variables (i_norm, j_norm ...) with new_index,
23588 * new_exp, create new expression for each of the iterators
23589 * i_nom_1 = (_new_index / interval[0])*step[0] + lb[0]
23590 * i_nom_1_remain_value = (_new_index % interval[0])*step[0] + lb[0], create a new var to store remain value
23591 * create a new var to store total_iters[i]
23592 */
23593 for(unsigned int i = 0; i < collapsing_factor - 1; i ++)
23594 {
23595 if(isPlus[i] == true)
23596 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]
23597 else
23598 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
23599
23600 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[i], scope), copyExpression(new_exp));
23601 new_stmt_list.push_back(assign_stmt);
23602 remain_exp_temp = buildModOp((remain_exp_temp), copyExpression(interval[i]));
23603
23604 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
23605 string remain_var_name= "_remainder";
23606 remain_var_name = "__"+ ivar[i]->get_name().getString() + remain_var_name;
23607 SgVariableDeclaration* loop_index_decl = buildVariableDeclaration(remain_var_name, buildIntType(), buildAssignInitializer(remain_exp_temp, buildIntType()), scope);
23608 remain_exp_temp = buildVarRefExp(remain_var_name, scope);
23609 new_stmt_list.push_back(loop_index_decl);
23610 }
23611 new_exp = NULL;
23612 }
23613
23614//Winnie, the inner most loop, iter
23615 if(isPlus[collapsing_factor - 1] == true)
23616 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1]), lb[collapsing_factor - 1]));
23617 else
23618 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMinusOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1])), lb[collapsing_factor - 1]));
23619 new_stmt_list.push_back(assign_stmt);
23620 prependStatementList(new_stmt_list, body);
23621
23622 /*
23623 * step 3: build the new loop, new step is always 1, disregard value of step[i]
23624 */
23625 SgExpression* incr_exp = buildPlusAssignOp(buildVarRefExp(ivar_name, scope), buildIntVal(1));
23626
23627 //Winnie, build the new conditional expression/ub
23628 SgExprStatement* cond_stmt = NULL;
23629 ub_exp = buildSubtractOp(ub_exp, buildIntVal(1));
23630 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar_name,scope),copyExpression(ub_exp)));
23631 ROSE_ASSERT(cond_stmt != NULL);
23632
23633 SgForStatement* new_loop = buildForStatement(buildAssignStatement(clps_index_ref, buildIntVal(0)), cond_stmt,incr_exp, body); //Winnie, add in the new block!
23634 new_loop->set_parent(scope); //TODO: what's the correct parent?
23635
23636 replaceStatement(target_loop, new_loop);
23637
23638 target_loop = new_loop; //Winnie, so that transOmpLoop() can work on the collapsed loop
23639 // constant folding for the transformed AST
23640 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
23641
23642 delete [] ivar;
23643 delete [] lb;
23644 delete [] ub;
23645 delete [] step;
23646 delete [] orig_body;
23647 delete [] total_iters;
23648 delete [] interval;
23649 delete [] isPlus;
23650
23651 #endif
23652
23653 return new_var_list;
23654}
23655
23656
23657
23658bool
23660 {
23661 // DQ (3/4/2014): Added support for testing two trees for equivalents using the AST iterators.
23662
23663#ifndef USE_CMAKEx
23664 // DQ (3/8/2014): Make this conditionally compiled based on when CMake is not used because the libraries are not configured yet.
23665
23666 // This is AST container for the ROSE AST that will provide an iterator.
23667 // We want two iterators (one for the copy of the snippet and one for the
23668 // original snippet so that we can query the original snippet's AST
23669 // as we process each IR node of the AST for the copy of the snippet.
23670 // Only the copy of the snippet is inserted into the target AST.
23671 RoseAst ast_of_copy(tree1);
23672 RoseAst ast_of_original(tree2);
23673
23674 // printf ("ast_of_copy.size() = %" PRIuPTR " \n",ast_of_copy.size());
23675
23676 // Build the iterators so that we can increment thorugh both ASTs one IR node at a time.
23677 RoseAst::iterator i_copy = ast_of_copy.begin();
23678 RoseAst::iterator i_original = ast_of_original.begin();
23679
23680 // Iterate of the copy of the snippet's AST.
23681 while (i_copy != ast_of_copy.end())
23682 {
23683#if 0
23684 printf ("*i_copy = %p = %s \n",*i_copy,(*i_copy)->class_name().c_str());
23685 printf ("*i_original = %p = %s \n",*i_original,(*i_original)->class_name().c_str());
23686#endif
23687 // DQ (2/28/2014): This is a problem for some of the test codes (TEST store/load heap string [test7a] and [test7a])
23688 // ROSE_ASSERT((*i_copy)->variantT() == (*i_original)->variantT());
23689 if ((*i_copy)->variantT() != (*i_original)->variantT())
23690 {
23691#if 0
23692 printf ("ERROR: return from SageInterface::isStructurallyEquivalentAST(): (*i_copy)->variantT() != (*i_original)->variantT() \n");
23693#endif
23694#if 0
23695 printf ("Making this an error! \n");
23696 ROSE_ABORT();
23697#endif
23698 return false;
23699 }
23700
23701 i_copy++;
23702
23703 // Verify that we have not reached the end of the ast for the original (both the
23704 // copy and the original are the same structurally, and thus the same size).
23705 ROSE_ASSERT(i_original != ast_of_original.end());
23706 i_original++;
23707 }
23708
23709 // We have reached the end of both ASTs.
23710 ROSE_ASSERT(i_copy == ast_of_copy.end() && i_original == ast_of_original.end());
23711#endif
23712
23713 return true;
23714 }
23715
23716
23717#endif
23718
23720 SgForStatement * for_loop,
23721 SgVariableSymbol * & iterator,
23722 SgExpression * & lower_bound,
23723 SgExpression * & upper_bound,
23724 SgExpression * & stride
23725) {
23728
23729 iterator = NULL;
23730 lower_bound = NULL;
23731 upper_bound = NULL;
23732 stride = NULL;
23733
23734 SgForInitStatement * for_init_stmt = for_loop->get_for_init_stmt();
23735 const std::vector<SgStatement *> & init_stmts = for_init_stmt->get_init_stmt();
23736 assert(init_stmts.size() == 1);
23737 SgExprStatement * init_stmt = isSgExprStatement(init_stmts[0]);
23738 assert(init_stmt != NULL);
23739 SgExpression * init = init_stmt->get_expression();
23740
23741 SgAssignOp * assign_init = isSgAssignOp(init);
23742 assert(assign_init != NULL);
23743 SgVarRefExp * iterator_init_ref = isSgVarRefExp(assign_init->get_lhs_operand_i());
23744 assert(iterator_init_ref != NULL);
23745 iterator = iterator_init_ref->get_symbol();
23746 assert(iterator != NULL);
23747 lower_bound = assign_init->get_rhs_operand_i();
23748
23749 SgExprStatement * test_stmt = isSgExprStatement(for_loop->get_test());
23750 assert(test_stmt != NULL);
23751 SgExpression * test = test_stmt->get_expression();
23752 SgBinaryOp * bin_test = isSgBinaryOp(test);
23753 assert(bin_test);
23754
23755 SgExpression * lhs_exp = bin_test->get_lhs_operand_i();
23756 while (isSgCastExp(lhs_exp)) lhs_exp = ((SgCastExp *)lhs_exp)->get_operand_i();
23757 SgVarRefExp * lhs_var_ref = isSgVarRefExp(lhs_exp);
23758 bool lhs_it = (lhs_var_ref != NULL) && (lhs_var_ref->get_symbol() == iterator);
23759
23760 SgExpression * rhs_exp = bin_test->get_rhs_operand_i();
23761 while (isSgCastExp(rhs_exp)) rhs_exp = ((SgCastExp *)rhs_exp)->get_operand_i();
23762 SgVarRefExp * rhs_var_ref = isSgVarRefExp(rhs_exp);
23763#ifndef NDEBUG
23764 bool rhs_it = (rhs_var_ref != NULL) && (rhs_var_ref->get_symbol() == iterator);
23765
23766// DQ (4/21/2016): Replacing use of bitwise xor with something more approriate for logical types.
23767// Note that the xor logica operator does not exist in C/C++ and that this is a case of using the
23768// bitwise xor operator on boolean values (not a great idea). Note that logical "a xor b" is
23769// equivalent to "!a != !b" the use of "!" only make sure that the "!=" is applied to a boolean
23770// value. Since these are boolean typed values we can use "a != b", directly.
23771// assert(lhs_it xor rhs_it);
23772 assert(lhs_it != rhs_it);
23773#endif
23774
23775 upper_bound = lhs_it ? bin_test->get_rhs_operand_i() : bin_test->get_lhs_operand_i();
23776
23777 bool inclusive;
23778 bool reversed;
23779
23780 switch (test->variantT()) {
23781 case V_SgGreaterOrEqualOp:
23782 inclusive = lhs_it;
23783 reversed = lhs_it;
23784 break;
23785 case V_SgGreaterThanOp:
23786 inclusive = !lhs_it;
23787 reversed = lhs_it;
23788 break;
23789 case V_SgLessOrEqualOp:
23790 inclusive = lhs_it;
23791 reversed = !lhs_it;
23792 break;
23793 case V_SgLessThanOp:
23794 inclusive = !lhs_it;
23795 reversed = !lhs_it;
23796 break;
23797 case V_SgEqualityOp:
23798 case V_SgNotEqualOp:
23799 default:
23800 ROSE_ABORT();
23801 }
23802
23803 SgExpression * increment = for_loop->get_increment();
23804 switch (increment->variantT()) {
23805 case V_SgPlusPlusOp:
23806 assert(!reversed);
23807 stride = SageBuilder::buildIntVal(1);
23808 break;
23809 case V_SgMinusMinusOp:
23810 assert(reversed);
23811 stride = SageBuilder::buildIntVal(-1);
23812 break;
23813 case V_SgPlusAssignOp:
23814 {
23815 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23816#ifndef NDEBUG
23817 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23818 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23819#endif
23820 stride = bin_op->get_rhs_operand_i();
23821 break;
23822 }
23823 case V_SgMinusAssignOp:
23824 {
23825 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23826#ifndef NDEBUG
23827 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23828 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23829#endif
23830 stride = bin_op->get_rhs_operand_i();
23831 break;
23832 }
23833 case V_SgAssignOp:
23834 {
23835 SgAssignOp * assign_op = (SgAssignOp *)increment;
23836#ifndef NDEBUG
23837 SgVarRefExp * inc_assign_lhs = isSgVarRefExp(assign_op->get_lhs_operand_i());
23838 assert(inc_assign_lhs != NULL && inc_assign_lhs->get_symbol() == iterator);
23839#endif
23840 SgBinaryOp * inc_assign_rhs = isSgBinaryOp(assign_op->get_rhs_operand_i());
23841 assert(inc_assign_rhs != NULL);
23842 SgVarRefExp * inc_assign_rhs_lhs = isSgVarRefExp(inc_assign_rhs->get_lhs_operand_i());
23843 if (inc_assign_rhs_lhs != NULL && inc_assign_rhs_lhs->get_symbol() == iterator)
23844 stride = inc_assign_rhs->get_rhs_operand_i();
23845 SgVarRefExp * inc_assign_rhs_rhs = isSgVarRefExp(inc_assign_rhs->get_rhs_operand_i());
23846 if (inc_assign_rhs_rhs != NULL && inc_assign_rhs_rhs->get_symbol() == iterator)
23847 stride = inc_assign_rhs->get_lhs_operand_i();
23848 break;
23849 }
23850 default:
23851 ROSE_ABORT();
23852 }
23853
23854 // DQ (7/19/2015): Added braces to avoid compiler warning about ambigious "else" case.
23855 if (!inclusive)
23856 {
23857 if (reversed)
23858 upper_bound = SageBuilder::buildAddOp(upper_bound, SageBuilder::buildIntVal(1));
23859 else
23860 upper_bound = SageBuilder::buildSubtractOp(upper_bound, SageBuilder::buildIntVal(1));
23861 }
23862
23863 return true;
23864}
23865
23866//------------------------------------------------------------------------------
23867#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
23868//------------------------------------------------------------------------------
23869
23874 jstring temp_directory = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(::currentJavaTraversalClass, Rose::Frontend::Java::Ecj::getTempDirectoryMethod);
23875
23876 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_directory, NULL);
23877 ROSE_ASSERT(utf8);
23878 string directory_name = utf8;
23879 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_directory, utf8);
23880
23881 list<string> sourcepath = project -> get_Java_sourcepath();
23882 sourcepath.push_back(directory_name); // push it in the back because it should have lower priority
23883 project -> set_Java_sourcepath(sourcepath);
23884
23885 return directory_name;
23886}
23887
23888
23892void SageInterface::destroyTempDirectory(string directory_name) {
23893 string command = string("rm -fr ") + directory_name;
23894 int status = system(command.c_str());
23895 ROSE_ASSERT(status == 0);
23896}
23897
23898
23902SgFile* SageInterface::processFile(SgProject *project, string filename, bool unparse /* = false */) {
23903 //
23904 // Set up the new source file for processing "a la Rose".
23905 //
23906 project -> get_sourceFileNameList().push_back(filename);
23907 Rose_STL_Container<std::string> arg_list = project -> get_originalCommandLineArgumentList();
23908 arg_list.push_back(filename);
23909 Rose_STL_Container<string> fileList = CommandlineProcessing::generateSourceFilenames(arg_list, false);
23910 CommandlineProcessing::removeAllFileNamesExcept(arg_list, fileList, filename);
23911 int error_code = 0; // need this because determineFileType takes a reference "error_code" argument.
23912 SgFile *file = determineFileType(arg_list, error_code, project);
23913 SgSourceFile *sourcefile = isSgSourceFile(file);
23914 ROSE_ASSERT(sourcefile);
23915 sourcefile -> set_parent(project);
23916
23917 //
23918 // Insert the file into the list of files in the project.
23919 //
23920 project -> get_fileList_ptr() -> get_listOfFiles().push_back(sourcefile);
23921 ROSE_ASSERT(sourcefile == isSgSourceFile((*project)[filename]));
23922
23923 sourcefile -> build_Java_AST(arg_list, project -> get_originalCommandLineArgumentList());
23924
23925 if (! unparse) { // if we are not supposed to unparse this file,
23926 project -> get_fileList_ptr() -> get_listOfFiles().pop_back(); // remove it from the list of files in the project
23927 ROSE_ASSERT(sourcefile != isSgSourceFile((*project)[filename]));
23928 }
23929
23930 // DQ (7/2/2020): Added assertion (fails for snippet tests).
23931 ROSE_ASSERT(file->get_preprocessorDirectivesAndCommentsList() != NULL);
23932
23933 return file;
23934}
23935
23936
23941string SageInterface::preprocessPackage(SgProject *project, string package_name) {
23942 string command = "package " + package_name + ";";
23943
23944 //
23945 // Call the Java side to create an input file with the relevant package statement; translate the file and return the file name.
23946 //
23947 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23948 Rose::Frontend::Java::Ecj::createTempFileMethod,
23949 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23950
23951 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23952 ROSE_ASSERT(utf8);
23953 string filename = (string) utf8;
23954 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23955
23956 processFile(project, filename); // translate the file
23957
23958 return package_name;
23959}
23960
23961
23966string SageInterface::preprocessImport(SgProject *project, string import_string) {
23967 string command = "import " + import_string + ";";
23968
23969 //
23970 // Call the Java side to create an input file with the relevant import statement.
23971 //
23972 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23973 Rose::Frontend::Java::Ecj::createTempFileMethod,
23974 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23975
23976 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23977 ROSE_ASSERT(utf8);
23978 string filename = (string) utf8;
23979 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23980
23981 processFile(project, filename); // translate the file
23982
23983 return import_string;
23984}
23985
23986
23991SgFile* SageInterface::preprocessCompilationUnit(SgProject *project, string file_name, string file_content, bool unparse /* true */) {
23992 //
23993 // Call the Java side to create an input file with the relevant import statement.
23994 //
23995 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23996 Rose::Frontend::Java::Ecj::createTempNamedFileMethod,
23997 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_name.c_str()),
23998 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_content.c_str()));
23999
24000 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
24001 ROSE_ASSERT(utf8);
24002 string filename = (string) utf8;
24003 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
24004
24005 return processFile(project, filename, unparse); // translate the file and unparse it, if requested (unparse=true is the default).
24006}
24007
24008
24013 ROSE_ASSERT(scope);
24014 SgClassDefinition *package_definition = NULL;
24015 for (int index = 0, length = package_name.size(); index < length; index++) {
24016 int n;
24017 for (n = index; n < length; n++) {
24018 if (package_name[n] == '.') {
24019 break;
24020 }
24021 }
24022 string name = package_name.substr(index, n - index);
24023
24024 SgClassSymbol *package_symbol = scope -> lookup_class_symbol(name);
24025 if (package_symbol == NULL) { // package not found?
24026 return NULL;
24027 }
24028
24029 SgJavaPackageDeclaration *package_declaration = isSgJavaPackageDeclaration(package_symbol -> get_declaration() -> get_definingDeclaration());
24030 ROSE_ASSERT(package_declaration);
24031 package_definition = package_declaration -> get_definition();
24032 ROSE_ASSERT(package_definition);
24033 scope = package_definition;
24034
24035 index = n;
24036 }
24037
24038 return package_definition;
24039}
24040
24041
24045SgClassDefinition *SageInterface::findOrInsertJavaPackage(SgProject *project, string package_name, bool create_directory /* = false */) {
24046 SgGlobal *global_scope = project -> get_globalScopeAcrossFiles();
24047 SgClassDefinition *package_definition = findJavaPackage(global_scope, package_name);
24048 if (package_definition == NULL) { // try again after loading the package
24049 preprocessPackage(project, package_name);
24050
24051 //
24052 // If requested, Create the directory associated with this package_name.
24053 //
24054 if (create_directory) {
24055 Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24056 Rose::Frontend::Java::Ecj::createTempNamedDirectoryMethod,
24057 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(package_name.c_str()));
24058 }
24059
24060 package_definition = findJavaPackage(global_scope, package_name);
24061 }
24062
24063 return package_definition;
24064}
24065
24070 ROSE_ASSERT(package_definition);
24071 SgClassSymbol *class_symbol = package_definition -> lookup_class_symbol(class_name);
24072 SgClassDeclaration *class_declaration = (class_symbol == NULL
24073 ? NULL
24074 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24075 if ((! class_declaration) || (! class_declaration -> attributeExists("complete"))) { // class not available in the scope
24076 string qualified_name = package_definition -> get_qualified_name().getString() + "." + class_name;
24077 preprocessImport(project, qualified_name);
24078 class_symbol = package_definition -> lookup_class_symbol(class_name);
24079 }
24080
24081 class_declaration = (class_symbol == NULL
24082 ? NULL
24083 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24084
24085 return class_declaration;
24086}
24087
24088
24092SgClassDeclaration *SageInterface::findOrImportJavaClass(SgProject *project, string package_name, string class_name) {
24093 return findOrImportJavaClass(project, findOrInsertJavaPackage(project, package_name, false), class_name);
24094}
24095
24096
24101 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24102 ROSE_ASSERT(class_declaration);
24103 SgClassDefinition *scope = isSgClassDefinition(class_declaration -> get_scope());
24104 while (scope && (! isSgJavaPackageDeclaration(scope -> get_parent()))) {
24105 class_declaration = isSgClassDeclaration(scope -> get_parent());
24106 ROSE_ASSERT(class_declaration);
24107 scope = isSgClassDefinition(class_declaration -> get_scope());
24108 }
24109
24110 if (! scope) { // a local type !!!
24111 return NULL;
24112 }
24113
24114 string class_name = class_declaration -> get_name().getString();
24115 return findOrImportJavaClass(project, scope, class_name);
24116}
24117
24118
24123 ROSE_ASSERT(class_definition);
24125 ROSE_ASSERT(type_list);
24126 SgArrayType *string_array_type = getUniqueJavaArrayType(Rose::Frontend::Java::StringClassType, 1);
24127 ROSE_ASSERT(string_array_type);
24128 type_list -> append_argument(string_array_type);
24129
24130 // DQ (1/11/2020): Fixing support for C++11 l-value and r-value reference modifiers for member functions.
24131 // SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, 0);
24132 SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, /* mfunc_specifier */ 0);
24133
24134 SgFunctionSymbol *method_symbol = class_definition -> lookup_function_symbol("main", member_function_type);
24135 delete type_list;
24136 return (method_symbol == NULL ? NULL : isSgMemberFunctionDeclaration(method_symbol -> get_declaration()));
24137}
24138
24139
24144 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24145 ROSE_ASSERT(class_declaration);
24146 SgClassDefinition *class_definition = class_declaration -> get_definition();
24147 return findJavaMain(class_definition);
24148}
24149
24150//------------------------------------------------------------------------------
24151#endif // ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
24152//------------------------------------------------------------------------------
24153
24155// Essentially replace variable a with b.
24157{
24158 ROSE_ASSERT (old_sym != NULL);
24159 ROSE_ASSERT (new_sym != NULL);
24160 ROSE_ASSERT (old_sym != new_sym);
24161 ROSE_ASSERT (scope != NULL);
24162
24163 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVarRefExp);
24164 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
24165 {
24166 SgVarRefExp *vRef = isSgVarRefExp(*i);
24167 if (vRef->get_symbol() == old_sym)
24168 vRef->set_symbol(new_sym);
24169 }
24170}
24171
24172
24173// 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.
24178bool
24180 {
24181 bool result = true;
24182
24183 bool includingSelf = false;
24184 SgSourceFile* sourceFile = getEnclosingSourceFile(stmt,includingSelf);
24185
24186 if (sourceFile == NULL)
24187 {
24188 printf ("In SageInterface::statementCanBeTransformed(): sourceFile not found \n");
24189 }
24190
24191 // I think we can assert this!
24192 ROSE_ASSERT(sourceFile != NULL);
24193
24194 if (sourceFile != NULL && sourceFile->get_unparse_tokens() == true && sourceFile->get_unparseHeaderFiles() == true)
24195 {
24196 // Need to look up the source file name, find the SgIncludeFile, and check if statements from this file can be transformed.
24197 // 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.
24198 string source_filename = stmt->getFilenameString();
24199#if 0
24200 printf ("In SageInterface::statementCanBeTransformed(): source_filename = %s \n",source_filename.c_str());
24201 printf (" --- Rose::includeFileMapForUnparsing.size() = %zu \n",Rose::includeFileMapForUnparsing.size());
24202#endif
24203
24204 // DQ (11/5/2019): Using the edg_include_file_map instead (constructed in EDG/ROSE translation).
24205 if (EDG_ROSE_Translation::edg_include_file_map.find(source_filename) != EDG_ROSE_Translation::edg_include_file_map.end())
24206 {
24207 SgIncludeFile* include_file = EDG_ROSE_Translation::edg_include_file_map[source_filename];
24208 ROSE_ASSERT(include_file != NULL);
24209#if 0
24210 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");
24211#endif
24212 if (include_file->get_can_be_supported_using_token_based_unparsing() == false)
24213 {
24214#if 0
24215 printf ("NOTE: Transformations of this statement cannot be supported using the header file unparsing with token unparsing options! \n");
24216#endif
24217 result = false;
24218 }
24219 }
24220 else
24221 {
24222 // DQ (5/13/2021): I think that the default (returing true) will work well.
24223 // This is likely just the original input source file (not a header file).
24224#if 0
24225 printf ("Not found in Rose::includeFileMapForUnparsing: source_filename = %s \n",source_filename.c_str());
24226#endif
24227#if 0
24228 printf ("Exiting as a test! \n");
24229 ROSE_ABORT();
24230#endif
24231 }
24232
24233#if 0
24234 printf ("Error: In statementCanBeTransformed(): this might be an issue! \n");
24235 ROSE_ABORT();
24236#endif
24237 }
24238
24239 return result;
24240 }
24241
24242
24243//Note: this function is no longer used by decl move tool: we use copy and insert instead to support moving to multiple scopes
24246{
24247 ROSE_ASSERT (decl!= NULL);
24248 ROSE_ASSERT (target_scope != NULL);
24249 ROSE_ASSERT (target_scope != decl->get_scope());
24250
24251#if 0 // at this stage, we focus on legal move only, any scope adjustment should be done earlier!
24252 // Special handling for If-Stmt, may need to climb up one level of scope when:
24253 // two bodies of if uses the same variable, but cannot be pushed down into each body.
24254 // If-stmt will be the innermost common scope for the variable.
24255 // But we should not move the declaration to if-stmt. We can only move it to the parent scope of if-stmt.
24256 if (isSgIfStmt (target_scope))
24257 {
24258 target_scope = SageInterface::getEnclosingScope (target_scope, false);
24259 if (target_scope == )
24260 }
24261# endif
24262
24263 // Move the declaration
24264 //TODO: consider another way: copy the declaration, insert the copy, replace varRefExp, and remove (delete) the original declaration
24266
24267 switch (target_scope->variantT())
24268 {
24269 case V_SgBasicBlock:
24270 {
24271 SageInterface::prependStatement (decl, target_scope);
24272 break;
24273 }
24274#if 0 // this check should be done earlier before any side effects can happen
24275 case V_SgIfStmt:
24276 {
24277 // adjust to parent scope of if-stmt
24278 break;
24279 }
24280#endif
24281 case V_SgForStatement:
24282 {
24283 // we move int i; to be for (int i=0; ...);
24284 SgForStatement* stmt = isSgForStatement (target_scope);
24285 ROSE_ASSERT(stmt != NULL);
24286 SgStatementPtrList& stmt_list = stmt->get_init_stmt();
24287 // Try to match a pattern like for (i=0; ...) here
24288 // assuming there is only one assignment like i=0
24289 // We don't yet handle more complex cases
24290 if (stmt_list.size() !=1)
24291 {
24292 cerr<<"Error in moveVariableDeclaration(): only single init statement is handled for SgForStatement now."<<endl;
24293 ROSE_ASSERT (stmt_list.size() ==1);
24294 }
24295 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
24296 ROSE_ASSERT (exp_stmt != NULL);
24297 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
24298 ROSE_ASSERT (assign_op != NULL);
24299
24300 // remove the existing i=0; preserve its right hand operand
24302 stmt_list.clear();
24303 SageInterface::deepDelete (exp_stmt);
24304
24305 // modify the decl's rhs to be the new one
24308 if (init_name->get_initptr() != NULL)
24309 SageInterface::deepDelete (init_name->get_initptr());
24310 init_name->set_initptr(initor);
24311 initor->set_parent(init_name);
24312
24313 stmt_list.insert (stmt_list.begin(), decl );
24314 break;
24315 }
24316
24317 default:
24318 {
24319 cerr<<"Error. Unhandled target scope type:"<<target_scope->class_name()<<endl;
24320 ROSE_ASSERT (false);
24321 }
24322 }
24323
24324 //make sure the symbol is moved also since prependStatement() (in fact fixVariableDeclaration()) does not handle this detail.
24326 ROSE_ASSERT(sym != NULL);
24327 SgScopeStatement* orig_scope = sym->get_scope();
24328 if (orig_scope != target_scope)
24329 {
24330 // SageInterface::fixVariableDeclaration() cannot switch the scope for init name.
24331 // it somehow always reuses previously associated scope.
24333 init_name->set_scope(target_scope);
24334 SgName sname = sym->get_name();
24335 orig_scope->remove_symbol(sym);
24336 target_scope->insert_symbol(sname, sym);
24337 }
24338 // This is difficult since C++ variables have namespaces
24339 // Details are in SageInterface::fixVariableDeclaration()
24340 ROSE_ASSERT (target_scope->symbol_exists(sym));
24341}
24342
24343class SimpleExpressionEvaluator: public AstBottomUpProcessing <struct SageInterface::const_int_expr_t> {
24344 public:
24346 }
24347
24348 struct SageInterface::const_int_expr_t getValueExpressionValue(SgValueExp *valExp) {
24349 struct SageInterface::const_int_expr_t subtreeVal;
24350 subtreeVal.hasValue_ = true;
24351
24352 if (isSgIntVal(valExp)) {
24353 subtreeVal.value_ = isSgIntVal(valExp)->get_value();
24354 } else if (isSgLongIntVal(valExp)) {
24355 subtreeVal.value_ = isSgLongIntVal(valExp)->get_value();
24356 } else if (isSgLongLongIntVal(valExp)) {
24357 subtreeVal.value_ = isSgLongLongIntVal(valExp)->get_value();
24358 } else if (isSgShortVal(valExp)) {
24359 subtreeVal.value_ = isSgShortVal(valExp)->get_value();
24360 } else if (isSgUnsignedIntVal(valExp)) {
24361 subtreeVal.value_ = isSgUnsignedIntVal(valExp)->get_value();
24362 } else if (isSgUnsignedLongVal(valExp)) {
24363 subtreeVal.value_ = isSgUnsignedLongVal(valExp)->get_value();
24364 } else if (isSgUnsignedLongLongIntVal(valExp)) {
24365 subtreeVal.value_ = isSgUnsignedLongLongIntVal(valExp)->get_value();
24366 } else if (isSgUnsignedShortVal(valExp)) {
24367 subtreeVal.value_ = isSgUnsignedShortVal(valExp)->get_value();
24368 }
24369 return subtreeVal;
24370 }
24371
24372 struct SageInterface::const_int_expr_t evaluateVariableReference(SgVarRefExp *vRef) {
24373 if (isSgModifierType(vRef->get_type()) == NULL) {
24375 val.value_ = -1;
24376 val.hasValue_ = false;
24377 return val;
24378 }
24379 if (isSgModifierType(vRef->get_type())->get_typeModifier().get_constVolatileModifier().isConst()) {
24380 // We know that the var value is const, so get the initialized name and evaluate it
24381 SgVariableSymbol *sym = vRef->get_symbol();
24382 SgInitializedName *iName = sym->get_declaration();
24383 SgInitializer *ini = iName->get_initializer();
24384
24385 if (isSgAssignInitializer(ini)) {
24386 SgAssignInitializer *initializer = isSgAssignInitializer(ini);
24387 SgExpression *rhs = initializer->get_operand();
24388 SimpleExpressionEvaluator variableEval;
24389
24390 return variableEval.traverse(rhs);
24391 }
24392 }
24394 val.hasValue_ = false;
24395 val.value_ = -1;
24396 return val;
24397 }
24398
24399 struct SageInterface::const_int_expr_t evaluateSynthesizedAttribute(SgNode *node, SynthesizedAttributesList synList) {
24400 if (isSgExpression(node) != NULL) {
24401 SgValueExp* valueExp = isSgValueExp(node);
24402 if (valueExp != NULL) {
24403 return this->getValueExpressionValue(valueExp);
24404 }
24405
24406 SgVarRefExp* varRefExp = isSgVarRefExp(node);
24407 if (varRefExp != NULL) {
24408 // std::cout << "Hit variable reference expression!" << std::endl;
24409 return evaluateVariableReference(varRefExp);
24410 }
24411 // Early break out for assign initializer // other possibility?
24412 if (isSgAssignInitializer(node)) {
24413 if(synList.at(0).hasValue_){
24414 return synList.at(0);
24415 } else {
24417 val.value_ = -1;
24418 val.hasValue_ = false;
24419 return val;
24420 }
24421 }
24422 struct SageInterface::const_int_expr_t evaluatedValue;
24423 evaluatedValue.hasValue_ = false;
24424 evaluatedValue.value_ = -1;
24425#if 0
24426 if(synList.size() != 2){
24427 for(SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it){
24428 std::cout << "Node: " << node->unparseToString() << "\n" << (*it).value_ << std::endl;
24429 std::cout << "Parent: " << node->get_parent()->unparseToString() << std::endl;
24430 std::cout << "Parent, Parent: " << node->get_parent()->get_parent()->unparseToString() << std::endl;
24431 }
24432 }
24433#endif
24434 for (SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it) {
24435 if((*it).hasValue_){
24436 if (isSgAddOp(node)) {
24437 assert(synList.size() == 2);
24438 evaluatedValue.value_ = synList[0].value_ + synList[1].value_ ;
24439 evaluatedValue.hasValue_ = true;
24440 } else if (isSgSubtractOp(node)) {
24441 assert(synList.size() == 2);
24442 evaluatedValue.value_ = synList[0].value_ - synList[1].value_ ;
24443 evaluatedValue.hasValue_ = true;
24444 } else if (isSgMultiplyOp(node)) {
24445 assert(synList.size() == 2);
24446 evaluatedValue.value_ = synList[0].value_ * synList[1].value_ ;
24447 evaluatedValue.hasValue_ = true;
24448 } else if (isSgDivideOp(node)) {
24449 assert(synList.size() == 2);
24450 evaluatedValue.value_ = synList[0].value_ / synList[1].value_ ;
24451 evaluatedValue.hasValue_ = true;
24452 } else if (isSgModOp(node)) {
24453 assert(synList.size() == 2);
24454 evaluatedValue.value_ = synList[0].value_ % synList[1].value_ ;
24455 evaluatedValue.hasValue_ = true;
24456 }
24457 } else {
24458 std::cerr << "Expression is not evaluatable" << std::endl;
24459 evaluatedValue.hasValue_ = false;
24460 evaluatedValue.value_ = -1;
24461 return evaluatedValue;
24462 }
24463 }
24464 evaluatedValue.hasValue_ = true;
24465 return evaluatedValue;
24466 }
24467 struct SageInterface::const_int_expr_t evaluatedValue;
24468 evaluatedValue.hasValue_ = false;
24469 evaluatedValue.value_ = -1;
24470 return evaluatedValue;
24471 }
24472};
24473
24477 return eval.traverse(expr);
24478}
24479
24480bool
24482
24483 class TypeEquivalenceChecker {
24484 public:
24485 TypeEquivalenceChecker(bool profile, bool useSemanticEquivalence)
24486 : profile_(profile), useSemanticEquivalence_(useSemanticEquivalence),
24487 namedType_(0), pointerType_(0), arrayType_(0), functionType_(0)
24488 {
24489 }
24490
24491 SgNode * getBasetypeIfApplicable(SgNode *t){
24492 SgNode * node = t;
24493 if (isSgTypedefType(t)) {
24494// std::cout << "This is a typedef nodeT1. We strip everything away and compare the hidden types." << std::endl;
24495 node = isSgTypedefType(t)->stripType(SgType::STRIP_TYPEDEF_TYPE);
24496 }
24497 if(useSemanticEquivalence_){
24498 if(isSgModifierType(t)){
24499 SgModifierType *modType = isSgModifierType(t);
24500 ROSE_ASSERT(modType != NULL);
24501 // We need to check for Volatile/Restrict types. These are modelled as ModifierTypes, but are equal (in some cases)
24502 // volatile seems to make no difference for basic (built in) types like int, bool etc. But it has an impact on types
24503 // like classes
24504 // restrict seems to have no impact on the type itself.
24505 if(SageInterface::isVolatileType(modType)){
24506 // handle volatile case
24507 std::cout << "Hit volatile type, stripping of modifier type" << std::endl;
24508 node = modType->get_base_type();
24509 }
24510 if(SageInterface::isRestrictType(modType)){
24511 // handle restrict case
24512 std::cout << "Hit restrict type, stripping of modifier type" << std::endl;
24513 node = modType->get_base_type();
24514 }
24515 }
24516 }
24517 ROSE_ASSERT(node != NULL);
24518 return node;
24519}
24520
24521bool typesAreEqual(SgType *t1, SgType *t2) {
24522 bool equal = false;
24523 if(t1 == NULL || t2 == NULL){
24524 std::string wasNull;
24525 if(t1 == NULL){
24526 wasNull = "t1";
24527 } else {
24528 wasNull = "t2";
24529 }
24530 std::cerr << "ERROR: " << wasNull << " was NULL" << std::endl;
24531 return equal;
24532 }
24533 // if both pointers point to same location the types MUST be equal!
24534 if(t1 == t2){
24535// std::cout << "Pointers are equal, returning true" << std::endl;
24536 return true;
24537 }
24538#ifndef USE_CMAKEx
24539 RoseAst subT1(t1);
24540 RoseAst subT2(t2);
24541
24542 for (RoseAst::iterator i = subT1.begin(), j = subT2.begin();
24543 i != subT1.end() && j != subT2.end(); ++i, ++j) {
24544 SgNode *nodeT1 = *i;
24545 SgNode *nodeT2 = *j;
24546
24547// std::cout << "nodeT1: " << nodeT1->class_name() << " nodeT2: " << nodeT2->class_name() << std::endl;
24548 nodeT1 = getBasetypeIfApplicable(nodeT1);
24549 nodeT2 = getBasetypeIfApplicable(nodeT2);
24550
24551 if (nodeT1->variantT() == nodeT2->variantT()) {
24552// std::cout << "variantT is the same" << std::endl;
24553 if(isSgModifierType(nodeT1)){
24554 // we need to check whether the modifier is the same or not
24555 SgTypeModifier modT1 = isSgModifierType(nodeT1)->get_typeModifier();
24556 SgTypeModifier modT2 = isSgModifierType(nodeT2)->get_typeModifier();
24557 if(modT1.get_constVolatileModifier().isConst() != modT2.get_constVolatileModifier().isConst()){
24558 return false;
24559 }
24560 if(modT1.get_constVolatileModifier().isVolatile() != modT2.get_constVolatileModifier().isVolatile()){
24561 return false;
24562 }
24563 } else if (isSgNamedType(nodeT1)) { // Two different names -> Must be two different things
24564 if (profile_) {
24565 namedType_++;
24566 }
24567 i.skipChildrenOnForward();
24568 j.skipChildrenOnForward();
24569 SgNamedType *c1 = isSgNamedType(nodeT1);
24570 SgNamedType *c2 = isSgNamedType(nodeT2);
24571
24572 // XXX A function to check whether a named type is anonymous or not would speed
24573 // up this check, since we could get rid of this string compare.
24574 if(!c1->get_autonomous_declaration()){
24575 return false;
24576 }
24577 if (!c2->get_autonomous_declaration()){
24578 return false;
24579 }
24580 if (c1->get_qualified_name() == c2->get_qualified_name()) {
24581 return true;
24582 } else {
24583 return false;
24584 }
24585
24586 } else if (isSgPointerType(nodeT1)) {
24587 if (profile_) {
24588 pointerType_++;
24589 }
24590 SgPointerType *t1 = isSgPointerType(nodeT1);
24591 SgPointerType *t2 = isSgPointerType(nodeT2);
24592
24593 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24594
24595 } else if(isSgReferenceType(nodeT1)){
24596 SgReferenceType *t1 = isSgReferenceType(nodeT1);
24597 SgReferenceType *t2 = isSgReferenceType(nodeT2);
24598
24599 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24600 } else if (isSgArrayType(nodeT1)) {
24601 if (profile_) {
24602 arrayType_++;
24603 }
24604 SgArrayType *a1 = isSgArrayType(nodeT1);
24605 SgArrayType *a2 = isSgArrayType(nodeT2);
24606
24607 bool arrayBaseIsEqual = typesAreEqual(a1->get_base_type(), a2->get_base_type());
24608
24611 bool arrayIndexExpressionIsEquivalent = false;
24612 if(t1Index.hasValue_ && t2Index.hasValue_){
24613 if(t1Index.value_ == t2Index.value_){
24614 arrayIndexExpressionIsEquivalent = true;
24615 }
24616 }
24617 bool arraysAreEqual = (arrayBaseIsEqual && arrayIndexExpressionIsEquivalent);
24618 return arraysAreEqual;
24619 } else if (isSgFunctionType(nodeT1)) {
24620 if(profile_) {
24621 functionType_++;
24622 }
24623 SgFunctionType *funcTypeA = isSgFunctionType(nodeT1);
24624 SgFunctionType *funcTypeB = isSgFunctionType(nodeT2);
24625// std::cout << "Inside SgFunctionType" << std::endl;
24626// assert(funcTypeA != funcTypeB);
24627 if(typesAreEqual(funcTypeA->get_return_type(), funcTypeB->get_return_type())) {
24628 // If functions don't have the same number of arguments, they are not type-equal
24629 if(funcTypeA->get_arguments().size() != funcTypeB->get_arguments().size()) {
24630 return false;
24631 }
24632 // This should always be the same as the if before...
24633 if(funcTypeA->get_argument_list()->get_arguments().size() != funcTypeB->get_argument_list()->get_arguments().size()){
24634 return false;
24635 }
24636
24637 for(SgTypePtrList::const_iterator ii = funcTypeA->get_arguments().begin(),
24638 jj = funcTypeB->get_arguments().begin();
24639 ii != funcTypeA->get_arguments().end() &&
24640 jj != funcTypeB->get_arguments().end();
24641 ++ii, ++jj) {
24642// std::cout << (*ii)->class_name() << " " << (*jj)->class_name() << std::endl;
24643 // For all argument types check whether they are equal
24644 if(!typesAreEqual((*ii), (*jj))) {
24645 return false;
24646 }
24647 }
24648 return true;
24649 }
24650 return false;
24651 } else {
24652 // We don't have a named type, pointer type or array type, so they are equal
24653 // This is for the primitive type - case
24654 return true;
24655 }
24656 } else {
24657 // In this case the types are not equal, since its variantT is not equal.
24658 return false;
24659 }
24660 }
24661 // this should be unreachable code...
24662 return equal;
24663#else
24664 std::cerr << "This feature for now is available with autotools only!" << std::endl;
24665 ROSE_ABORT();
24666#endif
24667}
24668
24669int getNamedTypeCount() {
24670 return namedType_;
24671}
24672
24673int getPointerTypeCount() {
24674 return pointerType_;
24675}
24676
24677int getArrayTypeCount() {
24678 return arrayType_;
24679}
24680
24681int getFunctionTypeCount() {
24682 return functionType_;
24683}
24684 private:
24685// SgNode * getBasetypeIfApplicable(SgNode *t);
24686 bool profile_, useSemanticEquivalence_;
24687 int namedType_, pointerType_, arrayType_, functionType_;
24688};
24689
24690TypeEquivalenceChecker tec(false, false);
24691return tec.typesAreEqual(typeA, typeB);
24692}
24693
24694
24695std::set<SgStatement*>
24697 {
24698 // DQ (6/11/2015): This reports the statements that are marked as transformed.
24699 // It is useful for debugging the token-based unparsing.
24700
24701 class StatementTraversal : public AstSimpleProcessing
24702 {
24703 public:
24704 StatementTraversal() : count (0) {}
24705 void visit (SgNode* node)
24706 {
24707 SgStatement* statement = isSgStatement(node);
24708 if (statement != nullptr && statement->isTransformation() == true)
24709 {
24710 returnset.insert(statement);
24711 count++;
24712 }
24713 }
24714
24715 int count; // running total of statements found marked as transformations in the input AST
24716 std::set<SgStatement*> returnset;
24717 };
24718
24719 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24720 StatementTraversal traversal;
24721 traversal.traverse(node, preorder);
24722
24723 return traversal.returnset;
24724 }
24725
24726std::set<SgStatement*>
24728 {
24729 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24730 // It is useful for debugging the token-based unparsing.
24731
24732#if 1
24733 printf ("In collectModifiedStatements(): node = %p = %s \n",node,node->class_name().c_str());
24734#endif
24735
24736 class StatementTraversal : public AstSimpleProcessing
24737 {
24738 public:
24739 StatementTraversal() : count (0) {}
24740 void visit (SgNode* node)
24741 {
24742 SgStatement* statement = isSgStatement(node);
24743 if (statement != NULL && statement->get_isModified() == true)
24744 {
24745 returnset.insert(statement);
24746 count++;
24747 }
24748 }
24749
24750 int count; // running total of statements found marked as transformations in the input AST
24751 std::set<SgStatement*> returnset;
24752 };
24753
24754 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24755 StatementTraversal traversal;
24756 traversal.traverse(node, preorder);
24757
24758 return traversal.returnset;
24759 }
24760
24761
24762void
24764 {
24765 // DQ (12/2/2019): This reports the file id values of all located nodes in the AST subtree represented by the input node.
24766
24767#if 0
24768 printf ("In outputFileIds(): node = %p = %s \n",node,node->class_name().c_str());
24769#endif
24770
24771 class LocatedNodeTraversal : public AstSimpleProcessing
24772 {
24773 public:
24774 LocatedNodeTraversal() {}
24775 void visit (SgNode* node)
24776 {
24777 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24778 if (locatedNode != NULL)
24779 {
24780#if 0
24781 printf ("In outputFileIds(): isModified() == %s: locatedNode = %p = %s \n",locatedNode->get_isModified() ? "true" : "false",locatedNode,locatedNode->class_name().c_str());
24782 printf (" --- file id = %d physical_file_id = %d \n",node->get_file_info()->get_file_id(),node->get_file_info()->get_physical_file_id());
24783#endif
24784 }
24785 else
24786 {
24787 SgInitializedName* initializedName = isSgInitializedName(node);
24788 if (initializedName != NULL)
24789 {
24790 printf ("In outputFileIds(): isModified() == %s: initializedName = %p = %s \n",initializedName->get_isModified() ? "true" : "false",initializedName,initializedName->class_name().c_str());
24791 printf (" --- file id = %d physical_file_id = %d \n",initializedName->get_file_info()->get_file_id(),initializedName->get_file_info()->get_physical_file_id());
24792 }
24793 }
24794 }
24795 };
24796
24797 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24798 LocatedNodeTraversal traversal;
24799 traversal.traverse(node, preorder);
24800
24801#if 0
24802 printf ("Exiting as a test! \n");
24803 ROSE_ABORT();
24804#endif
24805 }
24806
24807
24808std::set<SgLocatedNode*>
24810 {
24811 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24812 // It is useful for debugging the token-based unparsing.
24813
24814#if 0
24815 printf ("In collectModifiedLocatedNodes(): node = %p = %s \n",node,node->class_name().c_str());
24816#endif
24817
24818 class LocatedNodeTraversal : public AstSimpleProcessing
24819 {
24820 public:
24821 LocatedNodeTraversal() : count (0) {}
24822 void visit (SgNode* node)
24823 {
24824 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24825 if (locatedNode != NULL && locatedNode->get_isModified() == true)
24826 {
24827#if 0
24828 printf ("In collectModifiedLocatedNodes(): isModified() == true: locatedNode = %p = %s \n",locatedNode,locatedNode->class_name().c_str());
24829#endif
24830 returnset.insert(locatedNode);
24831 count++;
24832 }
24833 }
24834
24835 int count; // running total of statements found marked as transformations in the input AST
24836 std::set<SgLocatedNode*> returnset;
24837 };
24838
24839 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24840 LocatedNodeTraversal traversal;
24841 traversal.traverse(node, preorder);
24842
24843 return traversal.returnset;
24844 }
24845
24846
24848void
24849SageInterface::resetModifiedLocatedNodes(const std::set<SgLocatedNode*> & modifiedNodeSet)
24850 {
24851 // DQ (6/5/2019): Use a previously constructed set to reset the IR nodes to be marked as isModified.
24852
24853#if 0
24854 printf ("In resetModifiedLocatedNodes(): modifiedNodeSet.size() = %zu \n",modifiedNodeSet.size());
24855#endif
24856
24857 std::set<SgLocatedNode*>::const_iterator i = modifiedNodeSet.begin();
24858 while (i != modifiedNodeSet.end())
24859 {
24860 SgLocatedNode* node = *i;
24861#if 0
24862 printf ("Marking node = %p = %s as modified \n",node,node->class_name().c_str());
24863#endif
24864 node->set_isModified(true);
24865
24866 i++;
24867 }
24868 }
24869
24870
24871void
24873 {
24874 // DQ (10/23/2018): This reports the nodes in the AST that are marked as modified (isModified flag).
24875 // It is useful for debugging the token-based unparsing.
24876
24877 printf ("\n\n##################################################### \n");
24878 printf ("Report on modified statements: label = %s \n",label.c_str());
24879
24880 SgSourceFile* sourceFile = isSgSourceFile(node);
24881 if (sourceFile != NULL)
24882 {
24883 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24884 }
24885 else
24886 {
24887 SgGlobal* globalScope = isSgGlobal(node);
24888 if (globalScope != NULL)
24889 {
24890 sourceFile = isSgSourceFile(globalScope->get_parent());
24891 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24892 }
24893 }
24894
24895 ROSE_ASSERT(node != NULL);
24896 std::set<SgStatement*> collection = collectModifiedStatements(node);
24897
24898#if 0
24899 printf ("In reportModifiedStatements(): collection.size() = %zu \n",collection.size());
24900#endif
24901
24902 std::set<SgStatement*>::iterator i = collection.begin();
24903 while (i != collection.end())
24904 {
24905 // DQ (10/9/2019): Adding filename to debug output.
24906 string filename = (*i)->get_file_info()->get_filename();
24907
24908 // DQ (10/14/2019): Get the best name possible.
24909 if (filename == "transformation")
24910 {
24911#if 0
24912 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24913#endif
24914 // filename = (*i)->get_file_info()->get_physical_filename();
24915 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24916 if (sourceFile != NULL)
24917 {
24918 filename = sourceFile->getFileName();
24919 }
24920 }
24921
24922 printf (" --- filename = %s modified statement = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24923
24924 i++;
24925 }
24926
24927#if 1
24928 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
24929 // output spew else the message output at the top of this function will scroll off the screen.
24930 printf ("########################################################## \n");
24931 printf ("reportModifiedStatements(): Called using label = %s \n",label.c_str());
24932#endif
24933 printf ("########################################################## \n\n\n");
24934
24935#if 0
24936 printf ("Exiting as a test! \n");
24937 ROSE_ASSERT(false);
24938#endif
24939 }
24940
24941
24942
24943void
24945 {
24946 // DQ (6/21/2021): This reports the nodes in the AST that are marked as modified (isModified flag).
24947 // It is useful for debugging the token-based unparsing.
24948
24949 printf ("\n\n##################################################### \n");
24950 printf ("Report on modified locatedNodes: label = %s \n",label.c_str());
24951
24952 SgSourceFile* sourceFile = isSgSourceFile(node);
24953 if (sourceFile != NULL)
24954 {
24955 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24956 }
24957 else
24958 {
24959 SgGlobal* globalScope = isSgGlobal(node);
24960 if (globalScope != NULL)
24961 {
24962 sourceFile = isSgSourceFile(globalScope->get_parent());
24963 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24964 }
24965 }
24966
24967 ROSE_ASSERT(node != NULL);
24968 std::set<SgLocatedNode*> collection = collectModifiedLocatedNodes(node);
24969
24970#if 0
24971 printf ("In reportModifiedLocatedNode(): collection.size() = %zu \n",collection.size());
24972#endif
24973
24974 std::set<SgLocatedNode*>::iterator i = collection.begin();
24975 while (i != collection.end())
24976 {
24977 // DQ (10/9/2019): Adding filename to debug output.
24978 string filename = (*i)->get_file_info()->get_filename();
24979
24980 // DQ (10/14/2019): Get the best name possible.
24981 if (filename == "transformation")
24982 {
24983#if 0
24984 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24985#endif
24986 // filename = (*i)->get_file_info()->get_physical_filename();
24987 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24988 if (sourceFile != NULL)
24989 {
24990 filename = sourceFile->getFileName();
24991 }
24992 }
24993
24994 printf (" --- filename = %s modified locatedNode = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24995
24996 i++;
24997 }
24998
24999#if 1
25000 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
25001 // output spew else the message output at the top of this function will scroll off the screen.
25002 printf ("########################################################## \n");
25003 printf ("reportModifiedLocatedNodes(): Called using label = %s \n",label.c_str());
25004#endif
25005 printf ("########################################################## \n\n\n");
25006
25007#if 0
25008 printf ("Exiting as a test! \n");
25009 ROSE_ASSERT(false);
25010#endif
25011 }
25012
25013
25014
25015
25016// DQ (3/22/2019): Translate CPP directives from attached preprocessor information to CPP Directive Declaration IR nodes.
25017
25018void
25020 {
25021 // Debugging function to print out comments in the statements (added by DQ)
25022
25023 ROSE_ASSERT(locatedNode != NULL);
25024 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
25025
25026#if 0
25027 curprint ("/* Inside of printOutComments() */");
25028#endif
25029
25030 if (comments != NULL)
25031 {
25032#if 0
25033 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25034 curprint ("/* Inside of printOutComments(): comments != NULL */");
25035#endif
25036
25037 AttachedPreprocessingInfoType::iterator i;
25038 for (i = comments->begin(); i != comments->end(); i++)
25039 {
25040 ROSE_ASSERT ( (*i) != NULL );
25041 printf (" Attached Comment (relativePosition=%s): %s \n",
25042 // DQ (2/11/2021): Fixed to report correct relative locations.
25043 // ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25044 PreprocessingInfo::relativePositionName((*i)->getRelativePosition()).c_str(),
25045 (*i)->getString().c_str());
25046 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
25047 // curprint (string("/* Inside of printOutComments(): comments = ") + (*i)->getString() + " */");
25048
25049#if 0
25050 (*i)->get_file_info()->display("comment/directive location");
25051#endif
25052 }
25053 }
25054 else
25055 {
25056#if 0
25057 printf ("In SageInterface::printOutComments(): No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25058#endif
25059 }
25060 }
25061
25062
25063
25064bool
25066 {
25067 bool returnValue = false;
25068
25069 ROSE_ASSERT(currentPreprocessingInfo != NULL);
25070
25071 PreprocessingInfo::DirectiveType directive = currentPreprocessingInfo->getTypeOfDirective();
25072
25073 if (directive == PreprocessingInfo::C_StyleComment ||
25074 directive == PreprocessingInfo::CplusplusStyleComment ||
25075 directive == PreprocessingInfo::FortranStyleComment ||
25076 directive == PreprocessingInfo::CpreprocessorBlankLine ||
25077 directive == PreprocessingInfo::ClinkageSpecificationStart ||
25078 directive == PreprocessingInfo::ClinkageSpecificationEnd)
25079 {
25080 returnValue = true;
25081 }
25082
25083 return returnValue;
25084 }
25085
25086std::vector<SgC_PreprocessorDirectiveStatement*>
25088 {
25089 std::vector<SgC_PreprocessorDirectiveStatement*> directiveList;
25090
25091 // Find existing first and last header.
25092 AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo();
25093
25094 if (comments != nullptr)
25095 {
25096 AttachedPreprocessingInfoType::iterator i; // , firsti, lasti;
25097 for (i = comments->begin (); i != comments->end(); i++)
25098 {
25099 if (skipTranslateToUseCppDeclaration(*i) == true)
25100 {
25101 // 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).
25102 }
25103 else
25104 {
25105 SgC_PreprocessorDirectiveStatement* directive = SgC_PreprocessorDirectiveStatement::createDirective(*i);
25106 ROSE_ASSERT(directive != NULL);
25107 directiveList.push_back(directive);
25108 }
25109
25110 printf ("directiveList.size() = %zu \n",directiveList.size());
25111 }
25112 }
25113
25114 return directiveList;
25115 }
25116
25117
25118void
25120 {
25121 bool declarationsOnly = scope->containsOnlyDeclarations();
25122
25123 printf ("In translateScopeToUseCppDeclarations(): declarationsOnly = %s scope = %p = %s \n",declarationsOnly ? "true" : "false",scope,scope->class_name().c_str());
25124
25125 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> > directiveMap;
25126
25127 if (declarationsOnly == true)
25128 {
25129 // These are scopes such as global scope, namespace definitions, class definitions, etc.
25130 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
25131 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
25132 while (i != declarationList.end())
25133 {
25134 SgDeclarationStatement* declaration = *i;
25135 ROSE_ASSERT(declaration != NULL);
25136
25137 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(declaration,scope);
25138
25139 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25140
25141 if (attachDirectives.empty() == false)
25142 {
25143 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(declaration,attachDirectives));
25144 }
25145
25146 i++;
25147 }
25148
25149 // Need to save the list of things that will be added so we can avoid iterator invalidation.
25150 }
25151 else
25152 {
25153 // These are scopes such as SgBasicBlock (which can contain non-declaration statements.
25154 SgStatementPtrList & statementList = scope->getStatementList();
25155 SgStatementPtrList::iterator i = statementList.begin();
25156 while (i != statementList.end())
25157 {
25158 SgStatement* statement = *i;
25159 ROSE_ASSERT(statement != NULL);
25160
25161 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(statement,scope);
25162
25163 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25164
25165 if (attachDirectives.empty() == false)
25166 {
25167 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(statement,attachDirectives));
25168 }
25169
25170 i++;
25171 }
25172 }
25173
25174 printf ("directiveMap.size() = %zu \n",directiveMap.size());
25175
25176 printf ("Processing the directiveMap: \n");
25177 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >::iterator i = directiveMap.begin();
25178 while (i != directiveMap.end())
25179 {
25180 SgStatement* statement = i->first;
25181 std::vector<SgC_PreprocessorDirectiveStatement*> directives = i->second;
25182
25183 printf ("statement = %p = %s \n",statement,statement->class_name().c_str());
25184 printf ("directives.size() = %zu \n",directives.size());
25185 // std::vector<SgC_PreprocessorDirectiveStatement*>::reverse_iterator j = directives.begin();
25186 std::vector<SgC_PreprocessorDirectiveStatement*>::iterator j = directives.begin();
25187 while (j != directives.end())
25188 {
25189 scope->insert_statement(statement,*j);
25190
25191 j++;
25192 }
25193
25194 // Remove the directives there were attached to the statement.
25195 AttachedPreprocessingInfoType *comments = statement->getAttachedPreprocessingInfo();
25196 ROSE_ASSERT(comments != NULL);
25197
25198 AttachedPreprocessingInfoType deleteList;
25199 // std::vector<PreprocessingInfo*> deleteList;
25200
25201 // comments->erase();
25202 // statement->setAttachedPreprocessingInfo(NULL);
25203 AttachedPreprocessingInfoType::iterator k;
25204 for (k = comments->begin(); k != comments->end(); k++)
25205 {
25206#if 1
25207 ROSE_ASSERT ( (*k) != NULL );
25208 printf (" Attached Comment (relativePosition=%s): %s\n",
25209 ((*k)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25210 (*k)->getString().c_str());
25211 printf ("translateScopeToUseCppDeclarations(): Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*k)->getNumberOfLines(),(*k)->getColumnNumberOfEndOfString());
25212#endif
25213
25214 // We only want to process the CPP directives (skipping comments and a few othr kinds of obscure directives).
25215 if (skipTranslateToUseCppDeclaration(*k) == true)
25216 {
25217 // 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).
25218 printf ("Do NOT delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25219 }
25220 else
25221 {
25222 printf ("DO delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25223
25224 deleteList.push_back(*k);
25225 // delete *k;
25226 // *k = NULL;
25227 }
25228 }
25229
25230 printf ("Iterate over the deleteList: deleteList.size() = %zu comments->size() = %zu \n",deleteList.size(),comments->size());
25231 AttachedPreprocessingInfoType::iterator m = deleteList.begin();
25232 while (m != deleteList.end())
25233 {
25234 // comments->erase(m);
25235 // std::remove(comments->begin(), comments->end(), *m);
25236 comments->erase(std::remove(comments->begin(), comments->end(), *m), comments->end());
25237
25238 printf (" --- comments->size() = %zu \n",comments->size());
25239
25240 m++;
25241 }
25242
25243 // comments->clear();
25244 // delete comments; // statement->getAttachedPreprocessingInfoPtr();
25245 // statement->set_attachedPreprocessingInfoPtr(NULL);
25246
25247 i++;
25248 }
25249
25250 printf ("Leaving translateScopeToUseCppDeclarations(): scope = %p = %s \n",scope,scope->class_name().c_str());
25251 }
25252
25253
25254void
25256 {
25257 class CppTranslationTraversal : public AstSimpleProcessing
25258 {
25259 public:
25260 CppTranslationTraversal() {}
25261 void visit (SgNode* node)
25262 {
25263 printf ("In CppTranslationTraversal::visit(): node = %p = %s \n",node,node->class_name().c_str());
25264
25265 SgScopeStatement* scope = isSgScopeStatement(node);
25266 SgGlobal* globalScope = isSgGlobal(scope);
25267 if (globalScope != NULL)
25268 {
25269 printf ("In CppTranslationTraversal::visit(): processing scope = %p = %s \n",scope,scope->class_name().c_str());
25271 }
25272 else
25273 {
25274 if (scope != NULL)
25275 {
25276 printf ("In SageInterface::translateToUseCppDeclarations(): Currently skipping all but global scope! \n");
25277 }
25278 }
25279 }
25280 };
25281
25282 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
25283 CppTranslationTraversal traversal;
25284
25285 printf ("In translateToUseCppDeclarations(): Calling traversal.traverse() \n");
25286
25287 // We might want to do this traversla POSTORDER since we are transforming the AST at each scope.
25288 // traversal.traverse(n, preorder);
25289 traversal.traverse(n, postorder);
25290
25291 printf ("Leaving translateToUseCppDeclarations(): DONE: Calling traversal.traverse() \n");
25292 }
25293
25295{
25296 // print current level's info
25297 if (!n) return;
25298 cout<<"--------------"<<endl;
25299 cout<<n<<":"<<n->class_name()<< endl;
25300 if (SgLocatedNode * lnode = isSgLocatedNode(n))
25301 {
25302 cout<<"file info:\t ";
25303 lnode->get_file_info()->display();
25304 cout<<"\n unparseToString:\t ";
25305 lnode->unparseToString();
25306 }
25307
25308 // track back to its parent
25310}
25311// forward declaration is needed here,
25312//static void serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel);
25313
25314#if 0 // made it into a template function to handle various ptr lists in AST
25315// A special node in the AST text dump
25316static void serialize(SgTemplateArgumentPtrList& plist, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25317{
25318 out<<prefix;
25319 out<< (hasRemaining?"|---": "|___");
25320
25321// out<<"+"<<edgeLabel<<"+>";
25322 out<<" "<<edgeLabel<<" ->";
25323 // print address
25324 out<<"@"<<&plist<<" "<< "SgTemplateArgumentPtrList ";
25325
25326 out<<endl;
25327
25328 int last_non_null_child_idx =-1;
25329 for (int i = (int) (plist.size())-1; i>=0; i--)
25330 {
25331 if (plist[i])
25332 {
25333 last_non_null_child_idx = i;
25334 break;
25335 }
25336 }
25337
25338 for (size_t i=0; i< plist.size(); i++ )
25339 {
25340 bool n_hasRemaining=false;
25341#if 0
25342 if (i+1 < plist.size())
25343 n_hasRemaining=true;
25344#else
25345 if ((int)i< last_non_null_child_idx) n_hasRemaining = true;
25346#endif
25347 string suffix= hasRemaining? "| " : " ";
25348 string n_prefix = prefix+suffix;
25349 string n_edge_label="";
25350 if (plist[i])
25351 serialize (plist[i], n_prefix, n_hasRemaining, out,n_edge_label);
25352 }
25353}
25354#endif
25355
25356// print essential information from any AST node
25357// hasRemaining if this node has a sibling node to be visited next.
25358void SageInterface::serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25359{
25360 // there may be NULL children!!
25361 //if (!node) return;
25362
25363 out<<prefix;
25364 out<< (hasRemaining?"|---": "|___");
25365
25366 out<<" "<<edgeLabel<<" ->";
25367 if (!node)
25368 {
25369 out<<" NULL "<<endl;
25370 return;
25371 }
25372
25373 // print address
25374 out<<"@"<<node<<" "<< node->class_name()<<" ";
25375
25376 //optionally file info
25377 if (SgLocatedNode* lnode= isSgLocatedNode(node))
25378 {
25379 //Rose::StringUtility::stripPathFromFileName()
25380 out<< lnode->get_file_info()->get_filename() <<" "<<lnode->get_file_info()->get_line()<<":"<<lnode->get_file_info()->get_col();
25381 // also preprocessing info. attached.
25382 AttachedPreprocessingInfoType *comments =
25383 lnode->getAttachedPreprocessingInfo ();
25384
25385 if (comments != NULL)
25386 {
25387// printf ("Found an IR node with preprocessing Info attached:\n");
25388 out<<" AttachedPreprocessingInfoType@"<<comments;
25389 int counter = 0;
25390 AttachedPreprocessingInfoType::iterator i;
25391 out <<"{";
25392 for (i = comments->begin (); i != comments->end (); i++)
25393 {
25394 if (i!=comments->begin ())
25395 out<<endl;
25396 out<<"<id=";
25397 out<<counter++<<" ";
25398 // printf("-------------PreprocessingInfo #%d ----------- : \n",counter++);
25399 // printf("classification = %s:\n String format = %s\n",
25400 // PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str (),
25401 // (*i)->getString ().c_str ());
25402 if (*i==NULL)
25403 out<<" NULL="; // The AST may be in the middle of transformation, with NULL comments attached.
25404 else
25405 {
25406 out<<*i<<" classification="<<PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str ();
25407 out<<" string="<<(*i)->getString ().c_str ();
25408 out<<" relative pos=" ; // << (*i)->getRelativePosition ();
25409#if 1
25410 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
25411 out<<"inside";
25412 else if ((*i)->getRelativePosition () == PreprocessingInfo::before)
25413 out<<"before";
25414 else
25415 out<<"after";
25416#endif
25417 }
25418 out<<">";
25419 }
25420 out <<"}";
25421 }
25422 }
25423
25424 if (SgDeclarationStatement* v= isSgDeclarationStatement(node))
25425 {
25426 out<<" first nondefining decl@"<< v->get_firstNondefiningDeclaration();
25427 out<<" defining decl@"<< v->get_definingDeclaration();
25428 }
25429
25430 if (SgEnumVal* f = isSgEnumVal(node) )
25431 out<<" value="<< f->get_value() <<" declaration="<<f->get_declaration() << " name="<< f->get_name().getString();
25432 // optionally qualified name
25433
25434 if (SgFunctionDeclaration* f = isSgFunctionDeclaration(node) )
25435 out<<" "<< f->get_qualified_name();
25436
25437 if (SgAdaFunctionRenamingDecl* f = isSgAdaFunctionRenamingDecl(node) )
25438 out<<" renamed_function "<< f->get_renamed_function();
25439
25440 if (SgAdaRenamingDecl* f = isSgAdaRenamingDecl(node) )
25441 out<<" name="<< f->get_name() << " renamed decl "<<f->get_renamed() ;
25442
25443 if (SgClassDeclaration* f = isSgClassDeclaration(node) )
25444 out<<" "<< f->get_qualified_name();
25445
25446 if (SgTypedefDeclaration* f = isSgTypedefDeclaration(node) )
25447 out<<" "<< f->get_qualified_name();
25448
25449 if (SgAdaPackageSpecDecl * f = isSgAdaPackageSpecDecl(node) )
25450 out<<" "<< f->get_qualified_name();
25451
25452 if (SgAdaEnumRepresentationClause* f = isSgAdaEnumRepresentationClause(node) )
25453 out<<" enumType="<< f->get_enumType();
25454
25455 if (SgAdaAccessType* v = isSgAdaAccessType(node) )
25456 {
25457 // out<<" "<< v->get_qualified_name();
25458 //out<<" "<< v->get_name();
25459 // PP (2/18/22) updated to reflect properties in AdaAccessType
25460 //~ out<<" is_object_type"<< v->get_is_object_type();
25461 out<<" is_general_access"<< v->get_is_general_access();
25462 //~ out<<" is_constant:"<< v->get_is_constant();
25463 //~ out<<" is_protected:"<< v->get_is_protected ();
25464 out<<" is_anonymous:"<< v->get_is_anonymous ();
25465 }
25466
25467 if (SgAdaSubroutineType* v = isSgAdaSubroutineType(node) )
25468 {
25469 out<<" is_protected"<< v->get_is_protected();
25470 }
25471
25472 if (SgInitializedName * v = isSgInitializedName(node) )
25473 {
25474 out<<" "<< v->get_qualified_name();
25475 out<<" type@"<< v->get_type();
25476 out<<" initializer@"<< v->get_initializer();
25477 out<<" scope@"<< v->get_scope();
25478// type_set.insert (v->get_type());
25479 }
25480
25481 // associated class, function and variable declarations
25482 if (SgTemplateInstantiationDecl* f = isSgTemplateInstantiationDecl(node) )
25483 out<<" template class decl@"<< f->get_templateDeclaration();
25484
25485 if (SgMemberFunctionDeclaration* f = isSgMemberFunctionDeclaration(node) )
25486 out<<" assoc. class decl@"<< f->get_associatedClassDeclaration();
25487
25488 if (SgConstructorInitializer* ctor= isSgConstructorInitializer(node) )
25489 {
25490 out<<" member function decl@"<< ctor->get_declaration();
25491 }
25492
25493 if (SgIntVal* v= isSgIntVal(node))
25494 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25495
25496 if (SgShortVal* v= isSgShortVal(node))
25497 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25498
25499 if (SgLongIntVal* v= isSgLongIntVal(node))
25500 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25501
25502 if (SgLongLongIntVal* v= isSgLongLongIntVal(node))
25503 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25504
25505 if (SgUnsignedIntVal* v= isSgUnsignedIntVal(node))
25506 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25507
25508 if (SgUnsignedShortVal* v= isSgUnsignedShortVal(node))
25509 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25510
25511 if (SgUnsignedLongVal* v= isSgUnsignedLongVal(node))
25512 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25513
25514 if (SgUnsignedLongLongIntVal* v= isSgUnsignedLongLongIntVal(node))
25515 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25516
25517 if (SgFloatVal* v= isSgFloatVal(node))
25518 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25519
25520 if (SgDoubleVal* v= isSgDoubleVal(node))
25521 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25522
25523 if (SgLongDoubleVal* v= isSgLongDoubleVal(node))
25524 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25525
25526 if (SgVarRefExp* var_ref= isSgVarRefExp(node) )
25527 out<<" init name@"<< var_ref->get_symbol()->get_declaration() <<" symbol name="<<var_ref->get_symbol()->get_name();
25528
25529 if (SgMemberFunctionRefExp* func_ref= isSgMemberFunctionRefExp(node) )
25530 out<<" member func decl@"<< func_ref->get_symbol_i()->get_declaration();
25531
25532 if (SgTemplateInstantiationMemberFunctionDecl* cnode= isSgTemplateInstantiationMemberFunctionDecl(node) )
25533 out<<" template member func decl@"<< cnode->get_templateDeclaration();
25534
25535 if (SgFunctionRefExp* func_ref= isSgFunctionRefExp(node) )
25536 {
25537 SgFunctionSymbol* sym= func_ref->get_symbol_i();
25538 out<<" func decl@"<< sym->get_declaration() << " func sym name="<<sym->get_name();
25539 }
25540
25541 if (SgAdaRenamingRefExp* renaming_ref= isSgAdaRenamingRefExp(node) )
25542 {
25543 SgAdaRenamingDecl * renaming_decl = renaming_ref->get_decl();
25544 out<<" ada renaming decl@"<< renaming_decl;
25545 }
25546
25547 // base type of several types of nodes:
25548 if (SgTypedefDeclaration * v= isSgTypedefDeclaration(node))
25549 {
25550 out<<" base_type@"<< v->get_base_type();
25551// type_set.insert (v->get_base_type());
25552 }
25553
25554 if (SgArrayType* v= isSgArrayType(node))
25555 out<<" base_type@"<< v->get_base_type();
25556
25557 if (SgAdaAccessType* v= isSgAdaAccessType(node))
25558 out<<" base_type@"<< v->get_base_type();
25559
25560 if (SgTypeExpression* v= isSgTypeExpression(node))
25561 out<<" type@"<< v->get_type();
25562
25563 if (SgAdaAttributeExp* v= isSgAdaAttributeExp(node))
25564 out<<" attribute@"<< v->get_attribute();
25565
25566 if (SgUsingDirectiveStatement* v= isSgUsingDirectiveStatement(node))
25567 out<<" namespaceDeclaration="<< v->get_namespaceDeclaration();
25568
25569 out<<endl;
25570
25571 std::vector<SgNode* > children = node->get_traversalSuccessorContainer();
25572#if 0
25573 int total_count = children.size();
25574 int current_index=0;
25575#endif
25576
25577 int last_non_null_child_idx =-1;
25578 for (int i = (int) (children.size())-1; i>=0; i--)
25579 {
25580 if (children[i])
25581 {
25582 last_non_null_child_idx = i;
25583 break;
25584 }
25585 }
25586
25587#if 0
25588 // some Sg??PtrList are not AST nodes, not part of children , we need to handle them separatedly
25589 // we sum all children into single total_count to tell if there is remaining children.
25590 if (isSgTemplateInstantiationDecl (node))
25591 total_count += 1; // sn->get_templateArguments().size();
25592#endif
25593
25594 // handling SgTemplateArgumentPtrList first
25595 if (SgTemplateInstantiationDecl* sn = isSgTemplateInstantiationDecl (node))
25596 {
25597 SgTemplateArgumentPtrList& plist = sn->get_templateArguments();
25598 bool n_hasRemaining=false;
25599 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25600 string suffix= hasRemaining? "| " : " ";
25601 string n_prefix = prefix+suffix;
25602 string n_edge_label= "";
25603 serialize_list(plist, "SgTemplateArgumentPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25604 }
25605 else if (SgImportStatement* import_stmt = isSgImportStatement(node))
25606 {
25607 SgExpressionPtrList& plist = import_stmt->get_import_list();
25608 bool n_hasRemaining=false;
25609 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25610 string suffix= hasRemaining? "| " : " ";
25611 string n_prefix = prefix+suffix;
25612 string n_edge_label= "";
25613 serialize_list(plist, "SgExpressionPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25614 }
25615
25616 std::vector< std::string > successorNames= node->get_traversalSuccessorNamesContainer();
25617
25618 // finish sucessors
25619 for (size_t i =0; i< children.size(); i++)
25620 {
25621 bool n_hasRemaining=false;
25622#if 0
25623 if (current_index+1<total_count)
25624 n_hasRemaining=true;
25625 current_index++;
25626#else
25627 if ((int)i<last_non_null_child_idx) n_hasRemaining = true;
25628#endif
25629 string suffix= hasRemaining? "| " : " ";
25630 string n_prefix = prefix+suffix;
25631 if (children[i])
25632 serialize (children[i], n_prefix, n_hasRemaining, out, successorNames[i]);
25633 }
25634}
25635
25637{
25638 ostringstream oss;
25639 string prefix;
25640 string label="";
25641 serialize(node, prefix, false, oss, label);
25642 cout<<oss.str();
25643}
25644
25645void SageInterface::printAST(SgNode* node, const char* filename)
25646{
25647 printAST2TextFile(node, filename, true);
25648}
25649
25650void SageInterface::printAST2TextFile (SgNode* node, std::string filename, bool printType/*=true*/)
25651{
25652 // Rasmussen 9/21/2020: This leads to infinite recursion (clang warning message) and should be removed from API)
25653// ROSE_ABORT();
25654 printAST2TextFile (node, filename.c_str(), printType);
25655}
25656
25657void SageInterface::printAST2TextFile(SgNode* node, const char* filename, bool printType/*=true*/)
25658{
25659 ostringstream oss;
25660 string prefix;
25661 string label="";
25662 serialize(node, prefix, false, oss, label);
25663 ofstream textfile;
25664 textfile.open(filename, ios::out);
25665 textfile<<oss.str();
25666
25667 if (printType)
25668 {
25669 // append type information also
25670 textfile<<"Types encountered ...."<<endl;
25671 ostringstream oss2;
25672 VariantVector vv(V_SgType);
25673 Rose_STL_Container<SgNode*> tnodes= NodeQuery::queryMemoryPool(vv);
25674 for (Rose_STL_Container<SgNode*>::const_iterator i = tnodes.begin(); i != tnodes.end(); ++i)
25675 {
25676 serialize (*i, prefix, false, oss2, label);
25677 }
25678 textfile<<oss2.str();
25679 }
25680
25681 textfile.close();
25682}
25683
25685{
25686 saveToPDF(node, string("temp.pdf.json") );
25687}
25689// node to find its enclosing file node. The entire file's AST will be saved into a pdf.
25690void SageInterface:: saveToPDF(SgNode* node, std::string filename)
25691{
25692 ROSE_ASSERT(node != NULL);
25693 AstJSONGeneration json;
25694 json.generateWithinFile(filename, getEnclosingFileNode(node));
25695}
25696
25698{
25699 bool rtval = false;
25700 ROSE_ASSERT (node != NULL);
25701 Sg_File_Info* finfo = node->get_file_info();
25702 if (finfo!=NULL)
25703 {
25704 string fname = finfo->get_filenameString();
25705 string buildtree_str1 = string("include-staging/gcc_HEADERS");
25706 string buildtree_str2 = string("include-staging/g++_HEADERS");
25707 string installtree_str1 = string("include/edg/gcc_HEADERS");
25708 string installtree_str2 = string("include/edg/g++_HEADERS");
25709 string system_headers = string("/usr/include");
25710 // if the file name has a sys header path of either source or build tree
25711 if ((fname.find (buildtree_str1, 0) != string::npos) ||
25712 (fname.find (buildtree_str2, 0) != string::npos) ||
25713 (fname.find (installtree_str1, 0) != string::npos) ||
25714 (fname.find (installtree_str2, 0) != string::npos) ||
25715 (fname.find (system_headers, 0) != string::npos)
25716 )
25717 rtval = true;
25718 }
25719 return rtval;
25720}
25721
25722
25723// DQ (2/27/2021): Adding support to detect if a SgLocatedNode is located in a header file.
25725 {
25726 // Check if a node is from a header file
25727
25728 bool returnValue = false;
25729
25730 Sg_File_Info* fileInfo = node->get_file_info();
25731 ROSE_ASSERT(fileInfo != NULL);
25732 string filename = fileInfo->get_filenameString();
25733
25734#if 0
25735 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());
25736#endif
25737
25738 // DQ (2/27/2021): We save a map of all of the header files processed in the generation of the ROSE AST,
25739 // so the test is only if the filename is in the list.
25740 if (EDG_ROSE_Translation::edg_include_file_map.find(filename) == EDG_ROSE_Translation::edg_include_file_map.end())
25741 {
25742#if 0
25743 printf ("This is NOT in the EDG_ROSE_Translation::edg_include_file_map \n");
25744#endif
25745 }
25746 else
25747 {
25748#if 0
25749 printf ("This IS in the EDG_ROSE_Translation::edg_include_file_map \n");
25750#endif
25751 returnValue = true;
25752 }
25753
25754 return returnValue;
25755 }
25756
25757
25760{
25761 ROSE_ASSERT(return_type != NULL);
25762 ROSE_ASSERT(typeList != NULL);
25764 ROSE_ASSERT(fTable);
25765
25766 // This function make clever use of a static member function which can't be built
25767 // for the case of a SgMemberFunctionType (or at least not without more work).
25768 SgName typeName = SgFunctionType::get_mangled(return_type, typeList);
25769 SgFunctionType* funcType = isSgFunctionType(fTable->lookup_function_type(typeName));
25770
25771 return funcType;
25772}
25773
25778{
25779 ROSE_ASSERT (lhs != NULL);
25780 ROSE_ASSERT (rhs != NULL);
25781 if (lhs == rhs)
25782 return true;
25783
25784 bool rt = false;
25785 SgType* rt1 = lhs->get_return_type();
25786 SgType* rt2 = rhs->get_return_type();
25787
25788 if (isEquivalentType (rt1, rt2))
25789 {
25790 SgTypePtrList f1_arg_types = lhs->get_arguments();
25791 SgTypePtrList f2_arg_types = rhs->get_arguments();
25792 // Must have same number of argument types
25793 if (f1_arg_types.size() == f2_arg_types.size())
25794 {
25795 // DQ (2/16/2017): Fixed compiler warning about comparison between signed and unsigned integers
25796 // int counter = 0;
25797 size_t counter = 0;
25798 // iterate through all argument types
25799 // for (int i=0; i< f1_arg_types.size(); i++)
25800 for (size_t i=0; i< f1_arg_types.size(); i++)
25801 {
25802 if (isEquivalentType (f1_arg_types[i], f2_arg_types[i]) )
25803 counter ++; // count the number of equal arguments
25804 else
25805 break; // found different type? jump out the loop
25806 }
25807 // all arguments are equivalent, set to true
25808 if (counter == f1_arg_types.size())
25809 rt = true;
25810 }
25811 } // end if equivalent return types
25812
25813 return rt;
25814}
25815
25816bool
25818 {
25819 // This function is called in the SgType::isEquivalentType (const SgType & Y) const function.
25820
25821 // DQ (11/28/2015): A better goal for this function should be to define it as a recursive function.
25822
25823 // DQ (12/8/2015): We need to add support for SgMemberFunctionType as demonstrated by test2007_17.C.
25824 // and for SgTemplateType as demonstrated by tests/nonsmoke/functional/CompileTests/RoseExample_tests/testRoseHeaders_03.C
25825 // Note that this is only required within the change to use this isEquivalentType() function in the
25826 // support to replace:
25827 // templateParameterOrArgumentLocal->get_initializedName()->get_type() == templateParameterOrArgumentFromSymbol->get_initializedName()->get_type()
25828 // in ROSETTA/Grammar/Support.code
25829
25830 ROSE_ASSERT(lhs != NULL);
25831 ROSE_ASSERT(rhs != NULL);
25832
25833 bool isSame = false;
25834
25835 // 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).
25836 static int counter = 0;
25837
25838 const SgType & X = *lhs;
25839 const SgType & Y = *rhs;
25840
25841 // DQ (11/28/2015): We don't want to strip off everything.
25842 // SgType* stripType(unsigned char bit_array = STRIP_MODIFIER_TYPE | STRIP_REFERENCE_TYPE | STRIP_POINTER_TYPE | STRIP_ARRAY_TYPE | STRIP_TYPEDEF_TYPE ) const;
25843
25844 // I think we need to compute the type chain to evaluate equalence.
25845 // Rose_STL_Container< SgType*> getInternalTypes () const
25846
25847#define DEBUG_TYPE_EQUIVALENCE 0
25848
25849#if DEBUG_TYPE_EQUIVALENCE
25850 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25851 printf (" --- lhs = %s \n",lhs->unparseToString().c_str());
25852 printf (" --- rhs = %s \n",rhs->unparseToString().c_str());
25853#endif
25854
25855#if DEBUG_TYPE_EQUIVALENCE || 0
25856 if (counter == 0)
25857 {
25858 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25859 printf (" --- lhs = %p = %s = %s \n",lhs,lhs->class_name().c_str(),lhs->unparseToString().c_str());
25860 printf (" --- rhs = %p = %s = %s \n",rhs,rhs->class_name().c_str(),rhs->unparseToString().c_str());
25861 }
25862#endif
25863
25864#if DEBUG_TYPE_EQUIVALENCE || 0
25865 // Debugging output.
25866 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
25867 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
25868
25869 // Debugging output.
25870 printf ("Output of type chain for lhs: \n");
25871 for (size_t i = 0; i < X_typeChain.size(); i++)
25872 {
25873 SgType* element_type = X_typeChain[i];
25874 printf ("X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25875 printf (" --- X_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25876 SgModifierType* modifierType = isSgModifierType(element_type);
25877 if (modifierType != NULL)
25878 {
25879 // modifierType->get_typeModifier().display("X type chain");
25880 string s = modifierType->get_typeModifier().displayString();
25881 printf (" --- type chain modifier: %s \n",s.c_str());
25882 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25883 }
25884 }
25885
25886 printf ("Output of type chain for rhs: \n");
25887 for (size_t i = 0; i < Y_typeChain.size(); i++)
25888 {
25889 SgType* element_type = Y_typeChain[i];
25890 printf ("Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25891 printf (" --- Y_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25892 SgModifierType* modifierType = isSgModifierType(element_type);
25893 if (modifierType != NULL)
25894 {
25895 // modifierType->get_typeModifier().display("Y type chain");
25896 string s = modifierType->get_typeModifier().displayString();
25897 printf (" --- type chain modifier: %s \n",s.c_str());
25898 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25899 }
25900 }
25901#endif
25902
25903 // Increment the static variable to control the recursive depth while we debug this.
25904 counter++;
25905
25906 // DQ (11/28/2015): exit with debug output instead of infinte recursion.
25907 // if (counter >= 280)
25908 // if (counter >= 500)
25909 if (counter >= 280)
25910 {
25911 // 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());
25912 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);
25913 }
25914
25915 // DQ (12/23/2015): ASC application code requires this to be increased to over 122 (selected 300 for extra margin of safety).
25916 // DQ (11/28/2015): exit in stead of infinte recursion.
25917 // if (counter > 300)
25918 // if (counter > 600)
25919 // if (counter > 5000)
25920 // if (counter > 300)
25921 if (counter > 350)
25922 {
25923 // DQ (11/28/2015): I think this is a reasonable limit.
25924 printf ("ERROR: In SageInterface::isEquivalentType(): recursive limit exceeded for : counter = %d \n",counter);
25925 ROSE_ABORT();
25926 }
25927
25928 // bool exit = false;
25929
25930 // Strip off any typedefs since they are equivalent by definition.
25931 SgType* X_element_type = X.stripType( SgType::STRIP_TYPEDEF_TYPE );
25932 SgType* Y_element_type = Y.stripType( SgType::STRIP_TYPEDEF_TYPE );
25933
25934 // DQ (11/29/2015): We need to handle references (when they are both references we can support then uniformally).
25935 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
25936 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
25937
25938 if (X_referenceType != NULL && Y_referenceType != NULL)
25939 {
25940 X_element_type = X_referenceType->get_base_type();
25941 Y_element_type = Y_referenceType->get_base_type();
25942
25943 counter--;
25944
25945 // Recursive call.
25946 // return (*X_element_type) == (*Y_element_type);
25947 return isEquivalentType(X_element_type,Y_element_type);
25948 }
25949 else
25950 {
25951 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25952 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
25953 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
25954
25955 if (X_pointerType != NULL && Y_pointerType != NULL)
25956 {
25957 X_element_type = X_pointerType->get_base_type();
25958 Y_element_type = Y_pointerType->get_base_type();
25959
25960 counter--;
25961
25962 // Recursive call.
25963 // return (*X_element_type) == (*Y_element_type);
25964 return isEquivalentType(X_element_type,Y_element_type);
25965 }
25966 else
25967 {
25968 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25969 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
25970 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
25971
25972 // DQ (12/8/2015): We need to check that the array size is the same.
25973 if (X_arrayType != NULL && Y_arrayType != NULL)
25974 {
25975 X_element_type = X_arrayType->get_base_type();
25976 Y_element_type = Y_arrayType->get_base_type();
25977
25978 SgExpression* X_array_index_expression = X_arrayType->get_index();
25979 SgExpression* Y_array_index_expression = Y_arrayType->get_index();
25980
25981 if (X_array_index_expression == Y_array_index_expression)
25982 {
25983#if DEBUG_TYPE_EQUIVALENCE || 0
25984 printf ("In SageInterface::isEquivalentType(): counter = %d: Need to check the array size for static equivalence \n",counter);
25985#endif
25986 counter--;
25987
25988 // Recursive call.
25989 // return (*X_element_type) == (*Y_element_type);
25990 return isEquivalentType(X_element_type,Y_element_type);
25991 }
25992 else
25993 {
25994 // Need more complex test for expression equivalence.
25995#if DEBUG_TYPE_EQUIVALENCE || 0
25996 printf ("In SageInterface::isEquivalentType(): counter = %d Need more complex test for expression equivalence \n",counter);
25997 string str1 = X_array_index_expression->unparseToString();
25998 string str2 = Y_array_index_expression->unparseToString();
25999 printf (" --- array index expressions: str1 = %s str2 = %s \n",str1.c_str(),str2.c_str());
26000#endif
26001 // DQ (12/9/2016): Need to decriment the counter as part of recursive function call.
26002 counter--;
26003
26004 // Recursive call.
26005 return isEquivalentType(X_element_type,Y_element_type);
26006 }
26007 }
26008 else
26009 {
26010 // DQ (12/15/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26011 SgNonrealType* X_templateType = isSgNonrealType(X_element_type);
26012 SgNonrealType* Y_templateType = isSgNonrealType(Y_element_type);
26013
26014 // DQ (12/15/2015): We need to check that the array size is the same.
26015 if (X_templateType != NULL && Y_templateType != NULL)
26016 {
26017 string X_name = X_templateType->get_name();
26018 string Y_name = Y_templateType->get_name();
26019
26020 SgNonrealDecl* X_templateDecl = isSgNonrealDecl(X_templateType->get_declaration());
26021 ROSE_ASSERT(X_templateDecl != NULL);
26022 SgNonrealDecl* Y_templateDecl = isSgNonrealDecl(Y_templateType->get_declaration());
26023 ROSE_ASSERT(Y_templateDecl != NULL);
26024
26025 int X_template_parameter_position = X_templateDecl->get_template_parameter_position();
26026 int Y_template_parameter_position = Y_templateDecl->get_template_parameter_position();
26027
26028 SgNode * X_parent = X_templateDecl->get_parent();
26029 SgNode * Y_parent = Y_templateDecl->get_parent();
26030
26031#if DEBUG_TYPE_EQUIVALENCE
26032 SgNode * X_parent_parent = X_parent ? X_parent->get_parent() : NULL;
26033 SgNode * Y_parent_parent = Y_parent ? Y_parent->get_parent() : NULL;
26034 printf ("In SageInterface::isEquivalentType(): case SgNonrealType:\n");
26035 printf (" -- X_name = %s Y_name = %s\n", X_name.c_str(),Y_name.c_str());
26036 printf (" -- X_template_parameter_position = %d Y_template_parameter_position = %d\n", X_template_parameter_position,Y_template_parameter_position);
26037 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() : "");
26038 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() : "");
26039 printf (" -- X_templateDecl->get_mangled_name() = %s\n", X_templateDecl->get_mangled_name().str());
26040 printf (" -- Y_templateDecl->get_mangled_name() = %s\n", Y_templateDecl->get_mangled_name().str());
26041#endif
26042 bool value = (X_parent == Y_parent);
26043
26044 if (value && X_templateDecl->get_is_template_param() && Y_templateDecl->get_is_template_param()) {
26045 value = (X_template_parameter_position == Y_template_parameter_position);
26046 } else if (value && X_templateDecl->get_is_class_member() && Y_templateDecl->get_is_class_member()) {
26047 value = (X_name == Y_name);
26048 }
26049
26050 counter--;
26051
26052 return value;
26053 }
26054 else
26055 {
26056 // DQ (2/13/2018): I an unclear if we are really done since they could have resolved to different types or the same type.
26057 // Nothing to do here since we have explored all uniform pairs of intermediate types possible.
26058#if 0
26059 printf ("Nothing to do here since we have explored all uniform pairs of intermediate types possible: isSame = %s \n",isSame ? "true" : "false");
26060 // printf (" --- X_element_type = %p = %s \n",X_element_type,X_element_type->unparseToString().c_str());
26061 // printf (" --- Y_element_type = %p = %s \n",Y_element_type,Y_element_type->unparseToString().c_str());
26062 printf (" --- lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26063 printf (" --- rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26064#endif
26065#if DEBUG_TYPE_EQUIVALENCE
26066 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");
26067#endif
26068 }
26069 }
26070 }
26071 } // end if reference type, pointer type, array type, and template type
26072
26073 SgModifierType* X_modifierType = isSgModifierType(X_element_type);
26074 SgModifierType* Y_modifierType = isSgModifierType(Y_element_type);
26075
26076#if DEBUG_TYPE_EQUIVALENCE
26077 printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %p = %s Y_element_type = %p = %s \n",
26078 counter,X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26079#endif
26080
26081 if (X_modifierType != NULL && Y_modifierType != NULL)
26082 {
26083 // Handle the case of both modifiers.
26084#if DEBUG_TYPE_EQUIVALENCE
26085 printf ("In SageInterface::isEquivalentType(): loop: these are the both SgModifierType nodes: isSame = %s \n",isSame ? "true" : "false");
26086#endif
26087 if (X_modifierType == Y_modifierType)
26088 {
26089 isSame = true;
26090#if DEBUG_TYPE_EQUIVALENCE
26091 printf ("In SageInterface::isEquivalentType(): loop: these are the same modifier type: isSame = %s \n",isSame ? "true" : "false");
26092#endif
26093 }
26094 else
26095 {
26096 if (X_modifierType->get_typeModifier() == Y_modifierType->get_typeModifier())
26097 {
26098#if DEBUG_TYPE_EQUIVALENCE
26099 printf ("In SageInterface::isEquivalentType(): loop: these are equivalent modifiers: check the base type: isSame = %s \n",isSame ? "true" : "false");
26100#endif
26101 // Recursive call.
26102 // isSame = (*X_modifierType->get_base_type()) == (*Y_modifierType->get_base_type());
26103 isSame = isEquivalentType(X_modifierType->get_base_type(),Y_modifierType->get_base_type());
26104 }
26105 else
26106 {
26107#if DEBUG_TYPE_EQUIVALENCE
26108 printf ("In SageInterface::isEquivalentType(): loop: these are not equivalent modifier types: check for default settings: isSame = %s \n",isSame ? "true" : "false");
26109#endif
26110 // DQ (5/22/2016): fixing bug which cansed infinite recursion (case there the SgModifiers were different).
26111 bool skippingOverIdentityModifier = false;
26112
26113 if (X_modifierType->get_typeModifier().isIdentity() == true)
26114 {
26115#if DEBUG_TYPE_EQUIVALENCE
26116 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26117#endif
26118 X_element_type = X_modifierType->get_base_type();
26119
26120 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26121 skippingOverIdentityModifier = true;
26122 }
26123
26124 if (Y_modifierType->get_typeModifier().isIdentity() == true)
26125 {
26126#if DEBUG_TYPE_EQUIVALENCE
26127 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26128#endif
26129 Y_element_type = Y_modifierType->get_base_type();
26130
26131 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26132 skippingOverIdentityModifier = true;
26133 }
26134
26135 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26136#if DEBUG_TYPE_EQUIVALENCE
26137 printf ("In SageInterface::isEquivalentType(): loop: skippingOverIdentityModifier = %s \n",skippingOverIdentityModifier ? "true" : "false");
26138#endif
26139 // Recursive call on non-default modifier base types.
26140 // isSame = (*X_element_type) == (*Y_element_type);
26141 // isSame = isEquivalentType(X_element_type,Y_element_type);
26142 if (skippingOverIdentityModifier == true)
26143 {
26144#if DEBUG_TYPE_EQUIVALENCE
26145 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");
26146#endif
26147 // If we have made progress in skipping over an identity modifier then we need to reevaluate if these are the equivalent types.
26148 isSame = isEquivalentType(X_element_type,Y_element_type);
26149 }
26150 else
26151 {
26152 // 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).
26153 isSame = false;
26154#if DEBUG_TYPE_EQUIVALENCE
26155 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");
26156#endif
26157 }
26158
26159#if DEBUG_TYPE_EQUIVALENCE
26160 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isSame = %s \n",isSame ? "true" : "false");
26161#endif
26162 }
26163 }
26164 }
26165 else
26166 {
26167 // At least one of these is not a SgModifierType.
26168
26169 if (X_modifierType != NULL || Y_modifierType != NULL)
26170 {
26171 bool isReduceable = false;
26172
26173 if (X_modifierType != NULL && X_modifierType->get_typeModifier().isIdentity() == true)
26174 {
26175#if DEBUG_TYPE_EQUIVALENCE
26176 printf ("In SageInterface::isEquivalentType(): loop: found default setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26177#endif
26178 X_element_type = X_modifierType->get_base_type();
26179 isReduceable = true;
26180 }
26181
26182 if (Y_modifierType != NULL && Y_modifierType->get_typeModifier().isIdentity() == true)
26183 {
26184#if DEBUG_TYPE_EQUIVALENCE
26185 printf ("In SageInterface::isEquivalentType(): loop: found default setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26186#endif
26187 Y_element_type = Y_modifierType->get_base_type();
26188 isReduceable = true;
26189 }
26190
26191 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26192#if DEBUG_TYPE_EQUIVALENCE
26193 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s \n",isReduceable ? "true" : "false");
26194#endif
26195 if (isReduceable == true)
26196 {
26197 // Recursive call on non-default modifier base types.
26198 // isSame = (*X_element_type) == (*Y_element_type);
26199 isSame = isEquivalentType(X_element_type,Y_element_type);
26200 }
26201 else
26202 {
26203 // Neither of these types were reducable.
26204 isSame = false;
26205 }
26206
26207#if DEBUG_TYPE_EQUIVALENCE
26208 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s isSame = %s \n",
26209 isReduceable ? "true" : "false",isSame ? "true" : "false");
26210#endif
26211 }
26212 else
26213 {
26214 // Neither of these are SgModifierType nodes.
26215 // X_element_type = X_element_type->stripType( STRIP_TYPEDEF_TYPE );
26216 // Y_element_type = Y_element_type->stripType( STRIP_TYPEDEF_TYPE );
26217
26218 if (X_element_type == Y_element_type)
26219 {
26220 isSame = true;
26221#if DEBUG_TYPE_EQUIVALENCE || 0
26222 // printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s \n",isSame ? "true" : "false");
26223 printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s lhs = %p = %s rhs = %p = %s \n",
26224 isSame ? "true" : "false",lhs,lhs->unparseToString().c_str(),rhs,rhs->unparseToString().c_str());
26225#endif
26226#if DEBUG_TYPE_EQUIVALENCE || 0
26227 // DQ (2/13/2018): Debugging type equivalence. If they are the same typedef, they
26228 // still might not be interchangable if one is defined in a restrcited scope.
26229 const SgTypedefType* lhs_typedefType = isSgTypedefType(lhs);
26230 const SgTypedefType* rhs_typedefType = isSgTypedefType(rhs);
26231
26232 if (lhs_typedefType != NULL || rhs_typedefType != NULL)
26233 {
26234#if 0
26235 if (lhs_typedefType != NULL)
26236 {
26237 printf ("lhs was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26238 }
26239 if (rhs_typedefType != NULL)
26240 {
26241 printf ("rhs was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26242 }
26243#else
26244 printf (" --- one was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26245 printf (" --- one was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26246#endif
26247 }
26248#endif
26249 }
26250 else
26251 {
26252 // DQ (3/20/2016): This is reported by GNU as set but not used.
26253 // bool isReduceable = false;
26254
26255 // DQ (11/29/2015): We need to handle reference (when they are both references we can support then uniformally).
26256 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26257 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26258
26259 if (X_referenceType != NULL || Y_referenceType != NULL)
26260 {
26261#if 0
26262 if (X_referenceType != NULL)
26263 {
26264 X_element_type = X_referenceType->get_base_type();
26265
26266 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26267 // isReduceable = true;
26268 isReduceable = false;
26269 }
26270
26271 if (Y_referenceType != NULL)
26272 {
26273 Y_element_type = Y_referenceType->get_base_type();
26274
26275 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26276 // isReduceable = true;
26277 isReduceable = false;
26278 }
26279
26280 if (isReduceable == true)
26281 {
26282 // Recursive call on non-default modifier base types.
26283 // isSame = (*X_element_type) == (*Y_element_type);
26284 isSame = isEquivalentType(X_element_type,Y_element_type);
26285 }
26286 else
26287 {
26288 // Neither of these types were reducable.
26289 isSame = false;
26290 }
26291#else
26292 isSame = false;
26293#endif
26294 }
26295 else
26296 {
26297 // Recursive call on non-typedef base types.
26298 // isSame = (*X_element_type) == (*Y_element_type);
26299 // isSame = isEquivalentType(X_element_type,Y_element_type);
26300
26301#if DEBUG_TYPE_EQUIVALENCE
26302 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26303#endif
26304
26305 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26306 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26307 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26308
26309 if (X_pointerType != NULL || Y_pointerType != NULL)
26310 {
26311#if 0
26312 if (X_pointerType != NULL)
26313 {
26314 X_element_type = X_pointerType->get_base_type();
26315
26316 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26317 // isReduceable = true;
26318 isReduceable = false;
26319 }
26320
26321 if (Y_pointerType != NULL)
26322 {
26323 Y_element_type = Y_pointerType->get_base_type();
26324
26325 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26326 // isReduceable = true;
26327 isReduceable = false;
26328 }
26329
26330 if (isReduceable == true)
26331 {
26332 // Recursive call on non-default modifier base types.
26333 // isSame = (*X_element_type) == (*Y_element_type);
26334 isSame = isEquivalentType(X_element_type,Y_element_type);
26335 }
26336 else
26337 {
26338 // Neither of these types were reducable.
26339 isSame = false;
26340 }
26341#else
26342 isSame = false;
26343#endif
26344 }
26345 else
26346 {
26347 // Recursive call on non-typedef base types.
26348 // isSame = (*X_element_type) == (*Y_element_type);
26349 // isSame = isEquivalentType(X_element_type,Y_element_type);
26350
26351#if DEBUG_TYPE_EQUIVALENCE
26352 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26353#endif
26354
26355 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26356 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26357 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26358
26359 if (X_arrayType != NULL || Y_arrayType != NULL)
26360 {
26361#if 0
26362 if (X_arrayType != NULL)
26363 {
26364 X_element_type = X_arrayType->get_base_type();
26365
26366 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26367 // isReduceable = true;
26368 isReduceable = false;
26369 }
26370
26371 if (Y_arrayType != NULL)
26372 {
26373 Y_element_type = Y_arrayType->get_base_type();
26374
26375 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26376 // isReduceable = true;
26377 isReduceable = false;
26378 }
26379
26380 if (isReduceable == true)
26381 {
26382 // Recursive call on non-default modifier base types.
26383 // isSame = (*X_element_type) == (*Y_element_type);
26384 isSame = isEquivalentType(X_element_type,Y_element_type);
26385 }
26386 else
26387 {
26388 // Neither of these types were reducable.
26389 isSame = false;
26390 }
26391#else
26392 isSame = false;
26393#endif
26394 }
26395 else
26396 {
26397 // Recursive call on non-typedef base types.
26398 // isSame = (*X_element_type) == (*Y_element_type);
26399 // isSame = isEquivalentType(X_element_type,Y_element_type);
26400
26401#if DEBUG_TYPE_EQUIVALENCE
26402 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26403#endif
26404
26405 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26406 SgFunctionType* X_functionType = isSgFunctionType(X_element_type);
26407 SgFunctionType* Y_functionType = isSgFunctionType(Y_element_type);
26408
26409 if (X_functionType != NULL || Y_functionType != NULL)
26410 {
26411 bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (X_functionType == Y_functionType) );
26412 //TODO: Liao, 9/15/2016, better comparison of function types
26413 //bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (isEquivalentFunctionType(X_functionType, Y_functionType)) );
26414#if DEBUG_TYPE_EQUIVALENCE || 0
26415 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgFunctionType: value = %s \n",value ? "true" : "false");
26416#endif
26417 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26418 // isSame == value;
26419 isSame = value;
26420
26421 // DQ (3/20/2016): This is reported by GNU as set but not used.
26422 // isReduceable = false;
26423 }
26424 else
26425 {
26426 // Recursive call on non-typedef base types.
26427 // isSame = isEquivalentType(X_element_type,Y_element_type);
26428
26429 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26430 SgMemberFunctionType* X_memberFunctionType = isSgMemberFunctionType(X_element_type);
26431 SgMemberFunctionType* Y_memberFunctionType = isSgMemberFunctionType(Y_element_type);
26432
26433 if (X_memberFunctionType != NULL || Y_memberFunctionType != NULL)
26434 {
26435 // DQ (12/15/2015): This code should be unreachable since it would have executed the code above (the case of SgFunctionType).
26436 printf ("This should be unreachable code \n");
26437 ROSE_ABORT();
26438
26439#if 0 // [Robb Matzke 2021-03-24]: unreachable
26440 bool value = ( (X_memberFunctionType != NULL && Y_memberFunctionType != NULL) && (X_memberFunctionType == Y_memberFunctionType) );
26441#if DEBUG_TYPE_EQUIVALENCE || 0
26442 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgMemberFunctionType: value = %s \n",value ? "true" : "false");
26443#endif
26444 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26445 // isSame == value;
26446 isSame = value;
26447#endif
26448 }
26449 else
26450 {
26451 // Recursive call on non-typedef base types.
26452 // isSame = isEquivalentType(X_element_type,Y_element_type);
26453#if 0
26454 // Check for irreducable types.
26455 bool X_isReduceable = true;
26456 if (isSgTypeSignedLong(X_element_type) != NULL ||
26457 isSgTypeUnsignedInt(X_element_type) != NULL ||
26458 isSgTypeBool(X_element_type) != NULL ||
26459 isSgTypeInt(X_element_type) != NULL)
26460 {
26461 X_isReduceable = false;
26462 }
26463
26464 bool Y_isReduceable = true;
26465 if (isSgTypeSignedLong(Y_element_type) != NULL ||
26466 isSgTypeUnsignedInt(Y_element_type) != NULL ||
26467 isSgTypeBool(Y_element_type) != NULL ||
26468 isSgTypeInt(Y_element_type) != NULL)
26469 {
26470 Y_isReduceable = false;
26471 }
26472#if DEBUG_TYPE_EQUIVALENCE || 0
26473 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_isReduceable = %s Y_isReduceable = %s \n",
26474 X_isReduceable ? "true" : "false",Y_isReduceable ? "true" : "false");
26475#endif
26476 if (X_isReduceable == true || Y_isReduceable == true)
26477 {
26478 // Recursive call on non-default modifier base types.
26479 isSame = isEquivalentType(X_element_type,Y_element_type);
26480 }
26481 else
26482 {
26483 // Neither of these types were reducable.
26484 isSame = false;
26485 }
26486#else
26487 // DQ (12/20/2015): This is the default case for irreducable types.
26488 if (X_element_type->variantT() == Y_element_type->variantT())
26489 {
26490#if DEBUG_TYPE_EQUIVALENCE || 0
26491 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_element_type = %p = %s Y_element_type = %p = %s \n",
26492 X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26493#endif
26494 // DQ (5/26/2016): It is not good enough that the variants match.
26495 // isSame = true;
26496 // isSame = isEquivalentType(X_element_type,Y_element_type);
26497 isSame = (X_element_type == Y_element_type);
26498 }
26499 else
26500 {
26501 // Neither of these types were reducable or equal.
26502 isSame = false;
26503 }
26504#endif
26505 }
26506 }
26507 }
26508 }
26509 }
26510 }
26511 }
26512 }
26513
26514 // Decrement the static variable to control the recursive depth while we debug this.
26515 counter--;
26516
26517#if DEBUG_TYPE_EQUIVALENCE || 0
26518 printf ("In SageInterface::isEquivalentType(): isSame = %s \n",isSame ? "true" : "false");
26519#endif
26520
26521#if DEBUG_TYPE_EQUIVALENCE || 0
26522 if (counter == 1 && isSame == true)
26523 {
26524 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());
26525
26526 // Debugging output.
26527 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26528 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26529
26530 // Debugging output.
26531 printf (" --- Output of type chain for lhs: \n");
26532 for (size_t i = 0; i < X_typeChain.size(); i++)
26533 {
26534 SgType* element_type = X_typeChain[i];
26535 printf (" --- --- X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26536 SgModifierType* modifierType = isSgModifierType(element_type);
26537 if (modifierType != NULL)
26538 {
26539 // modifierType->get_typeModifier().display("X type chain");
26540 string s = modifierType->get_typeModifier().displayString();
26541 printf (" --- type chain modifier: %s \n",s.c_str());
26542 }
26543 }
26544
26545 printf (" --- Output of type chain for rhs: \n");
26546 for (size_t i = 0; i < Y_typeChain.size(); i++)
26547 {
26548 SgType* element_type = Y_typeChain[i];
26549 printf (" --- --- Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26550 SgModifierType* modifierType = isSgModifierType(element_type);
26551 if (modifierType != NULL)
26552 {
26553 // modifierType->get_typeModifier().display("Y type chain");
26554 string s = modifierType->get_typeModifier().displayString();
26555 printf (" --- --- type chain modifier: %s \n",s.c_str());
26556 }
26557 }
26558 }
26559#endif
26560
26561#if 0
26562 if (counter == 0)
26563 {
26564 if (isSame == true)
26565 {
26566 // 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());
26567 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26568 // printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26569 // printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26570 printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26571 printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26572 }
26573 else
26574 {
26575 // 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());
26576 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26577 }
26578 }
26579 else
26580 {
26581 printf (" --- counter = %d \n",counter);
26582 }
26583#endif
26584
26585 return isSame;
26586 }
26587
26588
26589#if 0
26590// This is modified to be a template function and so must be moved to the header file.
26591// DQ (8/30/2016): Added function to detect EDG AST normalization.
26592bool
26593SageInterface::isNormalizedTemplateInstantiation (SgFunctionDeclaration* function)
26594 {
26595 // This function is called in the Call graph generation to avoid filtering out EDG normalized
26596 // function template instnatiations (which come from normalized template functions and member functions).
26597
26598 bool retval = false;
26599
26600#if 1
26601 // DQ (8/30/2016): We need to mark this as an EDG normalization so that we can detect it as an exception
26602 // to some simple attempts to filter the AST (e.g. for the Call Graph implementation which filters on only
26603 // functions in the current directory). This explicit makring makes it much easier to get this test correct.
26604 // But we still need to look at if the location of the parent template is something that we wnat to output.
26605 // If tis is a template instantiation then it is not enough to look only at the non-defining declaration if
26606 // it is not compiler generated.
26607 retval = function->get_marked_as_edg_normalization();
26608#else
26609 // Test for this to be a template instantation (in which case it was marked as
26610 // compiler generated but we may want to allow it to be used in the call graph,
26611 // if it's template was a part was defined in the current directory).
26612 SgTemplateInstantiationFunctionDecl* templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(function);
26613 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(function);
26614
26615 if (templateInstantiationFunction != NULL)
26616 {
26617 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26618 templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(templateInstantiationFunction->get_firstNondefiningDeclaration());
26619 SgTemplateFunctionDeclaration* templateFunctionDeclaration = templateInstantiationFunction->get_templateDeclaration();
26620 if (templateFunctionDeclaration != NULL)
26621 {
26622 // retval = operator()(templateFunctionDeclaration);
26623 retval = (templateFunctionDeclaration->isCompilerGenerated() == false);
26624 }
26625 else
26626 {
26627 // Assume false.
26628 }
26629
26630#if DEBUG_SELECTOR
26631 printf (" --- case of templateInstantiationFunction: retval = %s \n",retval ? "true" : "false");
26632#endif
26633 }
26634 else
26635 {
26636 if (templateInstantiationMemberFunction != NULL)
26637 {
26638 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26639 templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(templateInstantiationMemberFunction->get_firstNondefiningDeclaration());
26640 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = templateInstantiationMemberFunction->get_templateDeclaration();
26641 if (templateMemberFunctionDeclaration != NULL)
26642 {
26643 // retval = operator()(templateMemberFunctionDeclaration);
26644 retval = (templateMemberFunctionDeclaration->isCompilerGenerated() == false);
26645 }
26646 else
26647 {
26648 // Assume false.
26649 }
26650
26651#if DEBUG_SELECTOR
26652 printf (" --- case of templateInstantiationMemberFunction: retval = %s \n",retval ? "true" : "false");
26653#endif
26654 }
26655 }
26656#endif
26657
26658 return retval;
26659 }
26660#endif
26661
26662void SageInterface::detectCycleInType(SgType * type, const std::string & from) {
26663#if 0
26664 printf("In detectCycleInType():\n");
26665 printf(" -- from = %s\n", from.c_str());
26666 printf(" -- type = %p (%s)\n", type, type->class_name().c_str());
26667#endif
26668 std::vector<SgType *> seen_types;
26669
26670 while (type != NULL) {
26671
26672 // DQ (4/15/2019): Added assertion.
26673 ROSE_ASSERT(type != NULL);
26674
26675 std::vector<SgType *>::const_iterator it = std::find(seen_types.begin(), seen_types.end(), type);
26676 if (it != seen_types.end()) {
26677 printf("ERROR: Cycle found in type = %p (%s):\n", type, type->class_name().c_str());
26678 size_t i = 0;
26679 for (; it != seen_types.end(); it++) {
26680 printf(" [%zd] %p (%s)\n", i, *it, (*it)->class_name().c_str());
26681 i++;
26682 }
26683 printf("-> detectCycleInType() was called from: %s\n", from.c_str());
26684 ROSE_ABORT();
26685 }
26686 seen_types.push_back(type);
26687
26688 SgModifierType * modType = isSgModifierType(type);
26689 SgPointerType * pointType = isSgPointerType(type);
26690 SgReferenceType * refType = isSgReferenceType(type);
26691 SgArrayType * arrayType = isSgArrayType(type);
26692 SgTypedefType * typedefType = isSgTypedefType(type);
26693
26694#if 0
26695 // DQ (4/15/2019): Don't count SgPointerMemberType (also fixed in SgType::stripType() function).
26696 if (isSgPointerMemberType(type) != NULL)
26697 {
26698 pointType = NULL;
26699 }
26700#endif
26701
26702 if ( modType ) {
26703 type = modType->get_base_type();
26704 } else if ( refType ) {
26705 type = refType->get_base_type();
26706 } else if ( pointType ) {
26707 type = pointType->get_base_type();
26708 // } else if ( pointerMemberType ) {
26709 // type = pointerMemberType->get_base_type();
26710 } else if ( arrayType ) {
26711 type = arrayType->get_base_type();
26712 } else if ( typedefType ) {
26713 type = typedefType->get_base_type();
26714 } else {
26715 break;
26716 }
26717 ROSE_ASSERT(type != NULL);
26718 }
26719}
26720
26721
26722#if 0
26723// DQ (11/10/2019): Older original version of the function.
26724
26725// DQ (6/6/2019): Move this to the SageInteface namespace.
26726void
26728 {
26729 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
26730 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
26731 // declarations in the outlined code we can support the outpiled code with those references. This
26732 // approach has the added advantage of also supporting the same include file tree as the original
26733 // file where the outlined code is being taken from.
26734
26735 class TransformFunctionDefinitionsTraversal : public AstSimpleProcessing
26736 {
26737 public:
26738 std::vector<SgFunctionDeclaration*> functionList;
26739 SgSourceFile* sourceFile;
26740 int sourceFileId;
26741 string filenameWithPath;
26742
26743 public:
26744 TransformFunctionDefinitionsTraversal(): sourceFile(NULL), sourceFileId(-99) {}
26745
26746 void visit (SgNode* node)
26747 {
26748#if 0
26749 printf ("In convertFunctionDefinitionsToFunctionPrototypes visit(): node = %p = %s \n",node,node->class_name().c_str());
26750#endif
26751 SgSourceFile* temp_sourceFile = isSgSourceFile(node);
26752 if (temp_sourceFile != NULL)
26753 {
26754 sourceFile = temp_sourceFile;
26755 sourceFileId = sourceFile->get_file_info()->get_file_id();
26756
26757 // The file_id is not sufficnet, not clear why, but the filenames match.
26758 filenameWithPath = sourceFile->get_sourceFileNameWithPath();
26759
26760 printf ("Found source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26761
26762 }
26763
26764 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
26765 if (functionDeclaration != NULL)
26766 {
26767 // This should have been set already.
26768 ROSE_ASSERT(sourceFile != NULL);
26769
26770 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
26771 if (functionDeclaration == definingFunctionDeclaration)
26772 {
26773#if 1
26774 printf ("Found a defining function declaration: functionDeclaration = %p = %s name = %s \n",
26775 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26776
26777 printf (" --- recorded source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26778 printf (" --- source file: file_info: id = %d name = %s \n",
26779 functionDeclaration->get_file_info()->get_file_id(),functionDeclaration->get_file_info()->get_filenameString().c_str());
26780#endif
26781 // DQ (3/20/2019): The file_id is not sufficent, using the filename with path to do string equality.
26782 // bool isInSourceFile = (sourceFileId == functionDeclaration->get_file_info()->get_file_id());
26783 bool isInSourceFile = (filenameWithPath == functionDeclaration->get_file_info()->get_filenameString());
26784#if 1
26785 printf (" --- isInSourceFile = %s \n",isInSourceFile ? "true" : "false");
26786#endif
26787 // Remove the defining declaration as a test.
26788 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
26789 if (isInSourceFile == true && functionDeclarationScope != NULL)
26790 {
26791#if 1
26792 printf (" --- Found a defining function declaration: functionDeclarationScope = %p = %s \n",
26793 functionDeclarationScope,functionDeclarationScope->class_name().c_str());
26794#endif
26795 // functionDeclarationScope->removeStatement(functionDeclaration);
26796 // removeStatement(functionDeclaration);
26797 functionList.push_back(functionDeclaration);
26798 }
26799 }
26800 }
26801 }
26802 };
26803
26804 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
26805 TransformFunctionDefinitionsTraversal traversal;
26806 traversal.traverse(node, preorder);
26807
26808 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
26809
26810#if 1
26811 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): functionList.size() = %zu \n",functionList.size());
26812#endif
26813
26814 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
26815 while (i != functionList.end())
26816 {
26817 SgFunctionDeclaration* functionDeclaration = *i;
26818 ROSE_ASSERT(functionDeclaration != NULL);
26819
26820 SgFunctionDeclaration* nondefiningFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
26821 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26822
26823#if 1
26824 printf (" --- Removing function declaration: functionDeclaration = %p = %s name = %s \n",
26825 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26826#endif
26827 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
26828 // removeStatement(functionDeclaration);
26829 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration);
26830
26831 i++;
26832 }
26833
26834#if 0
26835 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): exiting as a test! \n");
26836 ROSE_ABORT();
26837#endif
26838 }
26839#endif
26840
26841
26842void
26844 {
26845 // DQ (10/31/2020): Display function for scopes (useful for debugging).
26846 ROSE_ASSERT(scope != NULL);
26847
26848 printf ("Output the statements in scope = %p = %s \n",scope,scope->class_name().c_str());
26849
26850 // This makes a copy (on the stack) and is inefficent, but this is only for debugging.
26851 SgStatementPtrList statementList = scope->generateStatementList();
26852 for (size_t i = 0; i < statementList.size(); i++)
26853 {
26854 SgStatement* statement = statementList[i];
26855 printf (" --- statement: %zu ptr: %p IR node: %s name: %s \n",i,statement,statement->class_name().c_str(),SageInterface::get_name(statement).c_str());
26856 }
26857
26858#if 0
26859 printf ("Exiting as a test at the end of evaluation of global scope! \n");
26860 ROSE_ABORT();
26861#endif
26862 }
26863
26864
26867 {
26868 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
26869 // SgDeclarationStatement* nondefiningFunctionDeclaration = NULL;
26870
26871#if 0
26872 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p = %s name = %s \n",
26873 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26874#endif
26875
26876 // DQ (11/21/2019): Check if this is a constructor, this is a temporary fix.
26877 bool isConstructor = false;
26878 SgMemberFunctionDeclaration* tmp_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
26879 if (tmp_memberFunctionDeclaration != NULL)
26880 {
26881 isConstructor = tmp_memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
26882
26883#if 0
26884 if (isConstructor == true)
26885 {
26886 printf ("Skipping case of constructors (in building prototype from defining function declaration) \n");
26887 return;
26888 }
26889#endif
26890 }
26891
26892 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
26893 // bool replaceWithEmptyDeclaration = false;
26894 // SgDeclarationStatement* emptyDeclaration = NULL;
26895
26896 SgName name = functionDeclaration->get_name();
26897 SgType* return_type = functionDeclaration->get_type()->get_return_type();
26898
26899#if 0
26900 // DQ (12/10/2020): The issue is that the default arguments defined in template functions are represented in the AST.
26901 // Where we output the template as a string, it is included, and in the template instantiation it is represented in
26902 // the AST. So where it is used, default arguments are not represented in the AST and so the are not generated in
26903 // this function that builds the function prototype from the defining function.
26904
26905 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p \n",functionDeclaration);
26906 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
26907 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
26908
26909 // DQ (12/9/2020): Check if there is a default argument. Need to figure out how default arguments
26910 // are specified in the function declarations, and make sure the prototype reproduces them.
26911 for (size_t i = 0; i < functionDeclaration->get_args().size(); i++)
26912 {
26913 SgInitializedName* arg = functionDeclaration->get_args()[i];
26914#if 1
26915 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_args(): (i = %zu) arg = %p = %s isDefaultArgument = %s \n",
26916 i,arg,arg->get_name().str(),arg->get_file_info()->isDefaultArgument() ? "true" : "false");
26917 printf (" --- arg->get_initializer() = %p \n",arg->get_initializer());
26918#endif
26919 if (arg->get_file_info()->isDefaultArgument() == true)
26920 {
26921 printf ("NOTE: default argument (i = %zu) not reproduced in function prototype: arg = %p = %s \n",i,arg,arg->get_name().str());
26922 }
26923 }
26924#endif
26925
26926#if 1
26927 SgFunctionParameterList* param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26928#else
26929 // 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).
26930 // SgFunctionParameterList *param_list = functionDeclaration->get_parlist();
26931 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
26932 SgFunctionParameterList* param_list = NULL;
26933
26934 if (templateInstantiationFunctionDecl == NULL)
26935 {
26936 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26937 }
26938 else
26939 {
26940 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
26941 if (templateInstantiationMemberFunctionDecl == NULL)
26942 {
26943 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26944 }
26945 }
26946#endif
26947
26948
26949 // bool isTemplateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration) != NULL);
26950 bool isTemplateInstantiationMemberFunctionDecl = false;
26951
26952 SgScopeStatement* scope = functionDeclaration->get_scope();
26953 // SgTemplateParameterPtrList* templateParameterList = NULL; // functionDeclaration->get_templateParameterList();
26954 SgExprListExp* python_decoratorList = NULL;
26955 bool buildTemplateInstantiation = false;
26956 SgTemplateArgumentPtrList* templateArgumentsList = NULL;
26957
26958 // DQ (9/26/2019): Tracing down a null parent pointer.
26959 // ROSE_ASSERT(param_list->get_parent() != NULL);
26960 // ROSE_ASSERT(param_list->get_parent() == NULL);
26961 ROSE_ASSERT(param_list == NULL || param_list->get_parent() == NULL);
26962
26963 switch (functionDeclaration->variantT())
26964 {
26965 case V_SgTemplateMemberFunctionDeclaration:
26966 {
26967#if 0
26968 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template member functions \n");
26969#endif
26970 SgTemplateMemberFunctionDeclaration* original_templateMemberFunctionDeclaration = isSgTemplateMemberFunctionDeclaration(functionDeclaration);
26971 ROSE_ASSERT(original_templateMemberFunctionDeclaration != NULL);
26972
26973 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = NULL;
26974
26975 unsigned int functionConstVolatileFlags = 0;
26976
26977 ROSE_ASSERT(original_templateMemberFunctionDeclaration->get_type() != NULL);
26978
26979 // Need to call:
26980 // unsigned int get_mfunc_specifier();
26981
26982 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_templateMemberFunctionDeclaration->get_type());
26983 ROSE_ASSERT(memberFunctionType != NULL);
26984
26985 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
26986
26987 // SgTemplateMemberFunctionDeclaration*
26988 // buildNondefiningTemplateMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
26989 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList* templateParameterList );
26990
26991 SgTemplateParameterPtrList templateParameterList = original_templateMemberFunctionDeclaration->get_templateParameters();
26992 // ROSE_ASSERT(templateParameterList != NULL);
26993
26994 templateMemberFunctionDeclaration =
26995 buildNondefiningTemplateMemberFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags, &templateParameterList );
26996#if 0
26997 printf ("ERROR: Template functions are not yet supported! \n");
26998 ROSE_ABORT();
26999#endif
27000 nondefiningFunctionDeclaration = templateMemberFunctionDeclaration;
27001
27002 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27003
27004 // DQ (11/21/2019): Handle constructors.
27005 if (isConstructor == true)
27006 {
27007 templateMemberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27008 }
27009
27010 break;
27011 }
27012
27013 case V_SgTemplateFunctionDeclaration:
27014 {
27015#if 0
27016 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template functions \n");
27017#endif
27018 SgTemplateFunctionDeclaration* original_templateFunctionDeclaration = isSgTemplateFunctionDeclaration(functionDeclaration);
27019 ROSE_ASSERT(original_templateFunctionDeclaration != NULL);
27020
27021 SgTemplateFunctionDeclaration* templateFunctionDeclaration = NULL; // isSgTemplateFunctionDeclaration(functionDeclaration);
27022
27023 // SgTemplateFunctionDeclaration*
27024 // buildNondefiningTemplateFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27025 // SgScopeStatement* scope=NULL, SgExprListExp* decoratorList = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
27026
27027 SgTemplateParameterPtrList templateParameterList = original_templateFunctionDeclaration->get_templateParameters();
27028
27029 templateFunctionDeclaration = buildNondefiningTemplateFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, &templateParameterList );
27030#if 0
27031 printf ("ERROR: Template functions are not yet supported! \n");
27032 ROSE_ABORT();
27033#endif
27034 nondefiningFunctionDeclaration = templateFunctionDeclaration;
27035
27036 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27037
27038 break;
27039 }
27040
27041 // DQ (10/29/2020): Added new case.
27042 case V_SgTemplateInstantiationMemberFunctionDecl:
27043 {
27044 buildTemplateInstantiation = true;
27045
27046 isTemplateInstantiationMemberFunctionDecl = true;
27047
27048 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
27049 ROSE_ASSERT(templateInstantiationMemberFunctionDecl != NULL);
27050 templateArgumentsList = &(templateInstantiationMemberFunctionDecl->get_templateArguments());
27051#if 0
27052 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27053 // printf ("name from templateInstantiationMemberFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_template_name().str());
27054 printf ("name from templateInstantiationMemberFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_templateName().str());
27055 SgTemplateMemberFunctionDeclaration* templateDeclaration = templateInstantiationMemberFunctionDecl->get_templateDeclaration();
27056 if (templateDeclaration != NULL)
27057 {
27058 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27059 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27060 }
27061#endif
27062 // name = functionDeclaration->get_name();
27063 // name = templateInstantiationMemberFunctionDecl->get_template_name();
27064 name = templateInstantiationMemberFunctionDecl->get_templateName();
27065#if 0
27066 printf ("In case V_SgTemplateInstantiationMemberFunctionDecl: using name = %s \n",name.str());
27067#endif
27068 // DQ (10/29/2020): Change this to include the functionality to build the member function support without fall-through.
27069 }
27070 // fall through
27071 case V_SgMemberFunctionDeclaration:
27072 {
27073#if 0
27074 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support member functions \n");
27075#endif
27076 SgMemberFunctionDeclaration* original_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
27077 ROSE_ASSERT(original_memberFunctionDeclaration != NULL);
27078
27079 SgMemberFunctionDeclaration* memberFunctionDeclaration = NULL; // isSgMemberFunctionDeclaration(functionDeclaration);
27080
27081 // SgMemberFunctionDeclaration*
27082 // buildNondefiningMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27083 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList* templateArgumentsList);
27084
27085 unsigned int functionConstVolatileFlags = 0;
27086
27087 ROSE_ASSERT(original_memberFunctionDeclaration->get_type() != NULL);
27088
27089 // Need to call:
27090 // unsigned int get_mfunc_specifier();
27091
27092 // DQ (12/2/2019): If it is defined outside of the class, then don't replace with member function prototype,
27093 // since they is not allowed to be declared outside of the class they are a member of.
27094
27095 // We do want to build prototypes for template instantiation member functions, and template instantiation non-member functions (see below).
27096 bool buildPrototype = isTemplateInstantiationMemberFunctionDecl || original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope();
27097#if 0
27098 printf ("In SageInterface::buildFunctionPrototype(): buildPrototype = %s \n",buildPrototype ? "true" : "false");
27099#endif
27100 if (buildPrototype == true)
27101 {
27102 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_memberFunctionDeclaration->get_type());
27103 ROSE_ASSERT(memberFunctionType != NULL);
27104#if 0
27105 printf ("original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope() \n");
27106#endif
27107 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
27108
27109 memberFunctionDeclaration =
27111 ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags,
27112 buildTemplateInstantiation,templateArgumentsList );
27113#if 0
27114 printf ("ERROR: Member functions are not yet supported! \n");
27115 ROSE_ABORT();
27116#endif
27117 // DQ (11/21/2019): Handle constructors.
27118 if (isConstructor == true)
27119 {
27120 memberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27121 }
27122
27123 nondefiningFunctionDeclaration = memberFunctionDeclaration;
27124
27125 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27126 }
27127 else
27128 {
27129 // Case of member function defined outside of it's class.
27130#if 0
27131 printf ("NOTE: Member functions defined outside of their class can not be output as member function prototypes (not allowed in C++) \n");
27132#endif
27133 // We want to build a SgEmptyDeclaration using buildEmptyDeclaration() but this is not a function.
27134 // nondefiningFunctionDeclaration = buildEmptyDeclaration();
27135 nondefiningFunctionDeclaration = NULL;
27136#if 0
27137 nondefiningFunctionDeclaration = NULL;
27138
27139 replaceWithEmptyDeclaration = true;
27140 emptyDeclaration = buildEmptyDeclaration();
27141 ROSE_ASSERT(emptyDeclaration != NULL);
27142#endif
27143 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27144 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27145
27146 // Since we din't build a member function we don't need the parameter list.
27147 delete param_list;
27148 param_list = NULL;
27149#if 0
27150 printf ("Exiting as a test! \n");
27151 ROSE_ABORT();
27152#endif
27153 }
27154
27155 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27156 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27157 break;
27158 }
27159
27160 case V_SgFunctionDeclaration:
27161 {
27162 // This is for a non-member non-template function declaration.
27163 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27164 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27165 break;
27166 }
27167
27168 // DQ (10/29/2020): Added new case.
27169 case V_SgTemplateInstantiationFunctionDecl:
27170 {
27171 // This is for a non-member non-template function declaration.
27172 buildTemplateInstantiation = true;
27173 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27174 ROSE_ASSERT(templateInstantiationFunctionDecl != NULL);
27175 templateArgumentsList = &(templateInstantiationFunctionDecl->get_templateArguments());
27176#if 0
27177 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27178 // printf ("name from templateInstantiationFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationFunctionDecl->get_template_name().str());
27179 printf ("name from templateInstantiationFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationFunctionDecl->get_templateName().str());
27180 SgTemplateFunctionDeclaration* templateDeclaration = templateInstantiationFunctionDecl->get_templateDeclaration();
27181 if (templateDeclaration != NULL)
27182 {
27183 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27184 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27185 }
27186#endif
27187 name = templateInstantiationFunctionDecl->get_templateName();
27188#if 0
27189 printf ("In case V_SgTemplateInstantiationFunctionDecl: using name = %s \n",name.str());
27190#endif
27191 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27192 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27193 break;
27194 }
27195
27196 default:
27197 {
27198 // DQ (12/4/2019): If this is any other case than that handled above, then we just return.
27199 // These cases would be only template instantiations.
27200
27201 // Nothing to do, except delete the parameter list we built, and return.
27202 delete param_list;
27203 param_list = NULL;
27204
27205 return NULL;
27206 }
27207 }
27208
27209 // DQ (10/29/2020): We should be able to change this now that we support SgTemplateInstantiationFunctionDecl and SgTemplateInstantiationMemberFunctionDecl IR nodes.
27210 // DQ (9/26/2019): Tracing down a null parent pointer.
27211 ROSE_ASSERT(param_list == NULL || param_list->get_parent() != NULL);
27212 // ROSE_ASSERT(param_list != NULL);
27213 // ROSE_ASSERT(param_list->get_parent() != NULL);
27214
27215 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27216
27217 if (nondefiningFunctionDeclaration != NULL)
27218 {
27219 if (nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() == NULL)
27220 {
27221#if 0
27222 printf ("Setting the firstNondefiningDeclaration \n");
27223#endif
27224 nondefiningFunctionDeclaration->set_firstNondefiningDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27225 }
27226
27227 if (nondefiningFunctionDeclaration->get_definingDeclaration() == NULL)
27228 {
27229#if 0
27230 printf ("Setting the definingDeclaration \n");
27231#endif
27232 nondefiningFunctionDeclaration->set_definingDeclaration(functionDeclaration->get_definingDeclaration());
27233 }
27234
27235 ROSE_ASSERT(nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() != NULL);
27236 ROSE_ASSERT(nondefiningFunctionDeclaration->get_definingDeclaration() != NULL);
27237
27238 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27239 if (nondefiningFunctionDeclaration != NULL)
27240 {
27241 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27242 // This is a bug in the support for building a new prototype from a defining function declaration
27243 // and caused this problem. This assertion will prevent this sort of error from happening again.
27244 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27245 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27246 }
27247 }
27248
27249 return nondefiningFunctionDeclaration;
27250 }
27251
27252
27253// 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).
27256 {
27257 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27258 ROSE_ASSERT(functionDeclaration != NULL);
27259
27260#if 0
27261 printf ("****************************************************************** \n");
27262 printf ("Attached comments and CPP directives: defining functionDeclaration \n");
27263 SageInterface::printOutComments (functionDeclaration);
27264 printf ("****************************************************************** \n");
27265#endif
27266
27267 // 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.
27268
27269 nondefiningFunctionDeclaration = buildFunctionPrototype(functionDeclaration);
27270
27271 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27272 if (nondefiningFunctionDeclaration != NULL)
27273 {
27274 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27275 // This is a bug in the support for building a new prototype from a defining function declaration
27276 // and caused this problem. This assertion will prevent this sort of error from happening again.
27277 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27278 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27279 }
27280
27281 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27282
27283 if (templateInstantiationFunctionDecl == NULL)
27284 {
27285 if (nondefiningFunctionDeclaration != NULL)
27286 {
27287 // DQ (10/29/2020): Match the associated declaration modifiers.
27288 nondefiningFunctionDeclaration->get_declarationModifier() = functionDeclaration->get_declarationModifier();
27289
27290 // DQ (11/11/2020): Match the associated other kinds of modifiers.
27291 nondefiningFunctionDeclaration->get_functionModifier() = functionDeclaration->get_functionModifier();
27292 nondefiningFunctionDeclaration->get_specialFunctionModifier() = functionDeclaration->get_specialFunctionModifier();
27293
27294 nondefiningFunctionDeclaration->set_linkage( functionDeclaration->get_linkage() );
27295 nondefiningFunctionDeclaration->set_externBrace( functionDeclaration->get_externBrace() );
27296
27297 ROSE_ASSERT(nondefiningFunctionDeclaration->get_forward() == true);
27298
27299 // DQ (10/15/2019): Set the physical_file_id of the transformation to match that of the original defining declaration.
27300 int file_id = functionDeclaration->get_file_info()->get_physical_file_id();
27301 nondefiningFunctionDeclaration->get_file_info()->set_physical_file_id(file_id);
27302
27303 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27304 // removeStatement(functionDeclaration);
27305 // DQ (11/22/2020): Note that this step will move the comments and CPP directives to the new statement
27306 // (better in this step than in the copy of the pointer to the list above, which cause an iterator invalidation error).
27307 // DQ (10/21/2020): I think we may want to return the orignal defining function declaration.
27308 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27309 // DQ (11/15/2020): Note that the default is false, and we need true.
27310 bool movePreprocessingInfo = true;
27311 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration,movePreprocessingInfo);
27312
27313 // DQ (11/25/2020): This is the cause of a problem in the outliner caught in the resetParentPointer.C (definingDeclaration->get_parent() != __null).
27314 // 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.
27315 // This is the cause of a name qualification bug when the functionDeclaration is inserted into global scope and the name qualification
27316 // is not computed correctly (since the parent was still the namespace scope where it was originally.
27317 ROSE_ASSERT(nondefiningFunctionDeclaration->get_parent() != NULL);
27318 }
27319 }
27320 else
27321 {
27322 // DQ (7/12/2019): Template instantiations are not directly from the source code, so we don't have to move them.
27323 nondefiningFunctionDeclaration = NULL;
27324 }
27325
27326 // Check that static declaration is preserved.
27327 if (functionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true)
27328 {
27329 ROSE_ASSERT(nondefiningFunctionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true);
27330 }
27331
27332 // DQ (10/27/2020): Added return value so that we can access the new function prototype.
27333 return nondefiningFunctionDeclaration;
27334 }
27335
27336
27337std::vector<SgFunctionDeclaration*>
27339 {
27340 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
27341 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
27342 // declarations in the outlined code we can support the outpiled code with those references. This
27343 // approach has the added advantage of also supporting the same include file tree as the original
27344 // file where the outlined code is being taken from.
27345
27346 class FunctionDefinitionsTraversal : public AstSimpleProcessing
27347 {
27348 public:
27349 std::vector<SgFunctionDeclaration*> functionList;
27350 FunctionDefinitionsTraversal() {}
27351
27352 void visit (SgNode* node)
27353 {
27354 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
27355 if (functionDeclaration != NULL)
27356 {
27357 // This should have been set already.
27358 // ROSE_ASSERT(sourceFile != NULL);
27359
27360 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27361 if (functionDeclaration == definingFunctionDeclaration)
27362 {
27363 // Remove the defining declaration as a test.
27364 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27365 if (functionDeclarationScope != NULL)
27366 {
27367 functionList.push_back(functionDeclaration);
27368 }
27369 }
27370 }
27371 }
27372 };
27373
27374 // Now build the traveral object and call the traversal (preorder) on the AST subtree.
27375 FunctionDefinitionsTraversal traversal;
27376
27377 traversal.traverseWithinFile(node, preorder);
27378
27379 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27380
27381 return functionList;
27382 }
27383
27384
27385void
27387 {
27388 ROSE_ASSERT(node != NULL);
27389
27390 std::vector<SgFunctionDeclaration*> functionList = generateFunctionDefinitionsList(node);
27391 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27392
27393 while (i != functionList.end())
27394 {
27395 SgFunctionDeclaration* functionDeclaration = *i;
27396 ROSE_ASSERT(functionDeclaration != NULL);
27397 // Transform into prototype.
27399 i++;
27400 }
27401 }
27402
27403
27404
27405// DQ (7/14/2020): Added test for initializers to support debugging of Cxx11_tests/test2020_69.C.
27406void
27408 {
27409 // This function checks variable declarations for initializers. An issue (bug) in EDG 6.0
27410 // support for variable declarations initialized using lambda functions is that the initalizer
27411 // is discarded at some point in the processing of the AST. This function reports on all
27412 // variable declarations and if they contain initializers and if so what kind of initializer.
27413
27414 ROSE_ASSERT(node != nullptr);
27415
27416 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
27417 class CheckInitializerTraversal : public AstSimpleProcessing
27418 {
27419 public:
27420 void visit (SgNode* node)
27421 {
27422 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node);
27423 if (variableDeclaration != NULL)
27424 {
27425 SgInitializedName* initializedName = getFirstInitializedName(variableDeclaration);
27426 SgExpression* initializer = initializedName->get_initializer();
27427
27428 printf ("variableDeclaration = %p initializedName = %p = %s initializer = %p \n",
27429 variableDeclaration,initializedName,initializedName->get_name().str(),initializer);
27430
27431 if (initializer != NULL)
27432 {
27433 printf (" --- initializer = %s \n",initializer->class_name().c_str());
27434 }
27435 }
27436 }
27437 };
27438
27439 // Now buid the traveral object and call the traversal (preorder) on the project.
27440 CheckInitializerTraversal traversal;
27441 traversal.traverse(node, preorder);
27442 }
27443
27444namespace
27445{
27446 struct DeclaredType : sg::DispatchHandler<SgNamedType*>
27447 {
27448 void setResult(SgNamedType* ty) { res = ty; }
27449 void setResult(SgType*) { /* not a named type */ }
27450
27451 void handle(SgNode& n, SgNode&) { SG_UNEXPECTED_NODE(n); }
27452
27453 template <class SageDeclarationStatement>
27454 void handle(SageDeclarationStatement& n, SgDeclarationStatement&)
27455 {
27456 // SgDeclarationStatement::get_type is not a virtual function
27457 // => find overloaders returning SgNamedType in subclasses
27458 // by using the full type (SageDeclarationStatement).
27459 setResult(n.get_type());
27460 }
27461
27462 template <class SageNode>
27463 void handle(SageNode& n)
27464 {
27465 handle(n, n);
27466 }
27467 };
27468}
27469
27471{
27472 return sg::dispatch(DeclaredType{}, declaration);
27473}
27474
27476 SgGlobal * gsaf = project->get_globalScopeAcrossFiles();
27477 ROSE_ASSERT(gsaf != nullptr);
27478 SgSymbolTable * st = gsaf->get_symbol_table();
27479 ROSE_ASSERT(st != nullptr);
27480 rose_hash_multimap * hmm = st->get_table();
27481 ROSE_ASSERT(hmm != nullptr);
27482 hmm->clear();
27483
27484 st = SgNode::get_globalTypeTable()->get_type_table();
27485 ROSE_ASSERT(st != nullptr);
27486 hmm = st->get_table();
27487 ROSE_ASSERT(hmm != nullptr);
27488 hmm->clear();
27489
27491 ROSE_ASSERT(st != nullptr);
27492 hmm = st->get_table();
27493 ROSE_ASSERT(hmm != nullptr);
27494 hmm->clear();
27495}
27496
27498/*
27499
27500By default, only transformation generated AST nodes will be normalized since this is designed to normalize translator-generated code.
27501
27502--- p_lhs_operand_i ->@0x7ff2fc3f1010 SgArrowExp c_rc-575-out.cpp 16:13
27503 |--- p_lhs_operand_i ->@0x7ff2fc428010 SgAddressOfOp c_rc-575-out.cpp 16:4
27504 | |___ p_operand_i ->@0x7ff2fc582078 SgVarRefExp c_rc-575-out.cpp 16:5 init name@0x7ff2fcf03890 symbol name="table1"
27505 |___ p_rhs_operand_i ->@0x7ff2fc5820e0 SgVarRefExp c_rc-575-out.cpp 16:16 init name@0x7ff2fcf03480 symbol name="item1"
27506
27507
27508TODO: we only handle simplest pattern for now: both leaf operands involved are SgVarRefExp.
27509
27510 * */
27511int SageInterface::normalizeArrowExpWithAddressOfLeftOperand(SgNode* root, bool transformationGeneratedOnly /* =true */)
27512{
27513 int match_count = 0;
27514 ROSE_ASSERT (root);
27515
27516 // find all SgArrowExp, then try to match the expected pattern
27517 // SgArrowExp(SgAddressOfOp(SgVarRefExp:table1),SgVarRefExp:item1)
27518 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgArrowExp);
27519
27520 // The jovial2cpp translator generates two source file ASTs: and they often share the same subtrees.
27521 // So we need to make sure the same subtree is only processed once
27522 boost::unordered::unordered_map <SgNode*, bool> visited;
27523
27524 // reverse iterator is safer to use than forward iterator to support translation
27525 for (Rose_STL_Container<SgNode *>::reverse_iterator i = nodeList.rbegin(); i != nodeList.rend(); i++)
27526 {
27527 // skip a node if it is previously processed.
27528 if (visited.count(*i)==1)
27529 continue;
27530
27531 visited[*i]=true;
27532
27533 SgArrowExp* a_exp = isSgArrowExp(*i);
27534
27535 if (!a_exp)
27536 {
27537 cerr<<"SageInterface::normalizeArrowExpWithAddressOfLeftOperand() expects SgArrowExp while encountering "<<(*i)->class_name()<<"@"<<(*i) <<endl;
27538 ROSE_ASSERT (a_exp);
27539 }
27540
27541 if (transformationGeneratedOnly)
27542 {
27543 if (!(a_exp->get_file_info()->isTransformation()))
27544 continue;
27545 }
27546
27547 if (SgAddressOfOp* address_op = isSgAddressOfOp(a_exp->get_lhs_operand()) )
27548 {
27549 if (SgVarRefExp* left = isSgVarRefExp(address_op->get_operand())) // match left side pattern
27550 {
27551 if (SgVarRefExp* right = isSgVarRefExp (a_exp->get_rhs_operand())) // match right side pattern
27552 {
27553 // do the transformation: copy two operands, making a dot exp instead
27554 SgDotExp* dot_exp = buildDotExp (deepCopy(left), deepCopy(right));
27555 replaceExpression (a_exp, dot_exp);
27556 match_count++;
27557 }
27558 }
27559 }
27560 } // end for
27561
27562 return match_count;
27563}
27564
27565bool
27567 {
27568 class Traversal : public AstSimpleProcessing
27569 {
27570 public:
27571 bool found;
27572 Traversal() : found(false) {}
27573 void visit (SgNode* node)
27574 {
27575 SgCastExp* castExpression = isSgCastExp(node);
27576 if (castExpression != NULL)
27577 {
27578 // SgNode* parent = castExpression->get_parent();
27579 SgInitializer* initializer = isSgInitializer(castExpression->get_parent());
27580 if (initializer == NULL)
27581 {
27582 ROSE_ASSERT(castExpression->get_file_info() != NULL);
27583 if (castExpression->get_file_info()->isTransformation() == true)
27584 {
27585 printf (" --- Found a SgCastExp marked as a transformation: castExpression = %p \n",castExpression);
27586 found = true;
27587#if 0
27588 printf ("Exiting as a test! \n");
27589 ROSE_ASSERT(false);
27590#endif
27591 }
27592 else
27593 {
27594#if 0
27595 printf (" --- SgCastExp (but not marked as a transformation) node = %p = %s \n",node,node->class_name().c_str());
27596#endif
27597 }
27598 }
27599 else
27600 {
27601 // DQ (7/14/2021): This case is less interesting (not the SgCastExp that I was looking for in testing).
27602#if 1
27603 printf (" --- SgCastExp (but from an initializer) node = %p = %s \n",node,node->class_name().c_str());
27604#endif
27605 }
27606 }
27607 else
27608 {
27609#if 0
27610 printf (" --- node = %p = %s \n",node,node->class_name().c_str());
27611#endif
27612 }
27613 }
27614 };
27615
27616#if 1
27617 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s \n",s.c_str());
27618#endif
27619
27620 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27621 Traversal traversal;
27622 traversal.traverse(n, preorder);
27623
27624#if 1
27625 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s traversal.found = %s \n",s.c_str(),traversal.found ? "true" : "false");
27626#endif
27627#if 0
27628 // DQ (7/13/2021): return false so that we can test the execution of the code to generate that backend code.
27629 if (traversal.found == true)
27630 {
27631 printf ("In findFirstSgCastExpMarkedAsTransformation(): returning false \n");
27632 }
27633
27634 return false;
27635#else
27636 return traversal.found;
27637#endif
27638 }
27639
27640// A helper function to check
27641// begin: return 1
27642// middle (#else, #elif): return 2
27643// end directive: return -1
27644// othewise return 0;
27645static int isBeginDirective (PreprocessingInfo* info)
27646{
27647 ROSE_ASSERT (info != NULL);
27648 PreprocessingInfo::DirectiveType dtype= info->getTypeOfDirective();
27649 if (dtype == PreprocessingInfo::CpreprocessorIfdefDeclaration ||
27650 dtype == PreprocessingInfo::CpreprocessorIfndefDeclaration ||
27651 dtype == PreprocessingInfo::CpreprocessorIfDeclaration )
27652 {
27653 return 1;
27654 }
27655 else if (dtype==PreprocessingInfo::CpreprocessorElseDeclaration||
27656 dtype==PreprocessingInfo::CpreprocessorElifDeclaration)
27657 {
27658 return 2;
27659 }
27660 else if (dtype==PreprocessingInfo::CpreprocessorEndifDeclaration)
27661 {
27662 return -1;
27663 }
27664
27665 return 0;
27666}
27667
27668// a helper function to move things, the associated directive in the middle
27669static void moveInofListToNewPlace(AttachedPreprocessingInfoType* infoList, int cidx, set <AttachedPreprocessingInfoType*>& relatedInfoList, SgLocatedNode* lnode, int &retVal)
27670{
27671// AttachedPreprocessingInfoType* infoList = (*ki).first;
27672// int cidx= (*ki).second;
27673
27674 relatedInfoList.insert (infoList);
27675
27676 PreprocessingInfo* info = (*infoList)[cidx];
27677 // rewrite relative position
27678 info->setRelativePosition(PreprocessingInfo::after);
27679
27680 // insert after lnode
27681 lnode->addToAttachedPreprocessingInfo (info);
27682 retVal++;
27683
27684 // zero out from original list
27685 (*infoList)[cidx]= NULL;
27686}
27687
27688// Return the number of NULL PreprocessingInfo* within a subtree of a SgLocatedNode, inclusive
27690{
27691 int retVal=0;
27692 ROSE_ASSERT(lnode);
27693
27694 // collecting NULL entries
27695 RoseAst ast(lnode);
27696 RoseAst::iterator ast_i=ast.begin();
27697
27698 vector < pair< AttachedPreprocessingInfoType*, int> > empty_entries; // preprocessing info. to be erased, list vs. idx/offset
27699 for(;ast_i!=ast.end();++ast_i) {
27700 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27701 if (current ==NULL ) // skip non located nodes
27702 continue;
27703
27704 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27705 if (infoList == NULL) continue;
27706
27707 int commentIndex=0;
27708 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27709 {
27710 // fundamentally, we want to move individual PreprocessingInfo objects
27711 // Or just duplicate them (easier)
27712 PreprocessingInfo * info = *ci;
27713 if (info==NULL)
27714 empty_entries.push_back( make_pair (infoList, commentIndex) );
27715 commentIndex++;
27716 }
27717 }
27718
27719 // using reverse iterator to remove from backwards
27720 for (auto ki = empty_entries.rbegin(); ki != empty_entries.rend(); ki ++)
27721 {
27722 AttachedPreprocessingInfoType* infoList = (*ki).first;
27723 int cidx= (*ki).second;
27724
27725 PreprocessingInfo* info = (*infoList)[cidx];
27726 ROSE_ASSERT (info==NULL);
27727
27728 // erase start+offset
27729 AttachedPreprocessingInfoType::iterator k = infoList->begin();
27730 infoList->erase(k+cidx);
27731// cout<<"debugging: direct erasing: info@"<< infoList<< " idx="<<cidx<<endl;
27732 retVal ++;
27733 }
27734 return retVal;
27735}
27736
27737//TODO: expose this to header file?
27738// We keep all things, including level : starting from 0. Later iteration ignore the level 0 directives.
27739// Should this be maintained by librose or user space code?
27740static std::unordered_map <PreprocessingInfo*, SageInterface::PreprocessingInfoData> infoMap;
27741
27742void SageInterface::preOrderCollectPreprocessingInfo(SgNode* current, vector<PreprocessingInfo*>& infoList, int depth)
27743{
27744 // stop condition
27745 if (current == NULL)
27746 return;
27747
27748 // Three possible locations: before, inside, and after
27749 // immediately add prepression info that is before and inside of current node
27750 // delayed additions of these that are located after the current node
27751 vector<PreprocessingInfo*> afterList;
27752 if (SgLocatedNode* locatedNode = isSgLocatedNode(current))
27753 {
27754 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
27755
27756 if (comments != nullptr)
27757 {
27758 AttachedPreprocessingInfoType::iterator i;
27759 int idx=0;
27760 for (i = comments->begin (); i != comments->end (); i++)
27761 {
27762 PreprocessingInfo* info= *i;
27763
27764 // prepare the data just in case
27766 data.container=comments;
27767 data.index = idx;
27768 data.depth = depth;
27769
27770 // put directives with before location into the infoList
27771 if (info->getRelativePosition () == PreprocessingInfo::before
27772 )
27773 {
27774 infoList.push_back (info);
27775 infoMap[info] = data;
27776 }
27777 // How about inside position?
27778 // why it should be intepreted as the last one after all inner statment's preprocessingInfo?
27779 // because if it should be unparsed before all of them, it should have been attached to the first stmt's before location instead!
27780 else if (info->getRelativePosition () == PreprocessingInfo::after
27781 || info->getRelativePosition () == PreprocessingInfo::inside
27782 )
27783 {
27784 afterList.push_back (info); // if attached to be after, save to afterList
27785 infoMap[info] = data;
27786 }
27787 else
27788 {
27789 mlog[Sawyer::Message::Common::WARN] <<"Warning: unhandled relative position value:" <<info->getRelativePosition () <<endl;
27790 // ROSE_ASSERT (false); // Jovial has end_of
27791 }
27792
27793 idx++;
27794 } // end for
27795 }
27796 } // end if
27797
27798 // handling children nodes
27799 std::vector<SgNode* > children = current->get_traversalSuccessorContainer();
27800 for (auto c: children)
27801 preOrderCollectPreprocessingInfo (c, infoList, depth +1);
27802
27803 // append after locations after recursively handling children nodes.
27804 for (auto fi : afterList)
27805 infoList.push_back(fi);
27806}
27807
27808// This may be expensive to run since it is called anytime replace() is called.
27810// We need to attach them to be after lnode, before we can safely remove lnode. So the inner preprocessing info. can be preserved properly.
27811// This should be done before removing or replace the statement: lnode
27812// TODO: this may need to be a recursive function for multiple levels of nested directives.
27813//
27814// We only care about directives attached to inner nodes, not lnode : TODO: double check this for corner cases
27815//
27817{
27818 int retVal=0;
27819 ROSE_ASSERT(lnode);
27820
27821// algorithm: using a queue (vector to simulate it)
27822// queue <PreProcessingInfo* > q;
27823// start from 2nd node: ignore the first root node
27824// if start preprocessing info: (if, ifndef, ifdef), push to the end of q
27825// if end of preprocessing info. (endif), neturalize possible end p info at the end of q, otherwise push it to the end
27826//
27827// the queue in the end may contain mixed preprocessing info. #endif #endif ... #if #ifndef
27828// They cannot neutralize each other.
27829// They should be attached to be after lnode !
27830 RoseAst ast(lnode);
27831 RoseAst::iterator ast_i=ast.begin();
27832 ++ast_i; // skip the root node itself
27833
27834 // we store both the container and the element's index within the container. so later we can easily remove elements from containers
27835 vector < pair< AttachedPreprocessingInfoType*, int> > keepers; // preprocessing info. to be kept
27836 // for the middle directives like #else or #elif, sometimes their status (balanced or not) is directly associatd with its preceeding begin directive
27837 // it is not always an independent decision.
27838 // Note : the association is between individual preprocessing info. however, to faciliate removing them, the second part uses InfoList vs offset
27839 unordered_map < PreprocessingInfo * , vector< pair<AttachedPreprocessingInfoType*, int>> > associated_directives;
27840
27841 // store the associated middle directives what should be erased in the end
27842 // we have to store this separatedly since the begin diretive pinfo becomes NULL after they have been erased!
27843 // associated_directives[BeginInfo] will not retrieve them!
27844 vector< pair<AttachedPreprocessingInfoType*, int>> associated_erase;
27845
27846 // Two steps here
27847 // Step 1: We build the list first, then go through them to neutralize them
27848 // to simplify the problem: we exclude comments attached to the current located node, only consider things inside
27849 //
27850 // The list must provide the following information
27851 // infoList (container), index of the directive, PreprocessingInfo* itself
27852 vector<PreprocessingInfo*> candidateInfoList;
27853 // recursively search all directives, preserving original order in AST, consider attachment locations: before, inside and after.
27854 preOrderCollectPreprocessingInfo (lnode, candidateInfoList, 0);
27855 // now we have both candidateInfoList and infoMap.
27856
27857 for (auto candidate: candidateInfoList)
27858 {
27859 // fundamentally, we want to move individual PreprocessingInfo objects
27860 // Or just duplicate them (easier)
27861 PreprocessingInfo * info = candidate;
27862
27863 // we skip candidate that is attached to a node with depth of 0 (root node of the subtree)
27864 if (infoMap[info].depth ==0)
27865 continue;
27866
27867 int commentIndex = infoMap[info].index;
27868 AttachedPreprocessingInfoType* infoList = infoMap[info].container;
27869
27870 // begin directives
27871 if ( isBeginDirective(info) == 1)
27872 {
27873 keepers.push_back(make_pair (infoList,commentIndex));
27874 }
27875 // the middle #else, #elif,
27876 else if (isBeginDirective(info) == 2)
27877 {
27878 // two situtations for immediate decision of unbalanced status
27879 //1. empty stack, or
27880 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27881 if (keepers.size()==0)
27882 keepers.push_back(make_pair (infoList, commentIndex));
27883 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27884 {
27885 keepers.push_back(make_pair (infoList,commentIndex));
27886 }
27887 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27888 {
27889 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27890 // we associated this middle directive with the beginning directive
27891 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27892 }
27893 }
27894 // end directive
27895 else if ( isBeginDirective(info) == -1)
27896 {
27897 bool neutralized = false;
27898 // neutralize an internall matched pair, if any
27899 if (keepers.size()>0)
27900 {
27901 AttachedPreprocessingInfoType* comments = keepers.back().first;
27902 int idx = keepers.back().second;
27903
27904 if(isBeginDirective( (*comments)[idx] )==1)
27905 {
27906 keepers.pop_back();
27907 neutralized = true;
27908 }
27909 }
27910
27911 if (!neutralized)
27912 keepers.push_back(make_pair (infoList,commentIndex));
27913 }
27914
27915 }
27916
27917#if 0 // old and wrong linear search of directives
27918
27919 // Then we go through the list, extract keepers, neutralize anything else.
27920 for(;ast_i!=ast.end();++ast_i) {
27921 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27922 if (current ==NULL ) // skip non located nodes
27923 continue;
27924
27925 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27926 if (infoList == NULL) continue;
27927
27928 int commentIndex=0;
27929 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27930 {
27931 ROSE_ASSERT(*ci != NULL);
27932 // fundamentally, we want to move individual PreprocessingInfo objects
27933 // Or just duplicate them (easier)
27934 PreprocessingInfo * info = *ci;
27935
27936 // begin directives
27937 if ( isBeginDirective(info) == 1)
27938 {
27939 keepers.push_back(make_pair (infoList,commentIndex));
27940 }
27941 // the middle #else, #elif,
27942 else if (isBeginDirective(info) == 2)
27943 {
27944 // two situtations for immediate decision of unbalanced status
27945 //1. empty stack, or
27946 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27947 if (keepers.size()==0)
27948 keepers.push_back(make_pair (infoList,commentIndex));
27949 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27950 {
27951 keepers.push_back(make_pair (infoList,commentIndex));
27952 }
27953 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27954 {
27955 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27956 // we associated this middle directive with the beginning directive
27957 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27958 }
27959 }
27960 // end directive
27961 else if ( isBeginDirective(info) == -1)
27962 {
27963 bool neutralized = false;
27964 // neutralize an internall matched pair, if any
27965 if (keepers.size()>0)
27966 {
27967 AttachedPreprocessingInfoType* comments = keepers.back().first;
27968 int idx = keepers.back().second;
27969
27970 if(isBeginDirective( (*comments)[idx] )==1)
27971 {
27972 keepers.pop_back();
27973 neutralized = true;
27974 }
27975 }
27976
27977 if (!neutralized)
27978 keepers.push_back(make_pair (infoList,commentIndex));
27979 }
27980 commentIndex++;
27981 }
27982 }
27983#endif
27984// TODO this variable is not used in the end.
27985 set <AttachedPreprocessingInfoType*> relatedInfoList; // containers with comments to be moved
27986 // 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!
27987 // move from old containers, and add into lnode's after position
27988 for (auto ki = keepers.begin(); ki != keepers.end(); ki ++)
27989 {
27990 AttachedPreprocessingInfoType* infoList = (*ki).first;
27991 int cidx= (*ki).second;
27992 // TODO replace the code block below with moveInofListToNewPlace()
27993 relatedInfoList.insert (infoList);
27994
27995 PreprocessingInfo* info = (*infoList)[cidx];
27996 // rewrite relative position
27997 info->setRelativePosition(PreprocessingInfo::after);
27998
27999 // insert after lnode
28000 lnode->addToAttachedPreprocessingInfo (info);
28001 retVal++;
28002
28003 // we additionally process the associated directives, if any, TODO: reverse processing also??
28004 if (associated_directives.count (info)!=0)
28005 {
28006 vector<pair<AttachedPreprocessingInfoType*,int>> a_list_vec = associated_directives[info];
28007 for (auto vec_i = a_list_vec.rbegin(); vec_i != a_list_vec.rend(); vec_i ++ )
28008 {
28009 AttachedPreprocessingInfoType* a_infoList = (*vec_i).first;
28010 int aidx= (*vec_i).second;
28011 moveInofListToNewPlace (a_infoList, aidx, relatedInfoList, lnode, retVal);
28012 associated_erase.push_back(make_pair (a_infoList, aidx));
28013 }
28014 } // each begin directive may associate multiple other middle directives
28015
28016 // Doing this after the associated directives are processed.
28017 // zero out from original list, Note this element slot is NULL now!
28018 (*infoList)[cidx]= NULL;
28019
28020 }
28022 return retVal;
28023}
to specify a construct using a specifier Can be used alone or with parent handles when relative speci...
virtual void * getNode() const
Get the raw IR node associated with the current abstract node.
Base class for all IR node attribute values.
Attribute Evaluator for synthesized attributes.
SynthesizedAttributeType traverse(SgNode *node)
evaluates attributes on the entire AST
Attribute storing an SgNode.
Class for traversing the AST.
void traverse(SgNode *node, Order treeTraversalOrder)
traverse the entire AST. Order defines preorder (preorder) or postorder (postorder) traversal....
void visit(SgNode *astNode)
this method is called at every traversed node.
void visit(SgNode *astNode)
visitor function for each node to collect non-builtin types' declarations
void visit(SgNode *astNode)
this method is called at every traversed node.
For preprocessing information including source comments, include , if, define, etc.
RelativePositionType
MK: Enum type to store if the directive goes before or after the corresponding line of source code.
AST iterator.
Definition RoseAst.h:54
Interface for iterating over an AST.
Definition RoseAst.h:26
iterator begin()
Iterator positioned at root of subtree.
iterator end()
Iterator positioned at the end of the traversal.
const Digest & digest() override
Return the digest.
void insert(const std::string &x)
Insert data into the digest.
uint64_t make64Bits()
Returns the hash as a 64 bit int.
void visit(SgNode *node)
this method is called at every traversed node.
Interface for creating a statement whose computation writes its answer into a given variable.
A persistent attribute to represent a unique name for an expression.
SgName get_name() const override
Access function for getting name from declarations or types internally.
Base class for binary files.
SgAsmGenericHeaderList *const & get_headers() const
Property: List of all headers in file.
SgAsmGenericHeaderPtrList const & get_headers() const
Property: List of file header nodes.
Base class for container file headers.
SgAsmInterpretationPtrList const & get_interpretations() const
Property: Interpretation list.
Represents an interpretation of a binary container.
This class represents the concept of a C Assembler statement.
This class represents the rhs of a variable declaration which includes an optional assignment (e....
void set_operand(SgExpression *exp)
This sets the rhs expression.
SgExpression * get_operand() const
Returns the rhs.
This class represents the concept of a block (not a basic block from control flow analysis).
const SgStatementPtrList & get_statements() const
Returns a const STL list by reference.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a binary operator. It is derived from a SgExpression because oper...
SgExpression * get_lhs_operand() const
returns SgExpression pointer to the lhs operand associated with this binary operator.
void set_rhs_operand(SgExpression *exp)
This function allows the p_rhs_operand pointer to be set (used internally).
void set_lhs_operand(SgExpression *exp)
This function allows the p_lhs_operand pointer to be set (used internally).
SgExpression * get_rhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
SgExpression * get_lhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
virtual VariantT variantT() const override
returns new style SageIII enum values
SgExpression * get_rhs_operand() const
returns SgExpression pointer to the rhs operand associated with this binary operator.
This class represents a boolean value (expression value).
This class represents the notion of a break statement (typically used in a switch statment).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a C and C++ case option (used within a switch statement).
SgStatement * get_body() const
Returns pointer to a SgBasicBlock object.
void set_key(SgExpression *key)
Access function for pointer to SgExpression object wrapped by SgExpressionRoot in p_key_root.
void set_body(SgStatement *body)
Access function for p_body.
SgExpression * get_key() const
Returns pointer to a SgExpression object wrapped by SgExpressionRoot in p_key_root.
This class represents a cast of one type to another.
SgType * get_type() const override
unparsing support for pragmas
This class represents the concept of a catch within a try-catch construct used in C++ exception handl...
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Access function for p_body.
This class represents the concept of a class declaration statement. It includes the concept of an ins...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgScopeStatement * get_scope() const override
Returns scope of current statement.
This class represents the concept of a class definition in C++.
SgClassDeclaration * get_declaration() const
returns the class declaration associated with this class decinition.
const SgDeclarationStatementPtrList & get_members() const
Returns a const list to the data member declarations.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a C++ expression built from a class name.
SgClassSymbol * get_symbol() const
Returns pointer to SgSymbol.
This class represents the concept of a class name within the compiler.
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
static SgClassType * createType(SgDeclarationStatement *decl=NULL, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgClassType (types whose constructors take par...
This class represents the concept of a C trinary conditional expression (e.g. "test ?...
SgExpression * get_true_exp() const
Access function for p_true_exp.
void set_false_exp(SgExpression *false_exp)
Access function for p_false_exp.
SgExpression * get_conditional_exp() const
Access function for p_conditional_exp.
SgExpression * get_false_exp() const
Access function for p_false_exp.
void set_true_exp(SgExpression *true_exp)
Access function for p_true_exp.
void set_conditional_exp(SgExpression *conditional_exp)
Access function for p_conditional_exp.
This class represents the call of a class constructor to initialize a variable. For example "Foo foo;...
SgType * get_expression_type() const
Access function for p_expression_type, returns pointer to SgType associated with constructor.
This class represents the concept of a C or C++ continue statement.
Supporting class from copy mechanism within ROSE.
Definition sageCopy.h:26
This class represents the concept of a contructor initializer list (used in constructor (member funct...
bool isFriend() const
declaration modifier is friend.
This class represents the concept of a declaration statement.
SgSymbol * search_for_symbol_from_symbol_table() const
User interface for retrieving the associated symbol from the declaration.
void set_definingDeclaration(SgDeclarationStatement *definingDeclaration)
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
void set_firstNondefiningDeclaration(SgDeclarationStatement *firstNondefiningDeclaration)
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
SgDeclarationStatement * get_definingDeclaration() const
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
bool isForward() const
Returns boolean value indicating if this is a forward declaration.
SgDeclarationStatement * get_firstNondefiningDeclaration() const
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool hasAssociatedSymbol() const
Returns boolean value true of this type of declaration has an associated sysmbol.
SgName get_template_name() const
This function returns the template name (taken from the template declaration for the class,...
This class represents the concept of a C or C++ default case within a switch statement.
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Returns pointer to SgBasicBlock.
This class represents a directory within a projects file structure of files and directories.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_condition(SgStatement *condition)
Access function for p_condition.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the notion of an value (expression value).
This class represents the concept of an enum declaration.
SgScopeStatement * get_scope() const override
Access function for p_scope.
SgName get_name() const
Access function for p_name.
void set_scope(SgScopeStatement *scope) override
Access function for p_scope.
const SgInitializedNamePtrList & get_enumerators() const
Access function for p_enumerators.
This class represents the concept of a C and C++ expression list.
int replace_expression(SgExpression *o, SgExpression *n) override
This class represents the base class of all the expressions within this grammar.
This class represents the concept of a C or C++ statement which contains a expression.
This class represents the notion of an expression. Expressions are derived from SgLocatedNodes,...
virtual std::string class_name() const override
returns a string representing the class name
void set_need_paren(bool need_paren)
This function allows the p_need_paren flag to be set (used internally).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgType * get_type() const
unparsing support for pragmas
virtual int replace_expression(SgExpression *oldChild, SgExpression *newChild)
This class represents the base class of all the expressions within this grammar.
virtual const char * sage_class_name() const override
virtual Sg_File_Info * get_file_info(void) const override
Interface function to implement original SAGE interface to SgFile_Info objects.
void set_lvalue(bool lvalue)
This function allows the p_lvalue flag to be set (used internally).
bool get_lvalue() const
Returns a bool value if the current expression is assigned to.
This class represents a source file for a project (which may contian many source files and or directo...
std::string getFileName() const
associated filename
Sg_File_Info * get_file_info() const override
Access function calling get_startOfConstruct(), provided to support older interface.
This class represents the notion of an value (expression value).
This class represents the variable declaration or variable initialization withn a for loop.
const SgStatementPtrList & get_init_stmt() const
Returns const reference to a SgStatementPtrList (typedef to a STL list).
This class represents the concept of a for loop.
SgExpression * get_test_expr() const
Access function for p_test_expr_root.
SgForInitStatement * get_for_init_stmt() const
Access function for p_for_init_stmt.
void set_loop_body(SgStatement *loop_body)
Access function for p_loop_body.
SgStatement * get_loop_body() const
Access function for p_loop_body.
void set_for_init_stmt(SgForInitStatement *for_init_stmt)
Access function for p_for_init_stmt.
This class represents the concept of a C++ function call (which is an expression).
SgFunctionSymbol * getAssociatedFunctionSymbol() const
Returns the associated function symbol, if it can be resolved statically.
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a function declaration statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool isTemplateFunction() const
Determines if function is a template or non-template function.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
virtual std::string class_name() const override
returns a string representing the class name
SgBasicBlock * get_body() const
Access function for p_body.
This class represents the concept of a declaration list.
const SgInitializedNamePtrList & get_args() const
Access function for p_args.
const SgTypePtrList & get_arguments() const
Get a const list of input types (types of the parameters list) to this function type (from a cost fun...
This class represents the function being called and must be assembled in the SgFunctionCall with the ...
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the function type table (stores all function types so that they can be shared i...
SgSymbolTable * get_function_type_table() const
Returns pointer to SgSymbolTable used for function type symbols only.
This class represents a type for all functions.
virtual std::string class_name() const override
returns a string representing the class name
const SgTypePtrList & get_arguments() const
This is a const convience access function to the STL container of types in the child IR node (SgFunct...
virtual SgName get_mangled(void) const override
Mangled name support for unparser support.
This class represents the concept of a namespace definition.
virtual std::string class_name() const override
returns a string representing the class name
const SgDeclarationStatementPtrList & get_declarations() const
Returns a const list to the global scope declarations.
This class represents the concept of a C or C++ goto statement.
SgLabelStatement * get_label() const
Returns pointer to SgLabelStatement where control flow will be transfered during execution.
void set_label(SgLabelStatement *label)
Access function for p_label.
InheritedAttributeType traverse(SgGraphNode *basenode, SgIncidenceDirectedGraph *g, InheritedAttributeType inheritedValue, InheritedAttributeType nullInherit, SgGraphNode *endnode, bool insep=false, bool pcHk=false)
This is the function that is used by the user directly to start the algorithm.
This class represents the concept of an "if" construct.
void set_false_body(SgStatement *false_body)
Access function for p_false_body.
virtual std::string class_name() const override
returns a string representing the class name
void set_true_body(SgStatement *true_body)
Access function for p_true_body.
SgStatement * get_conditional() const
Access function for p_conditional.
SgStatement * get_true_body() const
Access function for p_true_body.
SgStatement * get_false_body() const
Access function for p_false_body.
void set_conditional(SgStatement *conditional)
Access function for p_conditional.
This class represents the notion of a declared variable.
SgName get_qualified_name() const
Returns the name with appropriate qualified names representing nested scopes.
SgSymbol * get_symbol_from_symbol_table() const
Get the associated SgSymbol from the symbol table located in the scope, without considering possible ...
virtual std::string class_name() const override
returns a string representing the class name
SgDeclarationStatement * get_declaration() const
Equal operator : it checks if all the data members are the same or point to the same objects.
This class represents the notion of an initializer for a variable declaration or expression in a func...
This class represents the concept of a C or C++ label statement.
SgName get_label() const
Returns SgName by value.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
label_type_enum
Type of label used (fortran only)
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of an expression or statement which has a position within the source...
virtual std::string class_name() const override
returns a string representing the class name
virtual const char * sage_class_name() const override
Sg_File_Info * get_endOfConstruct() const override
New function interface for Sg_File_Info data stores ending location of contruct (typically the closin...
void setTransformation()
Allow IR nodes (mostly SgLocatedNode) to be marked as a transformation.
virtual void addNewAttribute(std::string s, AstAttribute *a) override
Add a new attribute represented by the named string.
void set_endOfConstruct(Sg_File_Info *endOfConstruct)
This function sets the current source location position of the end of the current construct.
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
void addToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo::RelativePositionType locationInList=PreprocessingInfo::after)
This function adds comment or CPP directives to the current IR node.
virtual AstAttribute * getAttribute(std::string s) const override
Returns attribute of name 's'.
void set_startOfConstruct(Sg_File_Info *startOfConstruct)
This function sets the current source location position of the start of the current construct.
bool isCompilerGenerated() const
Simple test for if this is a compiler generated node.
void insertToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo *anchorInfoPtr, bool insertAfter=true)
Insert prepInfo After (or before if last parameter is false) an anchor info ptr in the list of prepro...
virtual VariantT variantT() const override
returns new style SageIII enum values
void setOutputInCodeGeneration()
Allow IR nodes (mostly SgLocatedNode) to be marked as to when the information was unavilable in the f...
virtual Sg_File_Info * get_file_info() const override
Interface function to implement original SAGE interface to SgFile_Info objects.
bool isTransformation() const
Simple test for if this is a part of a transformation.
AttachedPreprocessingInfoType *& getAttachedPreprocessingInfo(void)
Computes the number of nodes in the defined subtree of the AST.
This class represents the notion of an value (expression value).
This class represents the concept of a member function declaration statement.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the member function being called and must be assembled in the SgFunctionCall wi...
SgMemberFunctionDeclaration * getAssociatedMemberFunctionDeclaration() const
This is helpful in chasing down the associated declaration to this member function reference.
SgName get_name() const override
Access function for getting name from declarations or types internally.
SgTypeModifier & get_typeModifier()
Access function for modifier.
This class represents strings within the IR nodes.
virtual SgName get_name() const
Gets name of the type (useful for debugging, unparsing, etc.)
SgName get_qualified_name() const
Used for the SgNamedType object (base class for the SgClassType, SgTypedefType and the SgEnumType obj...
This class represents the concept of a C++ namespace alias declaration statement.
SgName get_name() const
Access function for p_name.
SgNamespaceDeclarationStatement * get_namespaceDeclaration() const
Access function for p_namespaceDeclaration.
This class represents the concept of a C++ namespace declaration.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgName get_name() const
Access function for p_name.
SgNamespaceDefinitionStatement * get_definition() const
Returns pointer to SgNamespaceDefinitionStatement.
This class represents the concept of a namespace definition.
This class represents the concept of a namespace name within the compiler.
This class represents the base class for all IR nodes within Sage III.
static SgTypeTable * get_globalTypeTable()
Access function for symbol table specific to non-function types.
virtual std::vector< std::string > get_traversalSuccessorNamesContainer() 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 num)
Converts a 64 bit in to base 62 (All letters and numbers).
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
Definition sageBuilder.C:58
void serialize(std::ostream &output, Graph &graph)
Serialize a graph into a stream of bytes.
ROSE_UTIL_API std::string stripFileSuffixFromFileName(const std::string &fileNameWithSuffix)
Get the file name without the ".suffix".
ROSE_UTIL_API std::string numberToString(long long)
Convert an integer to a string.
ROSE_UTIL_API std::string copyEdit(const std::string &inputString, const std::string &oldToken, const std::string &newToken)
Replace all occurrences of a string with another string.
ROSE_UTIL_API std::string stripPathFromFileName(const std::string &fileNameWithPath)
Returns the last component of a path in a filesystem.
The ROSE library.
SgStatement * getPreviousStatement(SgStatement *targetStatement, bool climbOutScope=true)
Functions to move to SgStatement object in SAGE III later.
Functions that build an AST.
Definition sageBuilder.h:32
ROSE_DLL_API SgAddOp * buildAddOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgFunctionDeclaration * buildNondefiningFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope=NULL, SgExprListExp *decoratorList=NULL, bool buildTemplateInstantiation=false, SgTemplateArgumentPtrList *templateArgumentsList=NULL, SgStorageModifier::storage_modifier_enum sm=SgStorageModifier::e_default)
Build a prototype for a function, handle function type, symbol etc transparently.
SourcePositionClassification
intended to be a private member, don't access it directly. could be changed any time
@ e_sourcePosition_last
Specify as source position to be filled in as part of AST construction in the front-end.
@ e_sourcePositionNullPointers
Classify as compiler generated code (e.g. template instantiation).
@ e_sourcePositionCompilerGenerated
Classify as a transformation.
@ e_sourcePositionFrontendConstruction
Set pointers to Sg_File_Info objects to NULL.
@ e_sourcePositionDefault
Error value for enum.
@ e_sourcePositionTransformation
Default source position.
ROSE_DLL_API SgPragma * buildPragma(const std::string &name)
Build SgPragma.
ROSE_DLL_API SourcePositionClassification getSourcePositionClassificationMode()
Get the current source position classification (defines how IR nodes built by the SageBuilder interfa...
ROSE_DLL_API SgEqualityOp * buildEqualityOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgTemplateMemberFunctionDeclaration * buildNondefiningTemplateMemberFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope, SgExprListExp *decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList *templateParameterList)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgLabelStatement * buildLabelStatement(const SgName &name, SgStatement *stmt=NULL, SgScopeStatement *scope=NULL)
Build a label statement, name is the label's name. Handling label symbol and scope internally.
ROSE_DLL_API SgAddressOfOp * buildAddressOfOp(SgExpression *op=NULL)
ROSE_DLL_API SgTemplateFunctionDeclaration * buildNondefiningTemplateFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope=NULL, SgExprListExp *decoratorList=NULL, SgTemplateParameterPtrList *templateParameterList=NULL)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgMultiplyOp * buildMultiplyOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgGotoStatement * buildGotoStatement(SgLabelStatement *label=NULL)
Build a goto statement.
ROSE_DLL_API std::string display(SourcePositionClassification &scp)
display function for debugging
ROSE_DLL_API SgLabelRefExp * buildLabelRefExp(SgLabelSymbol *s)
Build a Fortran numeric label ref exp.
ROSE_DLL_API SgLessOrEqualOp * buildLessOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgSubtractOp * buildSubtractOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgMemberFunctionType * buildMemberFunctionType(SgType *return_type, SgFunctionParameterTypeList *typeList, SgScopeStatement *struct_name, unsigned int mfunc_specifier)
Built in simple types.
ROSE_DLL_API SgWhileStmt * buildWhileStmt(SgStatement *condition, SgStatement *body, SgStatement *else_body=NULL)
Build while statement.
ROSE_DLL_API SgForStatement * buildForStatement(SgStatement *initialize_stmt, SgStatement *test, SgExpression *increment, SgStatement *loop_body, SgStatement *else_body=NULL)
Build a for statement, assume none of the arguments is NULL.
ROSE_DLL_API SgEmptyDeclaration * buildEmptyDeclaration()
Build an empty declaration (useful for adding precission to comments and CPP handling under token-bas...
ROSE_DLL_API SgConditionalExp * buildConditionalExp(SgExpression *test=NULL, SgExpression *a=NULL, SgExpression *b=NULL)
Build a conditional expression ?:
ROSE_DLL_API SgTypeInt * buildIntType()
Built in simple types.
SourcePositionClassification SourcePositionClassificationMode
C++ SageBuilder namespace specific state for storage of the source code position state (used to contr...
ROSE_DLL_API SgMinusOp * buildMinusOp(SgExpression *op=NULL)
ROSE_DLL_API SgExprListExp * buildExprListExp(SgExpression *expr1=NULL, SgExpression *expr2=NULL, SgExpression *expr3=NULL, SgExpression *expr4=NULL, SgExpression *expr5=NULL, SgExpression *expr6=NULL, SgExpression *expr7=NULL, SgExpression *expr8=NULL, SgExpression *expr9=NULL, SgExpression *expr10=NULL)
Build a SgExprListExp, used for function call parameter list etc.
ROSE_DLL_API SgPlusAssignOp * buildPlusAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgVarRefExp * buildVarRefExp(const SgName &name, SgScopeStatement *scope=NULL)
Build SgVarRefExp based on a variable's Sage name. It will lookup the name in the symbol table intern...
bool symbol_table_case_insensitive_semantics
Support for construction of case sensitive/insensitive symbol table handling in scopes.
ROSE_DLL_API SgDotExp * buildDotExp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgAssignInitializer * buildAssignInitializer(SgExpression *operand_i=NULL, SgType *expression_type=NULL)
Build the rhs of a variable declaration which includes an assignment.
ROSE_DLL_API SgArrayType * getUniqueJavaArrayType(SgType *, int)
Build a SgFile node and attach it to SgProject.
ROSE_DLL_API SgVariableDeclaration * buildVariableDeclaration(const SgName &name, SgType *type, SgInitializer *varInit=NULL, SgScopeStatement *scope=NULL)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgScopeStatement * topScopeStack()
intended to be a private member, don't access it directly. could be changed any time
ROSE_DLL_API SgNullExpression * buildNullExpression()
Build a null expression, set file info as the default one.
ROSE_DLL_API SgGreaterOrEqualOp * buildGreaterOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgReferenceType * buildReferenceType(SgType *base_type=nullptr)
Build a reference type.
ROSE_DLL_API SgExprStatement * buildExprStatement(SgExpression *exp=NULL)
Build a SgExprStatement, set File_Info automatically.
ROSE_DLL_API SgIfStmt * buildIfStmt(SgStatement *conditional, SgStatement *true_body, SgStatement *false_body)
Build if statement.
ROSE_DLL_API SgFunctionParameterList * buildFunctionParameterList(SgInitializedName *in1=NULL, SgInitializedName *in2=NULL, SgInitializedName *in3=NULL, SgInitializedName *in4=NULL, SgInitializedName *in5=NULL, SgInitializedName *in6=NULL, SgInitializedName *in7=NULL, SgInitializedName *in8=NULL, SgInitializedName *in9=NULL, SgInitializedName *in10=NULL)
Build an empty SgFunctionParameterList, possibly with some initialized names filled in.
ROSE_DLL_API SgPointerDerefExp * buildPointerDerefExp(SgExpression *op=NULL)
ROSE_DLL_API SgTypeBool * buildBoolType()
Built in simple types.
ROSE_DLL_API SgAssignOp * buildAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgPointerType * buildPointerType(SgType *base_type=nullptr)
Build a pointer type.
ROSE_DLL_API SgBoolValExp * buildBoolValExp(int value=0)
Build a bool value expression, the name convention of SgBoolValExp is little different from others fo...
ROSE_DLL_API 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 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