ROSE 0.11.145.141
sageInterface.C
1
2#include "sage3basic.h"
3#include "markLhsValues.h"
4#include "fixupNames.h"
5#include "FileUtility.h"
6#include <Sawyer/Message.h>
7
8#include "AstJSONGeneration.h"
9
10#include "SgNodeHelper.h" //Markus's helper functions
11
12#include "Rose/AST/Utility.h"
13
14#include "sageInterface.h"
15#include "Combinatorics.h"
16
17
18#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
19#include "replaceExpressionWithStatement.h"
20
21#include "constantFolding.h"
22#endif
23
24// DQ (10/14/2006): Added supporting help functions. tps commented out since it caused no compilation errors
25//#include "rewrite.h"
26
27// Liao 1/24/2008 : need access to scope stack sometimes
28#include "sageBuilder.h"
29
30// DQ (3/14/2017): Try to comment this out since it is not tested (used in get_C_array_dimensions(),
31// from midend/programTransformation/ompLowering/omp_lowering.cpp, but not tested).
32#include "sageGeneric.h"
33
34#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
35// For reusing some code from Qing's loop optimizer
36// Liao, 2/26/2009
37#include "AstInterface_ROSE.h"
38#include "LoopTransformInterface.h"
39
40#include "DepInfoAnal.h" // for AnalyzeStmtRefs()
41#include "ArrayAnnot.h"
42#include "ArrayInterface.h"
43
44#include "LoopUnroll.h"
45#include "abstract_handle.h"
46#include "roseAdapter.h"
47#endif
48
49#include <boost/lexical_cast.hpp>
50#include <boost/foreach.hpp>
51#include <sstream>
52#include <iostream>
53#include <algorithm> // for set operations
54#include <numeric> // for std::accumulate
55#include <map>
56#include <unordered_map>
57
58#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
59# include "jni.h"
60
61namespace Rose {
62 namespace Frontend {
63 namespace Java {
64 namespace Ecj {
65
66 extern jclass currentJavaTraversalClass;
67 extern JNIEnv *currentEnvironment;
68 extern jmethodID mainMethod;
69 extern jmethodID hasConflictsMethod;
70 extern jmethodID getTempDirectoryMethod;
71 extern jmethodID createTempFileMethod;
72 extern jmethodID createTempNamedFileMethod;
73 extern jmethodID createTempNamedDirectoryMethod;
74
75 } // ::Rose::Frontend::Java::Ecj
76 }// ::Rose::frontend::java
77 }// ::Rose::frontend
78}// ::Rose
79
80using namespace Rose::Frontend::Java::Ecj;
81
82#endif
83
84
85// DQ (11/5/2019): Added to support SageInterface::statementCanBeTransformed().
86namespace EDG_ROSE_Translation
87 {
88 // DQ (9/18/2018): Declare this map so that we can use it for the unparse header files option.
89#if defined(ROSE_BUILD_CXX_LANGUAGE_SUPPORT) && !defined(ROSE_USE_CLANG_FRONTEND)
90 // DQ (12/11/2018): Use the definition in the EDG edgRose.C file if C/C++ support IS defined.
91 extern std::map<std::string, SgIncludeFile*> edg_include_file_map;
92#else
93 // DQ (12/11/2018): Allow this to be the definition if C/C++ support is NOT defined.
94 std::map<std::string, SgIncludeFile*> edg_include_file_map;
95#endif
96 }
97
98
99
100// DQ (12/1/2015): Added to support macro handling.
101#include "detectMacroOrIncludeFileExpansions.h"
102
103namespace SageInterface {
104 template<class T> void setSourcePositionToDefault( T* node );
105}
106
107
108#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
109 #include "transformationSupport.h"
110#endif
111
112// We need this so that USE_CMAKE will be seen (set via configure).
113#include "rose_config.h"
114
115// DQ (3/4/2014): We need this feature to support the function: isStructurallyEquivalentAST().
116#include "RoseAst.h"
117
118// DQ (2/13/2022): We need this feature to support the function: deleteAllNodes().
119#include "AST_FILE_IO.h"
120
121
122// DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
123// The value of 0 allows the old implementation to be tested, and the value of 1 allows the new optimized implementation to be tested.
124#define OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS 1
125
128
129// DQ (3/21/2016): Added support for generateUniqueNameForUseAsIdentifier().
131std::map<std::string,SgNode*> SageInterface::local_name_to_node_map;
132std::map<SgNode*,std::string> SageInterface::local_node_to_name_map;
133
134typedef std::set<SgLabelStatement*> SgLabelStatementPtrSet;
135
136namespace SageInterface
137{
138 Transformation_Record trans_records;
139}
140
141// DQ (12/31/2005): This is OK if not declared in a header file
142using namespace std;
143using namespace Rose;
144using namespace SageBuilder;
145//using namespace Rose::Diagnostics; // for mlog, INFO, WARN, ERROR, FATAL, etc.
146
147// Used by serialize() to collect all types visited
148//std::set<SgType*> type_set;
149// DQ (1/18/2015): Define this container locally in this file only.
150namespace SageInterface
151 {
152 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
153 vector<SgBasicBlock*> addedBasicBlockNodes;
154 }
155
156
157#if 1
158// DQ (2/13/2022): Adding support to delete the whole AST (every SgNode).
159void
161 {
162 // This function uses a memory pool traversal specific to the SgFile IR nodes
163
164 // We need to use this function to get all of the SgNodes.
165 // template <typename NodeType> std::vector<NodeType*> getSgNodeListFromMemoryPool()
166
167 class MyTraversal : public ROSE_VisitTraversal
168 {
169 public:
170 std::vector<SgNode*> resultlist;
171 void visit ( SgNode* node)
172 {
173 SgNode* result = dynamic_cast<SgNode*>(node);
174 ROSE_ASSERT(result != NULL);
175#if 0
176 printf ("In SageInterface::deleteAllNodes(): result = %p = %s \n",result,result->class_name().c_str());
177#endif
178#if 0
179 if (result != NULL)
180 {
181 resultlist.push_back(result);
182 }
183#else
184 resultlist.push_back(result);
185#endif
186 };
187
188 virtual ~MyTraversal() {}
189 };
190
191 // For debugging, recode the number of IR nodes before we delete the AST.
192 size_t numberOfNodes_before = numberOfNodes();
193
194 MyTraversal my_traversal;
195
196 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
197 // NodeType::traverseMemoryPoolNodes(my_traversal);
198 my_traversal.traverseMemoryPool();
199
200 // return my_traversal.resultlist;
201
202
203 // vector<SgNode*> nodeList = getSgNodeListFromMemoryPool<SgNode>();
204 vector<SgNode*> & nodeList = my_traversal.resultlist;
205
206 printf ("In SageInterface::deleteAllNodes(): get list of SgNode: nodeList.size() = %zu \n",nodeList.size());
207
208 vector<SgNode*>::iterator i = nodeList.begin();
209
210 // This loop will call the delete operator on all of the IR nodes in the AST.
211 while (i != nodeList.end())
212 {
213 SgNode* node = *i;
214#if 0
215 // It is an error to be calling get_name() while so many nodes are being deleted.
216 // printf (" --- calling delete (and thus the destructor) node = %p = %s name = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
217 printf (" --- calling delete (and thus the destructor) node = %p = %s \n",node,node->class_name().c_str());
218#endif
219 delete node;
220 node = NULL;
221
222 i++;
223 }
224
225#if 0
226 // This demonstrates that this function only visits the specific IR node that is used as a template parameter.
227 vector<SgFunctionDeclaration*> functionDeclarationList = getSgNodeListFromMemoryPool<SgFunctionDeclaration>();
228 printf ("In SageInterface::deleteAllNodes(): get list of SgFunctionDeclaration: functionDeclarationList.size() = %zu \n",functionDeclarationList.size());
229#endif
230
231 // Now we need to delete the memory pools (implemented by ROSETTA).
232 AST_FILE_IO::clearAllMemoryPools();
233
234 size_t numberOfNodes_after = numberOfNodes();
235
236#if 1
237 printf ("Leaving SageInterface::deleteAllNodes(): numberOfNodes_before = %zu numberOfNodes_after = %zu \n",numberOfNodes_before,numberOfNodes_after);
238#endif
239 }
240#endif
241
242
243#if 0
244// DQ (3/5/2022): Adding support to check AST for invalide poionters.
245void
247 {
248 // This function uses a memory pool traversal to look for any pointers to invalid IR nodes.
249
250 // Step 1: is to build a map of the boundaries of the memory pools for each IR node kind.
251 // Step 2: traverse all of the IR nodes across all of the memory pools and check
252 // a) if the pointer to each node in the list of child IR nodes is in the map from step 1.
253 // b) if it is then we can expect to dereference the pointer and check the value of
254 // get_freepointer(), the value should be 0xffffffffffffffff, else it is an error
255 // (when it is an error it usually should be a value that is in the map from step 1, but it
256 // is a node that was previously deleted, so it is a stale pointer).
257
258 class BuildMapTraversal : public ROSE_VisitTraversal
259 {
260 public:
261 // std::vector<SgNode*> resultlist;
262 // std::map<enum VariantT,std::vector<std::pair<SgNode*,SgNode*>> mapOfMemoryPoolsBounds;
263
264 // We need to get the pools variable for each IR node.
265
266 void visit ( SgNode* node)
267 {
268 // Get list of all pointers to all IR nodes in the current node.
269
270 // $CLASSNAME::pools
272
273 resultlist.push_back(result);
274 };
275
276 virtual ~MyTraversal() {}
277 };
278
279 // For debugging, recode the number of IR nodes before we delete the AST.
280 size_t numberOfNodes_before = numberOfNodes();
281
282 MyTraversal my_traversal;
283
284 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
285 // NodeType::traverseMemoryPoolNodes(my_traversal);
286 my_traversal.traverseMemoryPool();
287 }
288#endif
289
290void
291SageInterface::DeclarationSets::addDeclaration(SgDeclarationStatement* decl)
292 {
293 // DQ (4/3/2014): This function either builds a new set or inserts declarations into an
294 // existing set based on if a set defined by the key (firstNondefiningDeclaration) is present.
295 ASSERT_not_null(decl);
296
297#if 0
298 printf ("TOP of SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
299#endif
300
301 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
302
303 if (firstNondefiningDeclaration == nullptr)
304 {
305 // It appears that some loop transformations (pass3.C) don't set the firstNondefiningDeclaration.
306#if 0
307 printf ("WARNING: SageInterface::DeclarationSets::addDeclaration(): firstNondefiningDeclaration == NULL: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
308#endif
309 return;
310 }
311 ASSERT_not_null(firstNondefiningDeclaration);
312
313 if (decl == firstNondefiningDeclaration)
314 {
315#if 0
316 if (isSgTypedefDeclaration(decl) != nullptr)
317 {
318 printf ("TOP of SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
319 }
320#endif
321 if (declarationMap.find(firstNondefiningDeclaration) == declarationMap.end())
322 {
323#if 0
324 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add a set for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
325#endif
326#if 0
327 if (isSgTypedefDeclaration(decl) != nullptr)
328 {
329 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add a set for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
330 }
331#endif
332 // Add a new set.
333 declarationMap[decl] = new set<SgDeclarationStatement*>();
334
335 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
336 ROSE_ASSERT(declarationMap[decl] != nullptr);
337
338 // Add a declaration to an existing set.
339 declarationMap[firstNondefiningDeclaration]->insert(decl);
340 }
341 else
342 {
343 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
344 {
345#if 0
346 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add the declaration to the existing set: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
347#endif
348#if 0
349 if (isSgTypedefDeclaration(decl) != nullptr)
350 {
351 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add the declaration to the existing set: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
352 }
353#endif
354 // Add a declaration to an existing set.
355 declarationMap[firstNondefiningDeclaration]->insert(decl);
356 }
357 else
358 {
359#if 0
360 printf ("WARNING: SageInterface::DeclarationSets::addDeclaration(): A set already exists for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
361#endif
362 // DQ (4/5/2014): The case of SgFunctionParameterList fails only for boost examples (e.g. test2014_240.C).
363 // Problem uses are associated with SgTemplateInstantiationFunctionDecl IR nodes.
364 bool ignore_error = (isSgFunctionParameterList(decl) != nullptr);
365
366 // DQ (4/17/2014): This is required for the EDG version 4.8 and I don't know why.
367 // Currently the priority is to pass our existing tests.
368 // An idea is that this is sharing introduced as a result of the use of default parameters.
369
370 // DQ (7/2/2014): I am seeing that this is required for a new application using GNU 4.4.7.
371 // It allows a boost issue specific to a revisited SgTypedefDeclaration pass, but I still
372 // don't understand the problem. so this needs a better fix.
373
375 bool isInTemplateFunctionDeclaration = enclosingFunction != nullptr && (isSgTemplateMemberFunctionDeclaration(enclosingFunction) || isSgTemplateFunctionDeclaration(enclosingFunction));
376
377 // Use short-circuit evaluation to improve performance.
378 SgClassDefinition* enclosingClassDefinition = isInTemplateFunctionDeclaration == true ? nullptr : getEnclosingClassDefinition(decl);
379 bool isInTemplateClassDefinition = enclosingClassDefinition != nullptr && isSgTemplateClassDefinition(enclosingClassDefinition);
380
381 bool isInTemplateDeclaration = isInTemplateFunctionDeclaration || isInTemplateClassDefinition;
382
383 ignore_error = ignore_error || (isSgTypedefDeclaration(decl) != nullptr) || (isSgTemplateInstantiationDecl(decl) != nullptr) || (isInTemplateDeclaration == true);
384
385 // DQ (2/5/2015): We need to ignore the case of un-named classes (or maybe those classes
386 // from unnamed classes with lambda member functions). See test2015_13.C for an example.
387 // Or maybe these should have been added to the declarationMap in the front-end?
388 if (isSgClassDeclaration(decl) != nullptr)
389 {
390 ignore_error = ignore_error || (isSgClassDeclaration(decl)->get_isUnNamed() == true);
391 }
392 }
393 }
394 }
395 else
396 {
397 // Add the declaration (make sure there is a set that exists).
398 if (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end())
399 {
400 // Make sure it does not already exist in the set.
401 ROSE_ASSERT (declarationMap[firstNondefiningDeclaration] != nullptr);
402 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
403 {
404 // Add a declaration to an existing set.
405 declarationMap[firstNondefiningDeclaration]->insert(decl);
406 }
407 else
408 {
409#if 0
410 printf ("This declaration is already in the set (skip adding it twice): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
411#endif
412 }
413 }
414 else
415 {
416 // In this case the defining declaration might be the only declaration to be traversed and
417 // so a set has not been built yet.
418#if 0
419 printf ("In SageInterface::DeclarationSets::addDeclaration(): Adding set and declaration for the firstNondefiningDeclaration = %p = %s = %s \n",
420 firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str(),get_name(firstNondefiningDeclaration).c_str());
421#endif
422
423 // DQ (4/5/2014): Just build the set and don't insert the firstNondefiningDeclaration.
424 // If we were to do so then it would be an error to use the insert it later.
425 // Note recursive call.
426 // addDeclaration(firstNondefiningDeclaration);
427 declarationMap[firstNondefiningDeclaration] = new set<SgDeclarationStatement*>();
428
429 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
430
431 // DQ (4/5/2014): We have to insert this since it is different from the firstNondefiningDeclaration.
432 // Add the declaration to the existing set.
433 declarationMap[firstNondefiningDeclaration]->insert(decl);
434
435 // DQ (4/5/2014): Added assertion.
436 ROSE_ASSERT(declarationMap[firstNondefiningDeclaration]->find(decl) != declarationMap[firstNondefiningDeclaration]->end());
437#if 0
438 printf ("SageInterface::DeclarationSets::addDeclaration(): No set exists for the firstNondefiningDeclaration = %p = %s = %s \n",firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str(),get_name(firstNondefiningDeclaration).c_str());
439 ROSE_ABORT();
440#endif
441 }
442 }
443
444#if 0
445 printf ("Leaving SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
446#endif
447 }
448
449const std::set<SgDeclarationStatement*>*
450SageInterface::DeclarationSets::getDeclarations(SgDeclarationStatement* decl)
451 {
452 // DQ (4/3/2014): This function returns the associated set of declarations.
453 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
454
455 ROSE_ASSERT(declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
456
457 const set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
458
459 // return this->declarationMap[firstNondefiningDeclaration];
460 return declarationSet;
461 }
462
463std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* > &
464SageInterface::DeclarationSets::getDeclarationMap()
465 {
466 return declarationMap;
467 }
468
469bool
470SageInterface::DeclarationSets::isLocatedInDefiningScope(SgDeclarationStatement* decl)
471 {
472 // DQ (4/7/2014): This function assumes that the input is a friend declaration.
473
474 // The existence of a declaration in a named scope (if a friend function) will cause
475 // subsequent declarations to be qualified where name qualification is required.
476 // A couple of issues:
477 // We likely need to keep track of the order of the declarations in the more
478 // complex cases because name qualification will be required after the declaration
479 // that appears in the named scope; but will not be required before the declaration in
480 // the named scope.
481
482#define DEBUG_LOCATED_IN_DEFINING_SCOPE 0
483
484 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
485 ROSE_ASSERT(firstNondefiningDeclaration != nullptr);
486
487 set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
488 ROSE_ASSERT(declarationSet != nullptr);
489
490 set<SgDeclarationStatement*>::iterator i = declarationSet->begin();
491
492 bool isDefinedInNamedScope = false;
493
494#if DEBUG_LOCATED_IN_DEFINING_SCOPE
495 printf ("In DeclarationSets::isLocatedInDefiningScope(): decl = %p = %s \n",decl,decl->class_name().c_str());
496 printf (" --- declarationSet->size() = %" PRIuPTR " \n",declarationSet->size());
497#endif
498
499 while (isDefinedInNamedScope == false && i != declarationSet->end())
500 {
501 ROSE_ASSERT(*i != nullptr);
502#if DEBUG_LOCATED_IN_DEFINING_SCOPE
503 printf (" --- *i = %p = %s \n",*i,(*i)->class_name().c_str());
504#endif
505 // We want to know the structural position, not the semantic scope.
506 SgScopeStatement* semantic_scope = (*i)->get_scope();
507 SgScopeStatement* structural_scope = isSgScopeStatement((*i)->get_parent());
508
509#if DEBUG_LOCATED_IN_DEFINING_SCOPE
510 printf (" --- semantic_scope = %p = %s \n",semantic_scope,semantic_scope->class_name().c_str());
511 printf (" --- structural_scope = %p = %s \n",structural_scope,structural_scope->class_name().c_str());
512#endif
513 // DQ (4/7/2014): If it is a member of a class then we don't consider the structural scope, else it makes a difference,
514 SgScopeStatement* scope = isSgClassDefinition(semantic_scope) != nullptr ? semantic_scope : structural_scope;
515 ASSERT_not_null(scope);
516
517#if DEBUG_LOCATED_IN_DEFINING_SCOPE
518 printf (" --- scope = %p = %s \n",scope,scope->class_name().c_str());
519 printf (" --- scope->isNamedScope() = %s \n",scope->isNamedScope() ? "true" : "false");
520#endif
521 SgGlobal* globalScope = isSgGlobal(scope);
522
523 // Friend functions declared in the class definition are not meaningful for determining name qualification.
524 if (globalScope != nullptr || (scope->isNamedScope() == true && isSgClassDefinition(structural_scope) == nullptr) )
525 {
526 // Check if the function is output in the unparing, else it would not be defined.
527 bool willBeOutput = ((*i)->get_file_info()->isCompilerGenerated() == false ||
528 ((*i)->get_file_info()->isCompilerGenerated() &&
529 (*i)->get_file_info()->isOutputInCodeGeneration()) );
530#if DEBUG_LOCATED_IN_DEFINING_SCOPE
531 printf (" --- before: willBeOutput = %s \n",willBeOutput ? "true" : "false");
532#endif
533 // Being output only count when it is output where it is located structurally.
534 willBeOutput = willBeOutput && scope == structural_scope;
535
536#if DEBUG_LOCATED_IN_DEFINING_SCOPE
537 printf (" --- after: willBeOutput = %s \n",willBeOutput ? "true" : "false");
538#endif
539 // DQ (3/20/2016): this is reported by GNU as set but not used.
540 // associatedDeclaration = *i;
541
542 // isDefinedInNamedScope = true;
543 isDefinedInNamedScope = willBeOutput;
544 }
545
546 i++;
547 }
548
549#if DEBUG_LOCATED_IN_DEFINING_SCOPE
550 if (associatedDeclaration != nullptr)
551 {
552 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p = %s \n",associatedDeclaration,associatedDeclaration->class_name().c_str());
553 }
554 else
555 {
556 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p \n",associatedDeclaration);
557 }
558#endif
559
560 return isDefinedInNamedScope;
561 }
562
564SageInterface::buildDeclarationSets(SgNode* n)
565 {
566 DeclarationSets* declarationSet = new DeclarationSets();
567
568 class DeclarationSetTraversal : public AstSimpleProcessing
569 {
570 private:
571 DeclarationSets* declarationSet;
572
573 public:
574 DeclarationSetTraversal(DeclarationSets* ds) : declarationSet(ds) {}
575 void visit (SgNode* node)
576 {
577 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
578 if (decl != nullptr)
579 {
580 declarationSet->addDeclaration(decl);
581 }
582 }
583 };
584
585 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
586 DeclarationSetTraversal traversal(declarationSet);
587 traversal.traverse(n, preorder);
588
589 return declarationSet;
590 }
591
593// DQ: 09/23/03
594// We require a global function for getting the string associated
595// with the definition of a variant (which is a global enum).
596string getVariantName ( VariantT v )
597 {
598 ROSE_ASSERT( int(v) < int(V_SgNumVariants));
599
600 // This code is far simpler (if the function is static)
601
602 // DQ (4/8/2004): Modified code to use new global list of sage
603 // class names (simpler this way)
604 // return string(SgTreeTraversal<int,int>::get_variantName(v));
605 extern const char* roseGlobalVariantNameList[];
606 return string(roseGlobalVariantNameList[v]);
607 }
608
609bool
611 {
612 // DQ (6/7/2012): This refactors the test for template instantiation syntax in names used for classes, member functions, and functions
613 bool usingTemplateSyntax = false;
614 string nameString = name.getString();
615
616 // DQ (6/7/2012): We need to avoid the identification of the "operator<()" as valid template syntax.
617 usingTemplateSyntax = (nameString.find('<') != string::npos) && (nameString.find('>') != string::npos);
618
619 // DQ (5/10/2016): Debugging case of C++11 using the Intel v16 compiler and it's associated mutex header file.
620 // See Cxx11_tests/test2016_32.C for an example that demonstrates this problem.
621 if (nameString == "<unnamed>")
622 {
623 printf ("In SageInterface::hasTemplateSyntax(): Identified case of name == <unnamed> \n");
624
625 usingTemplateSyntax = false;
626 }
627
628 // return (name.getString().find('<') == string::npos);
629 return usingTemplateSyntax;
630 }
631
632
633
634void
636 {
637 // DQ (2/12/2012): Refactoring disagnostic support for detecting where we are when something fails.
638
639 // This highest level node acceptable for us by this function is a SgGlobal (global scope).
640
641 ROSE_ASSERT(node != NULL);
642// printf ("Inside of SageInterface::whereAmI(node = %p = %s) \n",node,node->class_name().c_str());
643
644 // Enforce that some IR nodes should not be acepted inputs.
645 ROSE_ASSERT(isSgFile(node) == NULL);
646 ROSE_ASSERT(isSgFileList(node) == NULL);
647 ROSE_ASSERT(isSgProject(node) == NULL);
648
649 SgNode* parent = node->get_parent();
650
651 // Don't traverse past the SgFile level.
652 while (parent != nullptr && isSgFileList(parent) == nullptr)
653 {
654 // DQ (7/14/2019): These were commented out, but they are intended for debugging, so
655 // if someone does not need this output then the function should not have been called.
656 printf ("--- parent = %p = %s \n",parent,parent->class_name().c_str());
657
658 ROSE_ASSERT(parent->get_file_info() != NULL);
659 parent->get_file_info()->display("In SageInterface::whereAmI() diagnostics support");
660
661 parent = parent->get_parent();
662 }
663 }
664
665void
666SageInterface::initializeIfStmt(SgIfStmt *ifstmt, SgStatement* conditional, SgStatement * true_body, SgStatement * false_body)
667 {
668 // DQ (2/13/2012): Added new function to support proper initialization of a SgIfStmt that has already been built.
669 // This is important when we have to build the scope ahead of the test becasue the text contains a simple
670 // declaration (which must be put into the SgIfStmt scope).
671
672 // SgIfStmt *ifstmt = new SgIfStmt(conditional, true_body, false_body);
673 ROSE_ASSERT(ifstmt);
674
675 if (ifstmt->get_conditional() == nullptr)
676 ifstmt->set_conditional(conditional);
677
678 if (ifstmt->get_true_body() == nullptr)
679 ifstmt->set_true_body(true_body);
680
681 if (ifstmt->get_false_body() == nullptr)
682 ifstmt->set_false_body(false_body);
683
684 // Rasmussen (3/22/2020): Fixed setting case insensitivity
686 ifstmt->setCaseInsensitive(true);
687
689 if (conditional) conditional->set_parent(ifstmt);
690 if (true_body) true_body->set_parent(ifstmt);
691 if (false_body) false_body->set_parent(ifstmt);
692 }
693
694
695void
697 {
698 ROSE_ASSERT(switchStatement != NULL);
699
700 // Rasmussen (3/22/2020): Fixed setting case insensitivity
702 switchStatement->setCaseInsensitive(true);
703
704 if (switchStatement->get_item_selector() == nullptr)
705 switchStatement->set_item_selector(item_selector);
706
707 if (switchStatement->get_body() == nullptr)
708 switchStatement->set_body(body);
709
711 if (item_selector != nullptr)
712 item_selector->set_parent(switchStatement);
713 if (body != nullptr)
714 body->set_parent(switchStatement);
715 }
716
717
718void
720 {
721 ROSE_ASSERT(whileStatement);
722
723 // Rasmussen (3/22/2020): Fixed setting case insensitivity
725 whileStatement->setCaseInsensitive(true);
726
727 if (whileStatement->get_condition() == nullptr)
728 whileStatement->set_condition(condition);
729 if (whileStatement->get_body() == nullptr)
730 whileStatement->set_body(body);
731
732 // Python support.
733 if (whileStatement->get_else_body() == nullptr)
734 whileStatement->set_else_body(else_body);
735
736 setOneSourcePositionNull(whileStatement);
737 if (condition) condition->set_parent(whileStatement);
738 if (body) body->set_parent(whileStatement);
739
740 // DQ (8/10/2011): This is added by Michael to support a Python specific feature.
741 if (else_body != nullptr)
742 {
743 whileStatement->set_else_body(else_body);
744 else_body->set_parent(whileStatement);
745 }
746 }
747
748
749
752 {
753 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
754
755 // This function returns the namespace associated with any declaration.
756 // If the declaration is nested inside of other scopes this function
757 // iterates through these scopes to get the the first namespace.
758 // This is important for details of template handling, namely making sure
759 // that the template specializations (generated by ROSE) are put into the
760 // correct location (namespace) since stricted rules in gnu now enforce
761 // these details. If the declaration is not in a namespace as computed
762 // in the chain of scopes then this function returns nullptr.
763
764 ROSE_ASSERT(declaration != NULL);
765 SgScopeStatement* tempScope = declaration->get_scope();
766
767 // Loop back to the first namespace or stop at global scope (stop on either a namespace or the global scope)
768 while ( isSgNamespaceDefinitionStatement(tempScope) == nullptr && isSgGlobal(tempScope) == nullptr )
769 {
770 tempScope = tempScope->get_scope();
771 ROSE_ASSERT(tempScope != NULL);
772#if 0
773 printf ("Iterating back through scopes: tempScope = %p = %s = %s \n",tempScope,tempScope->class_name().c_str(),SageInterface::get_name(tempScope).c_str());
774#endif
775 }
776
777 SgNamespaceDefinitionStatement* namespaceScope = isSgNamespaceDefinitionStatement(tempScope);
778 return namespaceScope;
779 }
780
781
784 {
785 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
786 // DQ (11/4/2007): Get the associated declaration that will be in the original source code,
787 // if it is part of a template instantiation then get the original template declaration.
788
789 SgDeclarationStatement* parentDeclaration = nullptr;
790
791 SgScopeStatement* defn = memberFunctionInstantiation->get_class_scope();
792 ASSERT_not_null(defn);
793
794 // SgTemplateDeclaration* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
795 SgDeclarationStatement* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
796 ASSERT_not_null(templateDeclaration);
797
798 // If it is a template instatiation, then we have to find the temple declaration (not the template instantiation declaration), else we want the class declaration.
799 SgClassDefinition* cdefn = isSgClassDefinition(defn);
800 SgDeclarationScope* nrscope = isSgDeclarationScope(defn);
801 SgTemplateInstantiationDefn* templateInstatiationClassDefinition = isSgTemplateInstantiationDefn(defn);
802 if (templateInstatiationClassDefinition != nullptr)
803 {
804 // This is the case of a template member function in a templated class (see test2005_172.C).
805 SgTemplateInstantiationDefn* parentTemplateInstantiationDefinition = isSgTemplateInstantiationDefn(templateDeclaration->get_scope());
806 ASSERT_not_null(parentTemplateInstantiationDefinition);
807 SgTemplateInstantiationDecl* parentTemplateInstantiationDeclaration = isSgTemplateInstantiationDecl(parentTemplateInstantiationDefinition->get_declaration());
808 ASSERT_not_null(parentTemplateInstantiationDeclaration);
809
810 parentDeclaration = parentTemplateInstantiationDeclaration->get_templateDeclaration();
811 ASSERT_not_null(parentDeclaration);
812 }
813 else if (cdefn != nullptr)
814 {
815 // This is the case of a template member function in a class definition (see test2005_168.C).
816 parentDeclaration = cdefn->get_declaration();
817 ASSERT_not_null(parentDeclaration);
818 }
819 else if (nrscope != nullptr)
820 {
821 parentDeclaration = isSgDeclarationStatement(nrscope->get_parent());
822 ASSERT_not_null(parentDeclaration);
823 }
824 else
825 {
826 ROSE_ABORT();
827 }
828
829 return parentDeclaration;
830 }
831
835void
837{
838 ASSERT_not_null(var_decl);
839 ASSERT_not_null(base_decl);
840
841 // There is a bug (see gitlab-issue-349.jov) that arises when base_decl has a comment and it is the
842 // first statement, because base_decl will be removed (causing comments to be moved, where? good question!).
843 // Consider moving comments to var_decl first to circumvent (by artfulness or deception) potential problems.
844 // [Rasmussen 2024.04.10]
845
846 // try to remove it from the scope's declaration list
847 // If the struct decl was previously inserted into its scope
848 if (base_decl->get_parent() != nullptr)
849 {
850 if (base_decl->get_scope() == base_decl->get_parent())
851 {
852 SgStatementPtrList stmt_list = base_decl->get_scope()->generateStatementList();
853 if (find(stmt_list.begin(), stmt_list.end(), base_decl) != stmt_list.end())
855 }
856 }
857 base_decl->set_parent(var_decl);
858 var_decl->set_baseTypeDefiningDeclaration(base_decl);
859
860 //Set an internal mangled name for the anonymous declaration, if necessary
861 // resetNamesInAST(); // this will trigger mangleNameMap.size() ==0 assertion.
862 // We call resetEmptyNames directly instead.
863 ResetEmptyNames t1;
864 t1.traverseMemoryPool();
865}
866
867// DQ (11/4/2007): This looks for a forward temple member function declaration of matching name exists in the specified scope.
868bool
870 {
871 // DQ (11/3/2007): Look for an existing previously inserted (or existing) template member function declaration and only add one if we can't find it.
872
873 bool foundExistingPrototype = false;
874
875 ROSE_ASSERT(scope != NULL);
876 ROSE_ASSERT(functionDeclaration != NULL);
877 ROSE_ASSERT(startingAtDeclaration != NULL);
878
879 // TV (09/17/2018): ROSE-1378
880 if (isSgDeclarationScope(scope)) {
881 printf("TODO: SgDeclarationScope handling in SageInterface::isPrototypeInScope see ROSE-1378\n");
882 return false;
883 }
884
885 // These are the scopes for which get_declarationList() is properly defined.
886 ROSE_ASSERT(scope->containsOnlyDeclarations() == true);
887
888 // Note that this is only defined for certain scopes, but we only want it for THOSE scopes
889 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
890
891 // This is a simple way to restrict the evaluation (still linear, but jumps to initial position to start search).
892 SgDeclarationStatementPtrList::iterator startingLocation = find(declarationList.begin(),declarationList.end(),startingAtDeclaration);
893
894 if (startingLocation != declarationList.end())
895 {
896#if 0
897 printf ("startingLocation = %p = %s = %s \n",*startingLocation,(*startingLocation)->class_name().c_str(),SageInterface::get_name(*startingLocation).c_str());
898#endif
899 // printf ("Found the startingLocation is the global scope, now check if we need to add a new declaration \n");
900 SgDeclarationStatementPtrList::iterator i = startingLocation;
901 SgScopeStatement* targetScope = functionDeclaration->get_scope();
902 SgName targetName = functionDeclaration->get_name();
903
904 while (i != declarationList.end())
905 {
906 // printf ("i = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
907
908 // Look for a prototype like what we want to insert, if we find it then we don't need to add a second one!
909 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(*i);
910 if (templateMemberFunction != nullptr)
911 {
912 // Check the name and the scope
913 if (targetScope == templateMemberFunction->get_scope())
914 {
915 if (targetName == templateMemberFunction->get_name())
916 {
917 // Don't count the defining declaration which may be at the end of the global scope.
918 if (templateMemberFunction->isForward() == true)
919 {
920 foundExistingPrototype = true;
921
922 // Exit the loop (optimization)
923 break;
924 }
925 }
926 }
927 }
928
929 i++;
930 }
931 }
932
933 return foundExistingPrototype;
934 }
935
936bool
938 {
939 ROSE_ASSERT(node1 && node2);
940
941 SgNode* curnode = node2;
942 if (node1==node2)
943 {
944 return false;
945 }
946
947 do {
948 curnode= curnode->get_parent();
949 } while( (curnode!=nullptr) && (curnode!=node1));
950
951 if (curnode==node1)
952 {
953 return true;
954 }
955 else
956 {
957 return false;
958 }
959 }
960
961bool
963 {
964 // DQ (12/7/2020): This is supporting the recognition of functions in header files from two different AST.
965
966#define DEBUG_HAS_SAME_SCOPE 0
967
968#if DEBUG_HAS_SAME_SCOPE
969 printf ("In SageInterface::hasSameGlobalScope(): \n");
970 printf (" --- statement_1 = %p = %s \n",statement_1,statement_1->class_name().c_str());
971 printf (" --- statement_2 = %p = %s \n",statement_2,statement_2->class_name().c_str());
972#endif
973
974 bool includingSelf = true;
975 SgGlobal* global_scope_1 = getEnclosingNode<SgGlobal>(statement_1,includingSelf);
976 SgGlobal* global_scope_2 = getEnclosingNode<SgGlobal>(statement_2,includingSelf);
977
978#if DEBUG_HAS_SAME_SCOPE
979 printf (" --- global_scope_1 = %p = %s \n",global_scope_1,global_scope_1->class_name().c_str());
980 SgSourceFile* sourcefile_1 = isSgSourceFile(global_scope_1->get_parent());
981 printf (" --- --- sourcefile_1 = %p filename = %s \n",sourcefile_1,sourcefile_1->getFileName().c_str());
982
983 printf (" --- global_scope_2 = %p = %s \n",global_scope_2,global_scope_2->class_name().c_str());
984 SgSourceFile* sourcefile_2 = isSgSourceFile(global_scope_2->get_parent());
985 printf (" --- --- sourcefile_2 = %p filename = %s \n",sourcefile_2,sourcefile_2->getFileName().c_str());
986#endif
987
988 bool returnResult = (global_scope_1 == global_scope_2);
989
990#if DEBUG_HAS_SAME_SCOPE
991 printf ("Leaving SageInterface::hasSameGlobalScope(): returning: %s \n",returnResult ? "true" : "false");
992#endif
993
994 return returnResult;
995 }
996
997
998std::vector<SgNode*>
1000 {
1001 std::vector<SgNode*> intersectionSet;
1002
1003 // Collect all the IR nodes for the original AST
1004 std::vector<SgNode*> AST_original = NodeQuery::querySubTree (original,V_SgNode);
1005 std::vector<SgNode*> AST_copy = NodeQuery::querySubTree (copy,V_SgNode);
1006
1007 int AST_original_size = AST_original.size();
1008 int AST_copy_size = AST_copy.size();
1009
1010 if (SgProject::get_verbose() > 0)
1011 {
1012 printf ("Original AST size = %d \n",AST_original_size);
1013 printf ("Copy of original AST size = %d \n",AST_copy_size);
1014 }
1015
1016 int differenceInSizes = AST_original_size - AST_copy_size;
1017 if (differenceInSizes == 0)
1018 {
1019 if (SgProject::get_verbose() > 0)
1020 printf ("Copied AST is the SAME size as the original (size = %d) \n",AST_original_size);
1021 }
1022 else
1023 {
1024 printf ("Warning: Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) \n",AST_original_size,AST_copy_size);
1025 }
1026
1027 // Compute the intersection (reference in the copy that point to the origal AST).
1028 // std::set<SgNode*> AST_set_original = AST_original;
1029 std::set<SgNode*> AST_set_original;
1030 for (int i = 0; i < AST_original_size; i++)
1031 {
1032 AST_set_original.insert(AST_original[i]);
1033 }
1034
1035 std::set<SgNode*> AST_set_copy;
1036 for (int i = 0; i < AST_copy_size; i++)
1037 {
1038 AST_set_copy.insert(AST_copy[i]);
1039 }
1040
1041 int size = AST_original_size;
1042 std::vector<SgNode*> intersectionList(size);
1043
1044 // Is there a better way to do this? Build scratch space and then use the different between begin() and end to build another vector.
1045 std::vector<SgNode*>::iterator end = set_intersection(AST_set_original.begin(),AST_set_original.end(),AST_set_copy.begin(),AST_set_copy.end(),intersectionList.begin());
1046
1047 // Build a new vector from the relevant elements of the intersectionList scratch space.
1048 std::vector<SgNode*> meaningIntersectionList = std::vector<SgNode*>(intersectionList.begin(),end);
1049 std::vector<SgNode*> deleteList;
1050 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
1051 {
1052 if (meaningIntersectionList[i] != nullptr && isSgType(meaningIntersectionList[i]) != nullptr)
1053 {
1054 deleteList.push_back(meaningIntersectionList[i]);
1055 }
1056 }
1057
1058 // Remove the types since they are allowed to be shared...
1059 if (SgProject::get_verbose() > 0)
1060 printf ("Remove the types that are allowed to be shared: deleteList.size() = %ld \n",(long)deleteList.size());
1061
1062 for (std::vector<SgNode*>::iterator i = deleteList.begin(); i != deleteList.end(); i++)
1063 {
1064 meaningIntersectionList.erase(find(meaningIntersectionList.begin(),meaningIntersectionList.end(),*i));
1065 }
1066
1067 if (SgProject::get_verbose() > 0)
1068 printf ("After removing the types there are meaningIntersectionList.size() = %ld \n",(long)meaningIntersectionList.size());
1069
1070 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
1071 {
1072 printf (" meaningIntersectionList[%d] = %p = %s = %s \n",i,meaningIntersectionList[i],meaningIntersectionList[i]->class_name().c_str(),get_name(meaningIntersectionList[i]).c_str());
1073 }
1074
1075 int unmatchedIRnodes = 0;
1076 if (help != nullptr)
1077 {
1078 std::vector<SgNode*> tmp_AST_original; // = AST_original;
1079 std::vector<SgNode*> tmp_AST_copy; // = AST_copy;
1080
1081 int AST_original_size = AST_original.size();
1082 for (int j = 0; j < AST_original_size; j++)
1083 {
1084 if (AST_original[j] != NULL && isSgType(AST_original[j]) == NULL)
1085 {
1086 tmp_AST_original.push_back(AST_original[j]);
1087 }
1088 }
1089
1090 int AST_copy_size = AST_copy.size();
1091 for (int j = 0; j < AST_copy_size; j++)
1092 {
1093 if (AST_copy[j] != NULL && isSgType(AST_copy[j]) == NULL)
1094 {
1095 tmp_AST_copy.push_back(AST_copy[j]);
1096 }
1097 }
1098
1099 std::vector<SgNode*> deleteList_original;
1100 std::vector<SgNode*> deleteList_copy;
1101 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1102 {
1103 // printf (" (before removing types) meaningIntersectionList[%d] = %p = %s \n",i,meaningIntersectionList[i],(meaningIntersectionList[i] != NULL) ? meaningIntersectionList[i]->class_name().c_str() : "NULL");
1104 SgCopyHelp::copiedNodeMapTypeIterator i = help->get_copiedNodeMap().find(tmp_AST_original[j]);
1105 // printf ("SgCopyHelp::copiedNodeMapTypeIterator i != help->get_copiedNodeMap().end() = %s \n",i != help->get_copiedNodeMap().end() ? "true" : "false");
1106 if (i != help->get_copiedNodeMap().end())
1107 {
1108 // Matched up an original IR node with it's copy
1109 SgNode* associated_node_copy = i->second;
1110 ROSE_ASSERT(associated_node_copy != NULL);
1111 deleteList_original.push_back(tmp_AST_original[j]);
1112 deleteList_copy.push_back(associated_node_copy);
1113#if 0
1114 // printf ("Original IR node = %p = %s copy = %p \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),associated_node_copy);
1115 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(tmp_AST_original[j]);
1116 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction_copy = isSgTemplateInstantiationMemberFunctionDecl(associated_node_copy);
1117 if (templateMemberFunction != NULL)
1118 {
1119 printf ("In SageInterface::astIntersection(): Found a SgTemplateInstantiationMemberFunctionDecl = %p copy = %p \n",templateMemberFunction,associated_node_copy);
1120 // templateMemberFunction->get_startOfConstruct()->display("original: debug");
1121 // templateMemberFunction_copy->get_startOfConstruct()->display("copy: debug");
1122 }
1123#endif
1124 }
1125 }
1126
1127 int deleteList_original_size = deleteList_original.size();
1128 for (int j = 0; j < deleteList_original_size; j++)
1129 {
1130 // tmp_AST_original.erase(find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]));
1131 std::vector<SgNode*>::iterator k = find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]);
1132 if (k != tmp_AST_original.end())
1133 {
1134 tmp_AST_original.erase(k);
1135 }
1136 }
1137
1138 if (SgProject::get_verbose() > 0)
1139 printf ("IR nodes different between the original AST and the copy of the AST = %" PRIuPTR " \n",tmp_AST_original.size());
1140
1141 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1142 {
1143 printf ("non matched IR node = %p = %s = %s \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),get_name(tmp_AST_original[j]).c_str());
1144 // tmp_AST_original[j]->get_startOfConstruct()->display("debug");
1145 }
1146
1147 unmatchedIRnodes = (int)tmp_AST_original.size();
1148 }
1149
1150 // DQ (11/2/2007): Make this an error now!
1151 if (differenceInSizes != 0)
1152 {
1153 SgProject* originalProject = isSgProject(original);
1154 if (originalProject != NULL)
1155 {
1156 printf ("In %s Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) IR nodes different = %d \n",
1157 (*originalProject)[0]->get_sourceFileNameWithoutPath().c_str(),AST_original_size,AST_copy_size,unmatchedIRnodes);
1158 }
1159
1160 if (unmatchedIRnodes > 0)
1161 {
1162 printf ("Make this an error under stricter testing \n");
1163 ROSE_ABORT();
1164 }
1165 }
1166
1167 return intersectionSet;
1168 }
1169
1170// AJ (10/21/2004): Added support for changing the symbol name associated with an SgInitializedName
1171// by updating the symbol table
1172int
1173SageInterface::set_name ( SgInitializedName *initializedNameNode, SgName new_name )
1174 {
1175 // find the appropriate symbol table, delete the symbol
1176 // with the old name and add a symbol with the new name.
1177 ROSE_ASSERT(initializedNameNode != NULL);
1178
1179#define DEBUG_SET_NAME 0
1180
1181 // SgNode * node = this;
1182#if DEBUG_SET_NAME
1183 printf ("In SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1184#endif
1185
1186#if 0
1187 // DQ (12/9/2004): This should likely call the get_scope function (which is more robust than traversing
1188 // parents, there is a reason why we are forced to include the scope explicitly on some IR nodes,
1189 // see test2004_133.C for details).
1190 while((node!=NULL) && ( isSgScopeStatement(node)==NULL))
1191 node = node->get_parent();
1192
1193 ROSE_ASSERT(node!=NULL);
1194
1195 SgScopeStatement * scope_stmt = isSgScopeStatement(node);
1196#else
1197 SgScopeStatement *scope_stmt = initializedNameNode->get_scope();
1198#endif
1199
1200 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1201 if (isSgEnumDeclaration(initializedNameNode->get_parent()) != NULL)
1202 {
1203 ROSE_ASSERT(scope_stmt != NULL);
1204 printf ("scope_stmt = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1205#if 0
1206 printf ("Detected isSgEnumDeclaration as parent: exiting as a test in SageInterface::set_name() \n");
1207 ROSE_ASSERT(false);
1208#endif
1209 }
1210
1211 ROSE_ASSERT(scope_stmt != NULL);
1212 ROSE_ASSERT(scope_stmt->get_symbol_table() != NULL);
1213 ROSE_ASSERT(scope_stmt->get_symbol_table()->get_table() != NULL);
1214
1215 SgDeclarationStatement * parent_declaration = initializedNameNode->get_declaration();
1216
1217 ROSE_ASSERT(parent_declaration != NULL);
1218
1219 // Find the symbols associated with p_name
1220 std::pair<SgSymbolTable::hash_iterator,SgSymbolTable::hash_iterator> pair_it = scope_stmt->get_symbol_table()->get_table()->equal_range(initializedNameNode->get_name());
1221
1222 SgSymbolTable::hash_iterator found_it = scope_stmt->get_symbol_table()->get_table()->end();
1223
1224 for (SgSymbolTable::hash_iterator it = pair_it.first; it != pair_it.second; ++it)
1225 {
1226#if DEBUG_SET_NAME
1227 printf ("Looking for symbol in scope = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1228 printf (" --- *it = %p = %s \n",(*it).second,(*it).second->class_name().c_str());
1229#endif
1230 switch(parent_declaration->variantT())
1231 {
1232 case V_SgFunctionParameterList:
1233 case V_SgVariableDeclaration:
1234 {
1235 if (isSgVariableSymbol((*it).second) != NULL)
1236 found_it = it;
1237 break;
1238 }
1239
1240 case V_SgClassDeclaration:
1241 {
1242 if (isSgClassSymbol((*it).second) != NULL)
1243 found_it = it;
1244 break;
1245 }
1246
1247 case V_SgFunctionDeclaration:
1248 {
1249 if (isSgFunctionSymbol((*it).second) != NULL)
1250 found_it = it;
1251 break;
1252 }
1253
1254 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1255 case V_SgEnumDeclaration:
1256 {
1257 if (isSgEnumFieldSymbol((*it).second) != NULL)
1258 found_it = it;
1259 break;
1260 }
1261
1262 default:
1263 {
1264 printf ("Default reached in switch in SageInterface::set_name() \n");
1265 }
1266 };
1267 }
1268
1269 // there is no Variable, Class or Function symbol associated with p_name
1270 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1271 {
1272 printf ("Warning: There is no Variable, Class, Function, or EnumValue symbol associated with p_name \n");
1273 return 0;
1274 }
1275
1276 // DQ (11/12/2018): In general, this can't be tested if we permit it to be transformed.
1277 if (statementCanBeTransformed(parent_declaration) == false)
1278 {
1279 printf ("WARNING: SageInterface::set_name(): This statement can not be transformed because it is part of a header file specific more then once with different include file syntax \n");
1280 return 0;
1281 }
1282 else
1283 {
1284#if DEBUG_SET_NAME
1285 printf ("In SageInterface::set_name(): This statement can be transformed! parent_declaration = %p = %s \n",parent_declaration,get_name(parent_declaration).c_str());
1286#endif
1287
1288#if 0
1289 // DQ (11/12/2018): Initial test problem should not permit a transformation!
1290 printf ("Exiting as a test! \n");
1291 ROSE_ABORT();
1292#endif
1293 }
1294
1295 SgSymbol * associated_symbol = (*found_it).second;
1296
1297 // erase the name from there
1298 scope_stmt->get_symbol_table()->get_table()->erase(found_it);
1299
1300 // insert the new_name in the symbol table
1301// CH (4/9/2010): Use boost::unordered instead
1302//#ifdef _MSCx_VER
1303#if 0
1304 // DQ (11/28/2009): Unclear if this code is a problem (testing).
1305
1306// CH (4/7/2010): It seems that the following code can be compiled under MSVC 9.0
1307//#pragma message ("WARNING: this code does not apprear to compile with MSVC.")
1308// printf ("ERROR: this code does not apprear to compile with MSVC. \n");
1309// ROSE_ASSERT(false);
1310 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1311#else
1312 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1313#endif
1314 // if insertion failed
1315 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1316 {
1317 printf ("Warning: insertion of new symbol failed \n");
1318 return 0;
1319 }
1320
1321#if DEBUG_SET_NAME
1322 // Set the p_name to the new_name
1323 printf ("Reset initializedNameNode->get_name() = %s to new_name = %s \n",initializedNameNode->get_name().str(),new_name.str());
1324#endif
1325
1326 // p_name = new_name;
1327 initializedNameNode->set_name(new_name);
1328
1329 // DQ (11/30/2018): Mark the enclosing statement as modified, so that it will be recognized
1330 // in the header file unparsing as being a header file that should be unparsed.
1331 SgStatement* enclosingStatement = getEnclosingStatement(initializedNameNode);
1332 ROSE_ASSERT(enclosingStatement != NULL);
1333 enclosingStatement->set_isModified(true);
1334 enclosingStatement->setTransformation();
1335
1336 // Invalidate the p_iterator, p_no_name and p_name data members in the Symbol table
1337
1338#if 1
1339 // Search the AST for references to this SgInitializedName (SgVarRefExp), check if the symbol matches
1340 // (we can do this since we only reused the exisitng symbol), and mark those expressions as modified.
1341 class RoseVisitor : public ROSE_VisitTraversal
1342 {
1343 public:
1344 int counter;
1345 SgSymbol* symbol;
1346
1348 void visit (SgNode* node)
1349 {
1350 SgVarRefExp* varRefExp = isSgVarRefExp(node);
1351 SgVariableSymbol* variableSymbol = isSgVariableSymbol(symbol);
1352
1353 ROSE_ASSERT(varRefExp != NULL);
1354 ROSE_ASSERT(variableSymbol != NULL);
1355
1356 if (varRefExp->get_symbol() == variableSymbol)
1357 {
1358#if DEBUG_SET_NAME
1359 printf ("In SageInterface::set_name(): Found associated SgVarRefExp varRefExp = %p to symbol associated_symbol = %p \n",varRefExp,variableSymbol);
1360#endif
1361#if 0
1362 printf ("Exiting as a test! \n");
1363 ROSE_ABORT();
1364#endif
1365 varRefExp->set_isModified(true);
1366 varRefExp->setTransformation();
1367#if 1
1368 // DQ (5/2/2021): The traversal over the file will identify the nesting of and transformations in outer (enclosing) IR nodes.
1369 // DQ (5/1/2021): I think that we may have to set the physical node id and maybe make it to be output. This is
1370 // special to the case of using the header file unparsing (any maybe the token-based unparsing with the header
1371 // file unparsing, but I think just the header file unparsing).
1372#if 0
1373 printf ("In SageInterface::set_name(): When unparsing header files, we need to set the physical file id to the correct file \n");
1374#endif
1375 // DQ (4/23/2021): I think it is a problem that the statement is not marked as a transformation so that we
1376 // know how to handle it with the token-based unparsing.
1377 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1378 ROSE_ASSERT(associatedStatement != NULL);
1379 associatedStatement->setTransformation();
1380#endif
1381#if 0
1382 // DQ (11/13/2018): Mark the statement associated with this SgVarRefExp (see test9 in UnparseHeaders_tests).
1383 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1384 ROSE_ASSERT(associatedStatement != NULL);
1385 // associatedStatement->set_isModified(true);
1386 // associatedStatement->set_containsTransformation(true);
1387 associatedStatement->setTransformation();
1388#endif
1389 }
1390 }
1391
1392 RoseVisitor(SgSymbol* symbol_parmeter) : counter(0), symbol(symbol_parmeter)
1393 {
1394#if 0
1395 printf ("roseVisitor::visit: counter %4d node = %s \n",counter,symbol_parmeter->class_name().c_str());
1396#endif
1397 counter++;
1398 }
1399 };
1400
1401 // RoseVisitor visitor;
1402 // visitor.traverseMemoryPool();
1403 RoseVisitor t1(associated_symbol);
1405#endif
1406
1407#if DEBUG_SET_NAME
1408 printf ("Leaving SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s (return 1) \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1409#endif
1410
1411 // DQ (4/23/2021): I think that we should be returning zero for no error
1412 // and one for an error, this function appears to have this detail reversed.
1413 return 1;
1414 }
1415
1416
1417void
1419 {
1420 printf ("In SageInterface::listHeaderFiles(): includeFile filename = %s \n",includeFile->get_filename().str());
1421
1422 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
1423 class PrefixTraversal : public AstSimpleProcessing
1424 {
1425 public:
1426 void visit (SgNode* node)
1427 {
1428 printf ("In listHeaderFiles visit(): node = %p = %s \n",node,node->class_name().c_str());
1429 SgIncludeFile* includeFile = isSgIncludeFile(node);
1430 if (includeFile != NULL)
1431 {
1432 printf ("include file: filename = %s \n",includeFile->get_filename().str());
1433 }
1434 }
1435 };
1436
1437 // Now buid the traveral object and call the traversal (preorder) on the function definition.
1438 PrefixTraversal traversal;
1439 traversal.traverse(includeFile, preorder);
1440
1441 }
1442
1443
1444bool
1446 {
1447 // DQ (5/9/2021): Adding support for detection of statements in a scope that must be unparsed.
1448 // This function supports the token-based unparsing when used with unparsing of header files
1449 // to know when the scope can be unparsed via it's token stream, even though a statement from
1450 // a header file may contain a transformation.
1451 // returns true if there is a statement in the scope that has to be unparsed (is from the same file as the scope).
1452 // returns false if the scope is empty or contains only statements associated with one or more header files.
1453 // When the scope has statements from the same file, then if there is a transformation contained in any of
1454 // those statements then we have to unparse the scope one statement at a time when using the token-based
1455 // unparsing. If the scope has no statements from the same file, then the existance of any statement that
1456 // contains a transformation does not case the statements to be unparsed individually.
1457
1458 ROSE_ASSERT(scope != NULL);
1459 int scope_file_id = scope->get_file_info()->get_physical_file_id();
1460
1461 bool return_value = false;
1462
1463 if (scope->containsOnlyDeclarations() == true)
1464 {
1465 SgDeclarationStatementPtrList & declarationStatementList = scope->getDeclarationList();
1466#if 1
1467 printf ("In scopeHasStatementsFromSameFile(): DeclarationStatementList not implemented \n");
1468#endif
1469#if 1
1470 printf ("declarationStatementList.size() = %zu \n",declarationStatementList.size());
1471#endif
1472 SgDeclarationStatementPtrList::iterator i = declarationStatementList.begin();
1473
1474 while (i != declarationStatementList.end() && return_value == false)
1475 {
1476 SgDeclarationStatement* statement = *i;
1477 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1478
1479 if (statement_file_id == scope_file_id)
1480 {
1481 return_value = true;
1482 }
1483
1484 i++;
1485 }
1486#if 0
1487 printf ("Exiting as a test! \n");
1488 ROSE_ASSERT(false);
1489#endif
1490 }
1491 else
1492 {
1493 SgStatementPtrList & statementList = scope->getStatementList();
1494#if 1
1495 printf ("In scopeHasStatementsFromSameFile(): StatementList not implemented \n");
1496#endif
1497 SgStatementPtrList::iterator i = statementList.begin();
1498
1499 while (i != statementList.end() && return_value == false)
1500 {
1501 SgStatement* statement = *i;
1502 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1503
1504 if (statement_file_id == scope_file_id)
1505 {
1506 return_value = true;
1507 }
1508
1509 i++;
1510 }
1511 }
1512
1513 return return_value;
1514 }
1515
1516
1517namespace
1518{
1519 template <class SageDecl>
1520 std::string genericGetName(SageDecl* dcl)
1521 {
1522 ROSE_ASSERT(dcl);
1523 return dcl->get_name();
1524 }
1525}
1526
1527
1528
1529
1530string
1532 {
1533 string name = "undefined_name";
1534
1535 ROSE_ASSERT(directive != NULL);
1536
1537 name = directive->class_name();
1538
1539#if 1
1540 // I don't think we need this code now!
1541 switch (directive->variantT())
1542 {
1543 // Separate out these cases...
1544 case V_SgIncludeDirectiveStatement:
1545 case V_SgDefineDirectiveStatement:
1546 case V_SgUndefDirectiveStatement:
1547 case V_SgIfdefDirectiveStatement:
1548 case V_SgIfndefDirectiveStatement:
1549 case V_SgDeadIfDirectiveStatement:
1550 case V_SgIfDirectiveStatement:
1551 case V_SgElseDirectiveStatement:
1552 case V_SgElseifDirectiveStatement:
1553 case V_SgLineDirectiveStatement:
1554 case V_SgWarningDirectiveStatement:
1555 case V_SgErrorDirectiveStatement:
1556 case V_SgEmptyDirectiveStatement:
1557 {
1558 name = directive->class_name();
1559 break;
1560 }
1561
1562 // case ClinkageDeclarationStatement:
1563 case V_SgClinkageStartStatement:
1564 case V_SgClinkageEndStatement:
1565 {
1566 name = directive->class_name();
1567 break;
1568 }
1569
1570 case V_SgFortranIncludeLine:
1571 {
1572 name = directive->class_name();
1573 break;
1574 }
1575
1576 default:
1577 // name = "default name (default case reached: not handled)";
1578 printf ("Warning: default case reached in SageInterface::get_name ( const SgC_PreprocessorDirectiveStatement* directive ), directive = %p = %s \n",
1579 directive,directive->class_name().c_str());
1580 ROSE_ABORT();
1581#if 0 // [Robb Matzke 2021-03-24]: unreachable
1582 name = "directive_default_name_case_reached_not_handled";
1583 break;
1584#endif
1585 }
1586#endif
1587
1588 return name;
1589 }
1590
1591string
1593 {
1594 string name = "undefined_name";
1595
1596 ROSE_ASSERT(declaration != NULL);
1597
1598 // DQ (11/23/2008): Handle the case of a Cpp directive...
1599 const SgC_PreprocessorDirectiveStatement* directive = isSgC_PreprocessorDirectiveStatement(declaration);
1600 if (directive != NULL)
1601 {
1602 return SageInterface::get_name (directive);
1603 }
1604
1605 switch (declaration->variantT())
1606 {
1607 case V_SgTemplateMemberFunctionDeclaration:
1608 name = isSgTemplateMemberFunctionDeclaration(declaration)->get_name().str();
1609 break;
1610
1611 case V_SgTemplateFunctionDeclaration:
1612 name = isSgTemplateFunctionDeclaration(declaration)->get_name().str();
1613 break;
1614
1615 case V_SgTemplateClassDeclaration:
1616 name = isSgTemplateClassDeclaration(declaration)->get_name().str();
1617 break;
1618
1619 case V_SgTemplateDeclaration:
1620 name = isSgTemplateDeclaration(declaration)->get_name().str();
1621 break;
1622
1623 case V_SgTemplateInstantiationDecl:
1624 name = isSgTemplateInstantiationDecl(declaration)->get_templateName().str();
1625 break;
1626
1627 case V_SgClassDeclaration:
1628 case V_SgDerivedTypeStatement:
1629 case V_SgJovialTableStatement:
1630 name = isSgClassDeclaration(declaration)->get_name().str();
1631 break;
1632
1633 // Rasmussen (8/2/2019): Added SgJovialDefineDeclaration and SgJovialDirectiveStatement
1634 // I'm not sure class_name() is correct. Probably get_name() should be fixed.
1635 case V_SgJovialDefineDeclaration:
1636 case V_SgJovialDirectiveStatement:
1637 case V_SgJovialCompoolStatement:
1638 name = "__" + declaration->class_name() + "_";
1639 name += StringUtility::numberToString(declaration);
1640 break;
1641
1642 case V_SgJovialLabelDeclaration:
1643 name = isSgJovialLabelDeclaration(declaration)->get_label();
1644 break;
1645
1646 case V_SgEnumDeclaration:
1647 name = isSgEnumDeclaration(declaration)->get_name().str();
1648 break;
1649
1650 // DQ (11/5/2014): Adding support for template typedef declarations (C++11 feature).
1651 case V_SgTemplateInstantiationTypedefDeclaration:
1652 // DQ (11/3/2014): Adding support for template typedef declarations (C++11 feature).
1653 case V_SgTemplateTypedefDeclaration:
1654 case V_SgTypedefDeclaration:
1655 name = isSgTypedefDeclaration(declaration)->get_name().str();
1656 break;
1657
1658 case V_SgFunctionDeclaration:
1659 case V_SgProgramHeaderStatement:
1660 case V_SgProcedureHeaderStatement:
1661 case V_SgMemberFunctionDeclaration:
1662 case V_SgTemplateInstantiationFunctionDecl:
1663 case V_SgTemplateInstantiationMemberFunctionDecl:
1664 case V_SgAdaFunctionRenamingDecl:
1665 case V_SgAdaEntryDecl:
1666 name = isSgFunctionDeclaration(declaration)->get_name().str();
1667 break;
1668
1669 case V_SgNamespaceDeclarationStatement:
1670 name = isSgNamespaceDeclarationStatement(declaration)->get_name().str();
1671 break;
1672
1673 // DQ (2/12/2006): Added support to get name of SgFunctionParameterList
1674 case V_SgFunctionParameterList:
1675 {
1676 // Parents should be set prior to calling these functions (if not we might have to implement that case)
1677 ROSE_ASSERT(declaration->get_parent() != NULL);
1678
1679 if (SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration->get_parent()))
1680 {
1681 name = get_name(functionDeclaration);
1682 }
1683 else if (SgScopeStatement* scopeStmt = isSgScopeStatement(declaration->get_parent()))
1684 {
1685 name = get_name(scopeStmt);
1686 }
1687 else ROSE_ABORT();
1688
1689 name += "_parameter_list_";
1690 break;
1691 }
1692
1693 // DQ (2/10/2012): Added support for template variable declarations (using base class support).
1694 case V_SgTemplateVariableDeclaration:
1695
1696 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1697 case V_SgVariableDeclaration:
1698 {
1699 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1700 // because we use this mechanism to generate names for unnamed structs and enums).
1701 name = "_variable_declaration_";
1702 const SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(declaration);
1703 ROSE_ASSERT(variableDeclaration != NULL);
1704 SgInitializedNamePtrList::const_iterator i = variableDeclaration->get_variables().begin();
1705
1706 // Make sure that we have at least one variable in the list
1707 ROSE_ASSERT(i != variableDeclaration->get_variables().end());
1708 do {
1709 // name += string(" ") + string((*i)->get_name().str());
1710 name += string((*i)->get_name().str());
1711 i++;
1712 }
1713 while (i != variableDeclaration->get_variables().end());
1714 break;
1715 }
1716
1717
1718 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1719 case V_SgVariableDefinition:
1720 {
1721 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1722 // because we use this mechanism to generate names for unnamed structs and enums).
1723 name = "_variable_definition_";
1724 const SgVariableDefinition* variableDefinition = isSgVariableDefinition(declaration);
1725 ROSE_ASSERT(variableDefinition != NULL);
1726
1727 // define this in terms of the associated SgInitializedName
1728 ROSE_ASSERT(variableDefinition->get_vardefn() != NULL);
1729 name += get_name(variableDefinition->get_vardefn());
1730 break;
1731 }
1732
1733 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
1734 case V_SgPragmaDeclaration:
1735 {
1736 name = "_pragma_declaration_";
1737 const SgPragmaDeclaration* pragmaDeclaration = isSgPragmaDeclaration(declaration);
1738 ROSE_ASSERT(pragmaDeclaration != NULL);
1739 ROSE_ASSERT(pragmaDeclaration->get_pragma() != NULL);
1740 name += get_name(pragmaDeclaration->get_pragma());
1741 break;
1742 }
1743
1744 // DQ (4/15/2007): Implemented case for using directive statement (forgot this case)
1745 case V_SgUsingDirectiveStatement:
1746 {
1747 name = "_using_directive_statement_";
1748 const SgUsingDirectiveStatement* usingDeclaration = isSgUsingDirectiveStatement(declaration);
1749 ROSE_ASSERT(usingDeclaration != NULL);
1750 ROSE_ASSERT(usingDeclaration->get_namespaceDeclaration() != NULL);
1751 name += get_name(usingDeclaration->get_namespaceDeclaration());
1752 break;
1753 }
1754
1755 // DQ (6/20/2007): Added new case!
1756 case V_SgNamespaceAliasDeclarationStatement:
1757 {
1758 name = "_namespace_alias_directive_statement_";
1759 const SgNamespaceAliasDeclarationStatement* namespaceAliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
1760 ROSE_ASSERT(namespaceAliasDeclaration != NULL);
1761 ROSE_ASSERT(namespaceAliasDeclaration->get_name().is_null() == false);
1762 name += namespaceAliasDeclaration->get_name();
1763 break;
1764 }
1765
1766 // DQ (6/20/2007): Added new case!
1767 case V_SgUsingDeclarationStatement:
1768 {
1769 name = "_using_declaration_statement_";
1770 const SgUsingDeclarationStatement* usingDeclaration = isSgUsingDeclarationStatement(declaration);
1771 ROSE_ASSERT(usingDeclaration != NULL);
1772 if (usingDeclaration->get_declaration() != NULL)
1773 {
1774 name += get_name(usingDeclaration->get_declaration());
1775 }
1776 else
1777 {
1778 ROSE_ASSERT(usingDeclaration->get_initializedName() != NULL);
1779 name += get_name(usingDeclaration->get_initializedName());
1780 }
1781 break;
1782 }
1783
1784 // DQ (6/20/2007): Added new case!
1785 case V_SgTemplateInstantiationDirectiveStatement:
1786 {
1787 name = "_template_instantiation_directive_statement_";
1788 ROSE_ASSERT(declaration != NULL);
1789 const SgTemplateInstantiationDirectiveStatement* templateInstantiationDirective = isSgTemplateInstantiationDirectiveStatement(declaration);
1790 ROSE_ASSERT(templateInstantiationDirective != NULL);
1791 ROSE_ASSERT(templateInstantiationDirective->get_declaration() != NULL);
1792#if 0
1793 printf ("declaration->get_declaration() = %p = %s \n",templateInstantiationDirective->get_declaration(),templateInstantiationDirective->get_declaration()->class_name().c_str());
1794#endif
1795 name += get_name(templateInstantiationDirective->get_declaration());
1796 break;
1797 }
1798
1799 case V_SgCtorInitializerList:
1800 {
1801 name = "_ctor_list_";
1802 const SgCtorInitializerList* ctorDeclaration = isSgCtorInitializerList(declaration);
1803 ROSE_ASSERT(ctorDeclaration != NULL);
1804 ROSE_ASSERT(ctorDeclaration->get_parent() != NULL);
1805 name += get_name(ctorDeclaration->get_parent());
1806 break;
1807 }
1808
1809 // DQ (8/9/2007): Added case for SgAsmStmt
1810 case V_SgAsmStmt:
1811 {
1812 name = "_asm_stmt_";
1813 const SgAsmStmt* asmStatement = isSgAsmStmt(declaration);
1814 ROSE_ASSERT(asmStatement != NULL);
1815 ROSE_ASSERT(asmStatement->get_parent() != NULL);
1816 name += StringUtility::numberToString(const_cast<SgAsmStmt*>(asmStatement));
1817 break;
1818 }
1819
1820 // DQ (8/22/2007): Added case for SgImplicitStatement
1821 case V_SgImplicitStatement:
1822 {
1823 name = "_fortran_implicit_";
1824 const SgImplicitStatement* implicitStatement = isSgImplicitStatement(declaration);
1825 ROSE_ASSERT(implicitStatement != NULL);
1826 ROSE_ASSERT(implicitStatement->get_parent() != NULL);
1827 name += StringUtility::numberToString(const_cast<SgImplicitStatement*>(implicitStatement));
1828 break;
1829 }
1830
1831 // DQ (8/22/2007): Added case for SgNamelistStatement
1832 case V_SgNamelistStatement:
1833 {
1834 name = "_fortran_namelist_";
1835 const SgNamelistStatement* namelistStatement = isSgNamelistStatement(declaration);
1836 ROSE_ASSERT(namelistStatement != NULL);
1837 ROSE_ASSERT(namelistStatement->get_parent() != NULL);
1838 name += StringUtility::numberToString(const_cast<SgNamelistStatement*>(namelistStatement));
1839 break;
1840 }
1841
1842 // DQ (11/21/2007): Added case for SgEquivalenceStatement
1843 case V_SgEquivalenceStatement:
1844 {
1845 name = "_fortran_equivalence_";
1846 const SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(declaration);
1847 ROSE_ASSERT(equivalenceStatement != NULL);
1848 ROSE_ASSERT(equivalenceStatement->get_parent() != NULL);
1849 name += StringUtility::numberToString(const_cast<SgEquivalenceStatement*>(equivalenceStatement));
1850 break;
1851 }
1852
1853
1854 // DQ (11/21/2007): Added case for SgCommonBlock
1855 case V_SgCommonBlock:
1856 {
1857 name = "_fortran_common_block_";
1858 const SgCommonBlock* commonBlockStatement = isSgCommonBlock(declaration);
1859 ROSE_ASSERT(commonBlockStatement != NULL);
1860 ROSE_ASSERT(commonBlockStatement->get_parent() != NULL);
1861 name += StringUtility::numberToString(const_cast<SgCommonBlock*>(commonBlockStatement));
1862 break;
1863 }
1864
1865 // DQ (11/21/2007): Added case for SgImportStatement
1866 case V_SgImportStatement:
1867 {
1868 name = "_fortran_import_stmt_";
1869 const SgImportStatement* importStatement = isSgImportStatement(declaration);
1870 ROSE_ASSERT(importStatement != NULL);
1871 ROSE_ASSERT(importStatement->get_parent() != NULL);
1872 name += StringUtility::numberToString(const_cast<SgImportStatement*>(importStatement));
1873 break;
1874 }
1875
1876 // DQ (11/21/2007): Added case for SgFormatStatement
1877 case V_SgFormatStatement:
1878 {
1879 name = "_fortran_format_stmt_";
1880 const SgFormatStatement* formatStatement = isSgFormatStatement(declaration);
1881 ROSE_ASSERT(formatStatement != NULL);
1882 ROSE_ASSERT(formatStatement->get_parent() != NULL);
1883 name += StringUtility::numberToString(const_cast<SgFormatStatement*>(formatStatement));
1884 break;
1885 }
1886
1887 // DQ (12/27/2007): Added case for SgModuleStatement
1888 case V_SgModuleStatement:
1889 {
1890 name = "_fortran_module_stmt_";
1891 const SgModuleStatement* moduleStatement = isSgModuleStatement(declaration);
1892 ROSE_ASSERT(moduleStatement != NULL);
1893 ROSE_ASSERT(moduleStatement->get_parent() != NULL);
1894 name += StringUtility::numberToString(const_cast<SgModuleStatement*>(moduleStatement));
1895 break;
1896 }
1897
1898 // DQ (12/27/2007): Added case for SgUseStatement
1899 case V_SgUseStatement:
1900 {
1901 name = "_fortran_use_stmt_";
1902 const SgUseStatement* useStatement = isSgUseStatement(declaration);
1903 ROSE_ASSERT(useStatement != NULL);
1904 ROSE_ASSERT(useStatement->get_parent() != NULL);
1905 name += StringUtility::numberToString(const_cast<SgUseStatement*>(useStatement));
1906 break;
1907 }
1908
1909 // DQ (12/28/2007): Added case for SgContainsStatement
1910 case V_SgContainsStatement:
1911 {
1912 name = "_fortran_contains_stmt_";
1913 const SgContainsStatement* containsStatement = isSgContainsStatement(declaration);
1914 ROSE_ASSERT(containsStatement != NULL);
1915 ROSE_ASSERT(containsStatement->get_parent() != NULL);
1916 name += StringUtility::numberToString(const_cast<SgContainsStatement*>(containsStatement));
1917 break;
1918 }
1919
1920 // DQ (1/20/2008): Added case for SgEntryStatement
1921 case V_SgEntryStatement:
1922 {
1923 name = "_fortran_entry_stmt_";
1924 const SgEntryStatement* entryStatement = isSgEntryStatement(declaration);
1925 ROSE_ASSERT(entryStatement != NULL);
1926 ROSE_ASSERT(entryStatement->get_parent() != NULL);
1927 name += StringUtility::numberToString(const_cast<SgEntryStatement*>(entryStatement));
1928 break;
1929 }
1930
1931 // DQ (1/23/2008): Added case for SgAttributeSpecificationStatement
1932 case V_SgAttributeSpecificationStatement:
1933 {
1934 name = "_fortran_attribute_specification_stmt_";
1935 const SgAttributeSpecificationStatement* statement = isSgAttributeSpecificationStatement(declaration);
1936 ROSE_ASSERT(statement != NULL);
1937 ROSE_ASSERT(statement->get_parent() != NULL);
1939 break;
1940 }
1941
1942 case V_SgInterfaceStatement:
1943 {
1944 name = "_fortran_interface_stmt_";
1945 const SgInterfaceStatement* statement = isSgInterfaceStatement(declaration);
1946 ROSE_ASSERT(statement != NULL);
1947 ROSE_ASSERT(statement->get_parent() != NULL);
1948 name += StringUtility::numberToString(const_cast<SgInterfaceStatement*>(statement));
1949 break;
1950 }
1951
1952 case V_SgFortranIncludeLine:
1953 {
1954 name = "_fortran_include_line_stmt_";
1955 const SgFortranIncludeLine* statement = isSgFortranIncludeLine(declaration);
1956 ROSE_ASSERT(statement != NULL);
1957 ROSE_ASSERT(statement->get_parent() != NULL);
1958 name += StringUtility::numberToString(const_cast<SgFortranIncludeLine*>(statement));
1959 break;
1960 }
1961
1962 // DQ (4/16/2011): Added Java import statment support.
1963 case V_SgJavaImportStatement:
1964 {
1965 name = "_java_import_stmt_";
1966 const SgJavaImportStatement* statement = isSgJavaImportStatement(declaration);
1967 ROSE_ASSERT(statement != NULL);
1968 ROSE_ASSERT(statement->get_parent() != NULL);
1969 name += StringUtility::numberToString(const_cast<SgJavaImportStatement*>(statement));
1970 break;
1971 }
1972
1973 case V_SgJavaPackageDeclaration:
1974 {
1975 name = "_java_package_declaration_";
1976 const SgJavaPackageDeclaration* package_declaration = isSgJavaPackageDeclaration(declaration);
1977 ROSE_ASSERT(package_declaration != NULL);
1978 ROSE_ASSERT(package_declaration->get_parent() != NULL);
1979 name += StringUtility::numberToString(const_cast<SgJavaPackageDeclaration*>(package_declaration));
1980 break;
1981 }
1982
1983 case V_SgJavaPackageStatement:
1984 {
1985 name = "_java_package_stmt_";
1986 const SgJavaPackageStatement* statement = isSgJavaPackageStatement(declaration);
1987 ROSE_ASSERT(statement != NULL);
1988 ROSE_ASSERT(statement->get_parent() != NULL);
1989 name += StringUtility::numberToString(const_cast<SgJavaPackageStatement*>(statement));
1990 break;
1991 }
1992
1993 // DQ (1/21/2018): Added case for C++11 SgStaticAssertionDeclaration
1994 case V_SgStaticAssertionDeclaration:
1995 {
1996 name = "_static_assertion_declaration_stmt_";
1997 const SgStaticAssertionDeclaration* statement = isSgStaticAssertionDeclaration(declaration);
1998 ROSE_ASSERT(statement != NULL);
1999 ROSE_ASSERT(statement->get_parent() != NULL);
2000 name += StringUtility::numberToString(const_cast<SgStaticAssertionDeclaration*>(statement));
2001 break;
2002 }
2003
2004 case V_SgNonrealDecl:
2005 {
2006 const SgNonrealDecl * nrdecl = isSgNonrealDecl(declaration);
2007 ROSE_ASSERT(nrdecl != NULL);
2008 name = nrdecl->get_name();
2009 break;
2010 }
2011
2012 // DQ (3/26/2019): Adding support for new declaration.
2013 case V_SgEmptyDeclaration:
2014 {
2015 const SgEmptyDeclaration * emptyDeclaration = isSgEmptyDeclaration(declaration);
2016 ROSE_ASSERT(emptyDeclaration != NULL);
2017 name = string("emptyDeclaration") + StringUtility::numberToString(const_cast<SgDeclarationStatement*>(declaration));
2018 break;
2019 }
2020
2021 case V_SgAdaPackageSpecDecl:
2022 {
2023 name = genericGetName(isSgAdaPackageSpecDecl(declaration));
2024 break;
2025 }
2026
2027 case V_SgAdaPackageBodyDecl:
2028 {
2029 name = genericGetName(isSgAdaPackageBodyDecl(declaration));
2030 break;
2031 }
2032
2033 case V_SgAdaFormalTypeDecl:
2034 {
2035 name = genericGetName(isSgAdaFormalTypeDecl(declaration));
2036 break;
2037 }
2038
2039 case V_SgAdaGenericDecl:
2040 {
2041 // need to look inside the declaration wrapped by the generic.
2042 const SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(declaration);
2043 name = get_name(gendcl->get_declaration());
2044 break;
2045#if OBSOLETE_CODE
2046 if (isSgFunctionDeclaration(dcl->get_declaration())) {
2047 name = "_ada_generic_decl_" + genericGetName(isSgFunctionDeclaration(dcl->get_declaration()));
2048 break;
2049 }
2050 if (isSgAdaPackageSpecDecl(dcl->get_declaration())) {
2051 name = "_ada_generic_decl_" + genericGetName(isSgAdaPackageSpecDecl(dcl->get_declaration()));
2052 break;
2053 }
2054
2055 // something malformed in the tree if we get here
2056 ROSE_ABORT();
2057 break;
2058#endif /* OBSOLETE_CODE */
2059 }
2060
2061 case V_SgAdaDiscriminatedTypeDecl:
2062 {
2063 const SgAdaDiscriminatedTypeDecl* dcl = isSgAdaDiscriminatedTypeDecl(declaration);
2064 ROSE_ASSERT(dcl);
2065
2066 if (const SgDeclarationStatement* discrDcl = dcl->get_discriminatedDecl())
2067 {
2068 name = get_name(discrDcl);
2069 }
2070 else
2071 {
2072 name = "_incomplete_Ada_discriminated_type_";
2073 }
2074
2075 break;
2076 }
2077
2078 case V_SgAdaVariantDecl:
2079 {
2080 name = "_ada_variant_decl_";
2081 break;
2082 }
2083
2084 case V_SgAdaAttributeClause:
2085 {
2086 name = "_ada_attribute_clause_";
2087 break;
2088 }
2089
2090 case V_SgAdaRepresentationClause:
2091 {
2092 name = "_ada_representation_clause_";
2093 break;
2094 }
2095
2096 case V_SgAdaEnumRepresentationClause:
2097 {
2098 name = "_ada_enum_representation_clause_";
2099 break;
2100 }
2101
2102 case V_SgAdaComponentClause:
2103 {
2104 name = "_ada_component_clause_";
2105 break;
2106 }
2107
2108 case V_SgAdaTaskTypeDecl:
2109 {
2110 name = genericGetName(isSgAdaTaskTypeDecl(declaration));
2111 break;
2112 }
2113
2114 case V_SgAdaProtectedTypeDecl:
2115 {
2116 name = genericGetName(isSgAdaProtectedTypeDecl(declaration));
2117 break;
2118 }
2119
2120 case V_SgAdaTaskBodyDecl:
2121 {
2122 name = genericGetName(isSgAdaTaskBodyDecl(declaration));
2123 break;
2124 }
2125
2126 case V_SgAdaProtectedBodyDecl:
2127 {
2128 name = genericGetName(isSgAdaProtectedBodyDecl(declaration));
2129 break;
2130 }
2131
2132 case V_SgAdaRenamingDecl:
2133 {
2134 name = genericGetName(isSgAdaRenamingDecl(declaration));
2135 break;
2136 }
2137
2138 case V_SgAdaTaskSpecDecl:
2139 {
2140 name = genericGetName(isSgAdaTaskSpecDecl(declaration));
2141 break;
2142 }
2143
2144 case V_SgAdaProtectedSpecDecl:
2145 {
2146 name = genericGetName(isSgAdaProtectedSpecDecl(declaration));
2147 break;
2148 }
2149
2150 case V_SgAdaGenericInstanceDecl:
2151 {
2152 name = genericGetName(isSgAdaGenericInstanceDecl(declaration));
2153 break;
2154 }
2155
2156 case V_SgAdaFormalPackageDecl:
2157 {
2158 name = genericGetName(isSgAdaFormalPackageDecl(declaration));
2159 break;
2160 }
2161
2162 case V_SgAdaParameterList:
2163 {
2164 const SgAdaParameterList* plst = isSgAdaParameterList(declaration);
2165 ROSE_ASSERT(plst);
2166
2167 name = std::accumulate( plst->get_parameters().begin(), plst->get_parameters().end(),
2168 std::string{"_ada_parameter_list_"},
2169 [](std::string n, SgDeclarationStatement* rhs) -> std::string
2170 {
2171 n += SageInterface::get_name(rhs);
2172 return n;
2173 }
2174 );
2175 break;
2176 }
2177
2178 // Note that the case for SgVariableDeclaration is not implemented
2179 default:
2180 printf ("Warning: default case reached in SageInterface::get_name ( const SgDeclarationStatement* declaration ), declaration = %p = %s \n",
2181 declaration,declaration->class_name().c_str());
2182 ROSE_ABORT();
2183 }
2184
2185 return name;
2186 }
2187
2188string
2190 {
2191 string name = "undefined_name";
2192
2193 ROSE_ASSERT(scope != NULL);
2194
2195 switch (scope->variantT())
2196 {
2197 // DQ (6/11/2011): Added support for new template IR nodes.
2198 case V_SgTemplateClassDefinition:
2199 name = get_name(isSgTemplateClassDefinition(scope)->get_declaration());
2200 break;
2201
2202 case V_SgClassDefinition:
2203 case V_SgTemplateInstantiationDefn:
2204 name = get_name(isSgClassDefinition(scope)->get_declaration());
2205 break;
2206
2207 // DQ (9/8/2012): Added missing case for SgTemplateFunctionDefinition.
2208 case V_SgTemplateFunctionDefinition:
2209 case V_SgFunctionDefinition:
2210 name = get_name(isSgFunctionDefinition(scope)->get_declaration());
2211 break;
2212
2213 case V_SgNamespaceDefinitionStatement:
2214 name = get_name(isSgNamespaceDefinitionStatement(scope)->get_namespaceDeclaration());
2215 break;
2216 case V_SgJavaLabelStatement:
2217 name = (isSgJavaLabelStatement(scope)->get_label()).getString();
2218 break;
2219
2220 // DQ (7/18/2017): Added support for the new declaration scope.
2221 case V_SgDeclarationScope:
2222
2223 // DQ (11/30/2007): Added more fortran support.
2224 case V_SgAssociateStatement:
2225 case V_SgJavaForEachStatement:
2226
2227 case V_SgFunctionParameterScope:
2228 case V_SgAdaPackageSpec:
2229 case V_SgAdaPackageBody:
2230 case V_SgAdaTaskSpec:
2231 case V_SgAdaTaskBody:
2232 case V_SgAdaProtectedSpec:
2233 case V_SgAdaProtectedBody:
2234 case V_SgAdaGenericDefn:
2235 case V_SgAdaAcceptStmt:
2236 case V_SgJovialForThenStatement: //Rasmussen: Jovial for statement
2237 case V_SgMatlabForStatement: //SK: Matlab for statement
2238 case V_SgBasicBlock:
2239 case V_SgCatchOptionStmt:
2240 case V_SgDoWhileStmt:
2241 case V_SgForStatement:
2242 case V_SgGlobal:
2243 case V_SgIfStmt:
2244 case V_SgSwitchStatement:
2245 case V_SgWhileStmt:
2246 case V_SgFortranDo:
2247 case V_SgForAllStatement:
2248 case V_SgRangeBasedForStatement:
2249 name = StringUtility::numberToString(const_cast<SgScopeStatement*>(scope));
2250 break;
2251
2252 default:
2253 printf ("Error: undefined case (SgScopeStatement) in SageInterface::get_name(): node = %s \n",scope->class_name().c_str());
2254 ROSE_ABORT();
2255 }
2256
2257 return name;
2258 }
2259
2260string
2262 {
2263 string name = "undefined_name";
2264
2265 ROSE_ASSERT(stmt != NULL);
2266
2267 const SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
2268 if (declaration != NULL)
2269 {
2270 name = get_name(declaration);
2271 }
2272 else
2273 {
2274 const SgScopeStatement* scope = isSgScopeStatement(stmt);
2275 if (scope != NULL)
2276 {
2277 name = get_name(scope);
2278 }
2279 else
2280 {
2281 // DQ (10/25/2007): This is better since it names the SgLabelStatement case
2282 switch (stmt->variantT())
2283 {
2284#if 0
2285 case V_SgBreakStmt:
2286 case V_SgCaseOptionStmt:
2287 case V_SgCatchStatementSeq:
2288 case V_SgClinkageStartStatement:
2289 case V_SgContinueStmt:
2290 case V_SgDefaultOptionStmt:
2291 case V_SgExprStmt:
2292 case V_SgForInitStmt:
2293 case V_SgFunctionTypeTable:
2294 case V_SgGotoStatement:
2295 case V_SgReturnStmt:
2296 case V_SgSpawnStmt:
2297 case V_SgTryStmt:
2298 name = stmt->class_name();
2299 break;
2300#endif
2301 case V_SgLabelStatement:
2302 {
2303 const SgLabelStatement* labelStatement = isSgLabelStatement(stmt);
2304 name = labelStatement->get_label().str();
2305 break;
2306 }
2307
2308 default:
2309 {
2310 // printf ("Default reached in switch \n");
2311 // name = "default name";
2312 name = stmt->class_name();
2313 break;
2314 }
2315 }
2316 }
2317 }
2318
2319 return name;
2320 }
2321
2322string
2324 {
2325 // This function is useful for debugging
2326 // This is the most general case of a function to return a name for an IR node.
2327 ROSE_ASSERT(node != NULL);
2328
2329 string name = "undefined_name";
2330
2331 ROSE_ASSERT(node != NULL);
2332
2333 switch (node->variantT())
2334 {
2335 case V_SgInitializedName:
2336 {
2337 const SgInitializedName* initializedName = isSgInitializedName(node);
2338 if (initializedName != NULL)
2339 {
2340 name = initializedName->get_name().str();
2341 }
2342 break;
2343 }
2344#if 1
2345 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
2346 case V_SgPragma:
2347 {
2348 name = "_pragma_string_";
2349 const SgPragma* pragma = isSgPragma(node);
2350 ROSE_ASSERT(pragma != NULL);
2351 name += pragma->get_pragma();
2352 break;
2353 }
2354#endif
2355
2356 // DQ (5/31/2007): Implemented case for SgProject
2357 case V_SgProject:
2358 {
2359 name = "_project_";
2360 break;
2361 }
2362
2363 // DQ (5/31/2007): Implemented case for SgFile
2364 // case V_SgFile:
2365 case V_SgSourceFile:
2366#ifdef ROSE_ENABLE_BINARY_ANALYSIS
2367 case V_SgBinaryComposite:
2368#endif
2369 {
2370 name = "_file_";
2371
2372 // DQ (3/1/2009): Added support to include the file name.
2373 const SgFile* file = isSgFile(node);
2374 ROSE_ASSERT(file != NULL);
2375
2376 name += file->getFileName();
2377 break;
2378 }
2379
2380 // DQ (5/31/2007): Implemented case for SgSymbolTable
2381 case V_SgSymbolTable:
2382 {
2383 name = "_symbol_table_";
2384 break;
2385 }
2386
2387 // DQ (5/31/2007): Implemented case for SgStorageModifier
2388 case V_SgStorageModifier:
2389 {
2390 name = "_storage_modifier_";
2391 break;
2392 }
2393
2394
2395 // DQ (5/31/2007): Implemented case for Sg_File_Info
2396 case V_Sg_File_Info:
2397 {
2398 name = "_file_info_";
2399 break;
2400 }
2401
2402 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2403 case V_SgTemplateArgument:
2404 {
2405 name = "_template_argument_";
2406 const SgTemplateArgument* templateArgument = isSgTemplateArgument(node);
2407 ROSE_ASSERT(templateArgument != NULL);
2408 switch(templateArgument->get_argumentType())
2409 {
2411 {
2412 SgType* t = templateArgument->get_type();
2413 ROSE_ASSERT(t != NULL);
2414 name += get_name(t);
2415 break;
2416 }
2417
2419 {
2420 SgExpression* t = templateArgument->get_expression();
2421
2422 // DQ (8/11/2013): Adding support for including an initializedName instead of an expression (for template parameters used as expressions).
2423 // ROSE_ASSERT(t != NULL);
2424 // name += get_name(t);
2425 if (t != NULL)
2426 {
2427 ROSE_ASSERT(templateArgument->get_initializedName() == NULL);
2428 name += get_name(t);
2429 }
2430 else
2431 {
2432 ROSE_ASSERT(t == NULL);
2433 SgInitializedName* initializedName = templateArgument->get_initializedName();
2434 ROSE_ASSERT(initializedName != NULL);
2435
2436 name += get_name(initializedName);
2437 }
2438 break;
2439 }
2440
2442 {
2443 // SgTemplateDeclaration* t = templateArgument->get_templateDeclaration();
2444 SgDeclarationStatement* t = templateArgument->get_templateDeclaration();
2445 ROSE_ASSERT(t != NULL);
2446 name += get_name(t);
2447 break;
2448 }
2449
2450 default:
2451 {
2452 printf ("Error: default case reached in switch on templateArgument->get_argumentType() \n");
2453 ROSE_ABORT();
2454 }
2455 }
2456 break;
2457 }
2458
2459
2460 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2461 case V_SgTypeModifier:
2462 {
2463 const SgTypeModifier* typeModifier = isSgTypeModifier(node);
2464 ROSE_ASSERT(typeModifier != NULL);
2465 name = "_type_modifier_" + typeModifier->displayString();
2466 break;
2467 }
2468
2469 // DQ (11/19/2007): Implemented case for SgNameGroup
2470 case V_SgNameGroup:
2471 {
2472 const SgNameGroup* nameGroup = isSgNameGroup(node);
2473 ROSE_ASSERT(nameGroup != NULL);
2474 name = "_name_group_" + nameGroup->get_group_name();
2475 break;
2476 }
2477
2478 // DQ (11/20/2007): Implemented case for Fortran data statement support
2479 case V_SgDataStatementGroup:
2480 {
2481 const SgDataStatementGroup* dataGroup = isSgDataStatementGroup(node);
2482 ROSE_ASSERT(dataGroup != NULL);
2483 name = "_data_statement_group_";
2484 break;
2485 }
2486
2487 // DQ (11/20/2007): Implemented case for Fortran data statement support
2488 case V_SgDataStatementObject:
2489 {
2490 const SgDataStatementObject* dataObject = isSgDataStatementObject(node);
2491 ROSE_ASSERT(dataObject != NULL);
2492 name = "_data_statement_object_";
2493 break;
2494 }
2495
2496 // DQ (11/20/2007): Implemented case for Fortran data statement support
2497 case V_SgDataStatementValue:
2498 {
2499 const SgDataStatementValue* dataValue = isSgDataStatementValue(node);
2500 ROSE_ASSERT(dataValue != NULL);
2501 name = "_data_statement_value_";
2502 break;
2503 }
2504
2505 // DQ (11/19/2007): Implemented case for SgCommonBlock
2506 case V_SgCommonBlockObject:
2507 {
2508 const SgCommonBlockObject* commonBlockObject = isSgCommonBlockObject(node);
2509 ROSE_ASSERT(commonBlockObject != NULL);
2510 name = "_common_block_object_" + commonBlockObject->get_block_name();
2511 break;
2512 }
2513
2514 // DQ (12/23/2007): Added support for repeat_specification
2515 case V_SgFormatItem:
2516 {
2517 const SgFormatItem* formatItem = isSgFormatItem(node);
2518 ROSE_ASSERT(formatItem != NULL);
2519 name = "_format_item_";
2520 break;
2521 }
2522
2523 // DQ (12/23/2007): Added support for repeat_specification
2524 case V_SgFormatItemList:
2525 {
2526 const SgFormatItemList* formatItemList = isSgFormatItemList(node);
2527 ROSE_ASSERT(formatItemList != NULL);
2528 name = "_format_item_list_";
2529 break;
2530 }
2531
2532 // DQ (12/23/2007): Added support for repeat_specification
2533 case V_SgRenamePair:
2534 {
2535 const SgRenamePair* renamePair = isSgRenamePair(node);
2536 ROSE_ASSERT(renamePair != NULL);
2537 name = renamePair->get_local_name() + "__" + renamePair->get_use_name() + "_rename_pair_";
2538 break;
2539 }
2540
2541 // DQ (12/2/2010): Implemented case for SgName
2542 case V_SgName:
2543 {
2544 const SgName* name_node = isSgName(node);
2545 ROSE_ASSERT(name_node != NULL);
2546 name = "_name_" + name_node->getString();
2547 break;
2548 }
2549
2550 // DQ (8/8/2013): Implemented case for SgTemplateParameter
2551 case V_SgTemplateParameter:
2552 {
2553 const SgTemplateParameter* template_parameter_node = isSgTemplateParameter(node);
2554 ROSE_ASSERT(template_parameter_node != NULL);
2555 name = "_template_parameter_";
2556
2557 switch(template_parameter_node->get_parameterType())
2558 {
2560 {
2561 name += "type_parameter_";
2562 break;
2563 }
2564
2566 {
2567 name += "nontype_parameter_";
2568#if 1
2569 name += template_parameter_node->unparseToString();
2570#else
2571 if (template_parameter_node->get_expression() != NULL)
2572 {
2573 name += template_parameter_node->get_expression()->unparseToString();
2574 }
2575 else
2576 {
2577 ROSE_ASSERT(template_parameter_node->get_initializedName() != NULL);
2578
2579 // DQ (8/8/2013): This does not handle the case of "template <void (foo::*M)()> void test() {}"
2580 // since what is unparsed is: "_template_parameter_nontype_parameter_M"
2581 // instead of a string to represent what is in "void (foo::*M)()"
2582 // and differentiate it from: "int foo::*M" in: "template <void (foo::*M)()> void test() {}"
2583 name += template_parameter_node->get_initializedName()->unparseToString();
2584 }
2585#endif
2586 break;
2587 }
2588
2590 {
2591 name += "template_parameter_";
2592 break;
2593 }
2594
2595 default:
2596 {
2597 printf ("Error: default reached \n");
2598 ROSE_ABORT();
2599 }
2600 }
2601 break;
2602 }
2603
2604 // DQ (1/21/2019): Implemented case for SgBaseClass
2605 case V_SgBaseClass:
2606 {
2607 const SgBaseClass* base_class_node = isSgBaseClass(node);
2608 ROSE_ASSERT(base_class_node != NULL);
2609 ROSE_ASSERT(base_class_node->get_base_class() != NULL);
2610
2611 // Add the access modifier to the output.
2612 string access = "";
2613 const SgBaseClassModifier* baseClassModifier = base_class_node->get_baseClassModifier();
2614 ROSE_ASSERT(baseClassModifier != NULL);
2615 access = baseClassModifier->displayString();
2616
2617 name = "_base_class_" + access + "_" + get_name(base_class_node->get_base_class());
2618 break;
2619 }
2620
2621 default:
2622 {
2623 printf ("Default reached in switch for SgSupport IR node = %s \n",node->class_name().c_str());
2624 name = "default name";
2625 // ROSE_ASSERT(false);
2626 break;
2627 }
2628 }
2629
2630 return name;
2631 }
2632
2633
2634string
2636 {
2637 // This function is useful for debugging
2638 // This is the most general case of a function to return a name for an IR node.
2639 ROSE_ASSERT(symbol != NULL);
2640
2641 string aliasSymbolPrefix = "";
2642 if (isSgAliasSymbol(symbol) != NULL)
2643 {
2644 aliasSymbolPrefix = "_ALIAS";
2645 }
2646
2647 // printf ("In SageInterface::get_name(): symbol->get_symbol_basis() = %p = %s \n",symbol->get_symbol_basis(),symbol->get_symbol_basis()->class_name().c_str());
2648 // printf ("In SageInterface::get_name(): symbol->get_declaration() = %p = %s \n",symbol->get_declaration(),symbol->get_declaration()->class_name().c_str());
2649
2650 // This is a call to the "get_name()" virtual function
2651 return symbol->get_name() + aliasSymbolPrefix + "_symbol_";
2652 }
2653
2654string
2656 {
2657 // This function is useful for debugging
2658 // This is the most general case of a function to return a name for an IR node.
2659 ROSE_ASSERT(type != NULL);
2660
2661 string returnName;
2662
2663 const SgNamedType* namedType = isSgNamedType(type);
2664 if (namedType != NULL)
2665 {
2666 returnName = "named_type_";
2667 returnName = namedType->get_name().getString();
2668 }
2669 else
2670 {
2671 switch(type->variantT())
2672 {
2673 case V_SgPointerType:
2674 {
2675 const SgPointerType* pointerType = isSgPointerType(type);
2676 returnName = "pointer_to_";
2677 returnName += get_name(pointerType->get_base_type());
2678 break;
2679 }
2680
2681 case V_SgReferenceType:
2682 {
2683 const SgReferenceType* referenceType = isSgReferenceType(type);
2684 returnName = "reference_to_";
2685 returnName += get_name(referenceType->get_base_type());
2686 break;
2687 }
2688
2689 case V_SgArrayType:
2690 {
2691 const SgArrayType* arrayType = isSgArrayType(type);
2692 returnName = "array_of_";
2693 returnName += get_name(arrayType->get_base_type());
2694 break;
2695 }
2696
2697 case V_SgModifierType:
2698 {
2699 const SgModifierType* modifierType = isSgModifierType(type);
2700 returnName = get_name(&(modifierType->get_typeModifier()));
2701 returnName += get_name(modifierType->get_base_type());
2702 break;
2703 }
2704
2705 // DQ (8/26/2012): Added case to support template declaration work.
2706 case V_SgTemplateType:
2707 {
2708 const SgTemplateType* templateType = isSgTemplateType(type);
2709 returnName = "templateType_";
2710 returnName += templateType->get_name();
2711 break;
2712 }
2713
2714 default:
2715 {
2716 returnName = type->class_name();
2717 }
2718 }
2719 }
2720
2721 return returnName;
2722 }
2723
2724string
2726 {
2727 string name = "undefined_name";
2728
2729 // ROSE_ASSERT(expr != NULL);
2730 switch(expr->variantT())
2731 {
2732 case V_SgVarRefExp:
2733 {
2734 const SgVarRefExp* varRef = isSgVarRefExp(expr);
2735 name = "var_ref_of_";
2736 ROSE_ASSERT(varRef != NULL);
2737 ROSE_ASSERT(varRef->get_symbol() != NULL);
2738 name += varRef->get_symbol()->get_name();
2739 break;
2740 }
2741
2742 // DQ (2/2/2011): Added case to support fortran use of label references in alternate return parameters.
2743 case V_SgLabelRefExp:
2744 {
2745 const SgLabelRefExp* labelRef = isSgLabelRefExp(expr);
2746 name = "label_ref_of_";
2747 ROSE_ASSERT(labelRef != NULL);
2748 ROSE_ASSERT(labelRef->get_symbol() != NULL);
2749 name += labelRef->get_symbol()->get_name();
2750 break;
2751 }
2752
2753 case V_SgPntrArrRefExp:
2754 {
2755 const SgPntrArrRefExp* arrayRef = isSgPntrArrRefExp(expr);
2756 name = "array_ref_of_";
2757 name += get_name(arrayRef->get_lhs_operand());
2758 name += "_at_";
2759 name += get_name(arrayRef->get_rhs_operand());
2760 break;
2761 }
2762
2763 case V_SgFunctionCallExp:
2764 {
2765 const SgFunctionCallExp* functionCall = isSgFunctionCallExp(expr);
2766 name = "function_call_";
2767 name += get_name(functionCall->get_function());
2768 break;
2769 }
2770
2771 case V_SgFunctionRefExp:
2772 {
2773 const SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(expr);
2774 name = "function_ref_";
2775 name += functionRefExp->get_symbol()->get_name();
2776 break;
2777 }
2778
2779 // DQ (4/19/2013): Added support for SgMemberFunctionRefExp.
2780 case V_SgMemberFunctionRefExp:
2781 {
2782 const SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(expr);
2783 name = "member_function_ref_";
2784 name += memberFunctionRefExp->get_symbol()->get_name();
2785 break;
2786 }
2787
2788 case V_SgIntVal:
2789 {
2790 const SgIntVal* valueExp = isSgIntVal(expr);
2791 name = "integer_value_exp_";
2792 name += StringUtility::numberToString(valueExp->get_value());
2793 break;
2794 }
2795
2796 case V_SgStringVal:
2797 {
2798 const SgStringVal* valueExp = isSgStringVal(expr);
2799 name = "string_value_exp_";
2800 name += valueExp->get_value();
2801 break;
2802 }
2803
2804 case V_SgSubscriptExpression:
2805 {
2806 const SgSubscriptExpression* subscriptExpression = isSgSubscriptExpression(expr);
2807 name = "subscript_exp_";
2808 // name += StringUtility::numberToString(subscriptExpression->get_lowerBound());
2809 name += get_name(subscriptExpression->get_lowerBound());
2810 name += "_";
2811 // name += StringUtility::numberToString(subscriptExpression->get_upperBound());
2812 name += get_name(subscriptExpression->get_upperBound());
2813 name += "_";
2814 // name += StringUtility::numberToString(subscriptExpression->get_stride());
2815 name += get_name(subscriptExpression->get_stride());
2816 break;
2817 }
2818
2819 case V_SgNullExpression:
2820 {
2821 name = "null_expression";
2822 break;
2823 }
2824
2825 // DQ (1/17/2011): Added support for SgExprListExp (to support debugging).
2826 case V_SgExprListExp:
2827 {
2828 const SgExprListExp* exprListExp = isSgExprListExp(expr);
2829 name = "expr_list_exp_";
2830 for (size_t i = 0; i < exprListExp->get_expressions().size(); i++)
2831 {
2832 name += get_name(exprListExp->get_expressions()[i]);
2833 }
2834 break;
2835 }
2836
2837 // DQ (1/31/2011): Added to support Fortran debugging.
2838 case V_SgActualArgumentExpression:
2839 {
2840 const SgActualArgumentExpression* actualArgExp = isSgActualArgumentExpression(expr);
2841 name = "actual_arg_exp_name_";
2842 name += actualArgExp->get_argument_name();
2843 name = "_exp_";
2844 name += get_name(actualArgExp->get_expression());
2845 break;
2846 }
2847
2848 // DQ (7/25/2012): Added support for new template IR nodes.
2849 case V_SgTemplateParameterVal:
2850 {
2851 const SgTemplateParameterVal* valueExp = isSgTemplateParameterVal(expr);
2852 name = "template_parameter_value_expression_number_";
2853 // name += valueExp->get_value();
2854 // name += get_name(valueExp);
2855 name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2856 break;
2857 }
2858
2859 // DQ (4/19/2013): Added support for SgDotExp.
2860 case V_SgDotExp:
2861 {
2862 const SgDotExp* dotExp = isSgDotExp(expr);
2863 ROSE_ASSERT(dotExp != NULL);
2864
2865 name = "_dot_exp_lhs_";
2866 name += get_name(dotExp->get_lhs_operand());
2867 name += "_dot_exp_rhs_";
2868 name += get_name(dotExp->get_rhs_operand());
2869 // name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2870 break;
2871 }
2872
2873 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2874 case V_SgLambdaExp:
2875 {
2876 const SgLambdaExp* lambdaExp = isSgLambdaExp(expr);
2877 ROSE_ASSERT (lambdaExp != NULL);
2878 name = "lambda_expression_";
2879 break;
2880 }
2881
2882 // DQ (1/3/2020): Added support for SgThisExp.
2883 case V_SgThisExp:
2884 {
2885 const SgThisExp* thisExp = isSgThisExp(expr);
2886 ROSE_ASSERT(thisExp != NULL);
2887
2888 name = "_this_exp_for_";
2889
2890 SgClassSymbol* classSymbol = thisExp->get_class_symbol();
2891 ROSE_ASSERT(classSymbol != NULL);
2892 // name += get_name(classSymbol->get_name());
2893 // string class_name = classSymbol->get_name();
2894 // name += class_name;
2895 name += classSymbol->get_name();
2896 break;
2897 }
2898
2899 default:
2900 {
2901 // Nothing to do for other IR nodes
2902#if 0
2903 // DQ (7/25/2012): Make this an error.
2904 printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2905 ROSE_ABORT();
2906#endif
2907 // DQ (4/8/2010): define something specific to this function to make debugging more clear.
2908 // printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2909 // name = "undefined_expression_name";
2910 name = expr->class_name() + "_undef_name";
2911 break;
2912 }
2913 }
2914
2915 return name;
2916 }
2917
2918string
2920 {
2921 // This function is useful for debugging
2922 // This is the most general case of a function to return a name for an IR node.
2923 ROSE_ASSERT(node != NULL);
2924
2925 string returnName;
2926
2927 switch(node->variantT())
2928 {
2929 case V_SgRenamePair:
2930 {
2931 const SgRenamePair* n = isSgRenamePair(node);
2932 returnName = "rename_pair_";
2933 returnName += n->get_local_name().str();
2934 returnName += "_from_";
2935 returnName += n->get_use_name().str();
2936 break;
2937 }
2938
2939 case V_SgInitializedName:
2940 {
2941 const SgInitializedName* n = isSgInitializedName(node);
2942 ROSE_ASSERT (n != NULL);
2943 returnName = "initialized_name_";
2944 returnName += n->get_name().str();
2945 break;
2946 }
2947
2948 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2949 case V_SgLambdaCapture:
2950 {
2951 const SgLambdaCapture* n = isSgLambdaCapture(node);
2952 ROSE_ASSERT (n != NULL);
2953 returnName = "lambda_capture_";
2954 // returnName += n->get_name().str();
2955 break;
2956 }
2957
2958#if 0
2959 case V_SgInterfaceBody:
2960 {
2961 const SgInterfaceBody* n = isSgInterfaceBody(node);
2962 returnName = "interface_body";
2963 break;
2964 }
2965#endif
2966 default:
2967 {
2968 returnName = node->class_name();
2969 }
2970 }
2971
2972 return returnName;
2973 }
2974
2975string
2977 {
2978 // This function is useful for debugging
2979 // This is the most general case of a function to return a name for an IR node.
2980 // Later this function will handle expressions, etc.
2981
2982 string name = "undefined_name";
2983
2984 ROSE_ASSERT(node != NULL);
2985
2986 const SgLocatedNode* locatedNode = isSgLocatedNode(node);
2987 if (locatedNode != NULL)
2988 {
2989 const SgStatement* statement = isSgStatement(node);
2990 if (statement != NULL)
2991 {
2992 name = get_name(statement);
2993 }
2994 else
2995 {
2996 const SgExpression* expression = isSgExpression(node);
2997 if (expression != NULL)
2998 {
2999 name = get_name(expression);
3000 }
3001 else
3002 {
3003 const SgLocatedNodeSupport* locatedNodeSupport = isSgLocatedNodeSupport(node);
3004 if (locatedNodeSupport != NULL)
3005 {
3006 name = get_name(locatedNodeSupport);
3007 }
3008 else
3009 {
3010 const SgToken* token = isSgToken(node);
3011 if (token != NULL)
3012 {
3013 name = get_name(token);
3014 }
3015 else
3016 {
3017 printf ("Unknown SgLocatedNode = %p = %s \n",node,node->class_name().c_str());
3018 ROSE_ABORT();
3019 }
3020 }
3021 }
3022 }
3023 }
3024 else
3025 {
3026 const SgSupport* supportNode = isSgSupport(node);
3027 if (supportNode != NULL)
3028 {
3029 name = get_name(supportNode);
3030 }
3031 else
3032 {
3033 // DQ (9/21/2005): I think this is good enough for the more general case (for now)
3034 const SgSymbol* symbol = isSgSymbol(node);
3035 if (symbol != NULL)
3036 {
3037 name = get_name(symbol);
3038 }
3039 else
3040 {
3041 // DQ (8/7/2007): Added support to get names of types (usefult for SgNamedType objects).
3042 const SgType* type = isSgType(node);
3043 if (type != NULL)
3044 {
3045 name = get_name(type);
3046 }
3047 else
3048 {
3049 name = node->class_name();
3050 }
3051 }
3052 }
3053 }
3054
3055 return name;
3056 }
3057
3058
3059string
3061 {
3062 // This function is useful for debugging
3063 string name = "undefined_name";
3064
3065 ROSE_ASSERT(token != NULL);
3066 name = token->get_lexeme_string();
3067
3068 // Handle special cases
3069 if (name == " ")
3070 name = "<space>";
3071 else if (name == "\n")
3072 name = "<eol>";
3073 else if (name == "\t")
3074 name = "<tab>";
3075
3076 return name;
3077 }
3078
3079
3080void
3087
3088
3089string
3091 {
3092 // DQ (3/20/2016): Adding support for generating a unique name from a declaration that
3093 // can be used as an identifier. This functionality is used in the DSL infrastructure
3094 // support (refactored to this location in ROSE). The point of this mechanism is that
3095 // unlike mangled names that are compressed in a way that allows them to only be used
3096 // within a single translation unit, names generated by this function can be used across
3097 // multiple translation units. These names are also easier to interprete in debugging
3098 // (since they explicitly contain the scope, function name, and coding to interprete
3099 // function overloading.
3100
3101 // At present it only supports class declarations, and function declarations (all others
3102 // are trapped as errors).
3103
3104 // Name collision testing, it might be that this should be external to this function.
3105 // static std::map<std::string,int> dsl_attribute_name_collision_map;
3106 // static std::map<std::string,int> local_name_collision_map;
3107
3108 string s;
3109
3110 // string scope = SageInterface::get_name(classDeclaration->get_scope());
3111 string scope = isSgGlobal(declaration->get_scope()) == NULL ? SageInterface::get_name(declaration->get_scope()) : "global";
3112
3113 switch (declaration->variantT())
3114 {
3115 case V_SgClassDeclaration:
3116 case V_SgTemplateClassDeclaration:
3117 // case V_SgTemplateInstantiationDecl:
3118 {
3119 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declaration);
3120 ROSE_ASSERT(classDeclaration != NULL);
3121
3122 string type_name = classDeclaration->get_name();
3123#if 0
3124 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case class or template type: type_name = %s \n",type_name.c_str());
3125#endif
3126 string className = string("scope_") + scope + "_type_name_" + type_name;
3127#if 0
3128 printf ("classDeclaration->get_scope() = %p = %s scope = %s \n",classDeclaration->get_scope(),classDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3129#endif
3130 s = className;
3131 break;
3132 }
3133
3134 // DQ (3/29/2016): Seperate out the case of the SgTemplateInstantiationDecl.
3135 case V_SgTemplateInstantiationDecl:
3136 {
3137 SgTemplateInstantiationDecl* templateInstantiationDeclaration = isSgTemplateInstantiationDecl(declaration);
3138 ROSE_ASSERT(templateInstantiationDeclaration != NULL);
3139
3140 // Note that we can't use the mangled name because they might not be unique across multiple translation units if seperately compiled).
3141 // string type_name = templateInstantiationDeclaration->get_name();
3142 // string type_name = templateInstantiationDeclaration->get_mangled_name();
3143 // string type_name = templateInstantiationDeclaration->get_templateName();
3144 string type_name = templateInstantiationDeclaration->get_name();
3145#if 0
3146 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgTemplateInstantiationDecl: type_name = %s \n",type_name.c_str());
3147#endif
3148 string className = string("scope_") + scope + "_type_name_" + type_name;
3149
3150 // Note that trimSpaces is defined in the name mangling support.
3151 // string compressedClassName = trimSpaces(className);
3152 // string compressedClassName = SageInterface::get_name(templateInstantiationDeclaration);
3153 // ROSE_UTIL_API std::string copyEdit(const std::string& inputString, const std::string & oldToken, const std::string & newToken);
3154
3155 // We need to turn this template instatiation name into a name that can be used as a C++ identifier.
3156 string compressedClassName = StringUtility::copyEdit(className," ","");
3157 compressedClassName = StringUtility::copyEdit(compressedClassName,"<","_abs_");
3158 compressedClassName = StringUtility::copyEdit(compressedClassName,">","_abe_");
3159 compressedClassName = StringUtility::copyEdit(compressedClassName,",","_comma_");
3160 compressedClassName = StringUtility::copyEdit(compressedClassName,"*","_star_");
3161 compressedClassName = StringUtility::copyEdit(compressedClassName,"&","_ref_");
3162#if 0
3163 printf ("className = %s compressedClassName = %s \n",className.c_str(),compressedClassName.c_str());
3164#endif
3165#if 0
3166 printf ("templateInstantiationDeclaration->get_scope() = %p = %s scope = %s \n",
3167 templateInstantiationDeclaration->get_scope(),templateInstantiationDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3168#endif
3169 // s = className;
3170 s = compressedClassName;
3171#if 0
3172 printf ("Exiting as a test! \n");
3173 ROSE_ABORT();
3174#endif
3175 break;
3176 }
3177
3178 case V_SgFunctionDeclaration:
3179 case V_SgTemplateFunctionDeclaration:
3180 case V_SgTemplateInstantiationFunctionDecl:
3181 {
3182 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration);
3183 ROSE_ASSERT(functionDeclaration != NULL);
3184#if 0
3185 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgFunctionDeclaration: not implemented \n");
3186#endif
3187 // We might at some point want the qualified name.
3188 string original_name = functionDeclaration->get_name();
3189
3190 string function_name_part = mangleFunctionName(original_name,"return_type");
3191 string function_name = string("scope_") + scope + "_function_name_" + function_name_part;
3192
3193 // DQ (3/16/2016): Detect name collisions so that we can
3194 // std::map<std::string,int> dsl_attribute_name_collision_map;
3195 if (local_name_collision_map.find(function_name) == local_name_collision_map.end())
3196 {
3197 local_name_collision_map.insert(pair<string,int>(function_name,0));
3198 }
3199 else
3200 {
3201 local_name_collision_map[function_name]++;
3202
3203 int count = local_name_collision_map[function_name];
3204#if 0
3205 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3206#endif
3207 function_name += StringUtility::numberToString(count);
3208 }
3209
3210 s = function_name;
3211#if 0
3212 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgFunctionDeclaration: Exiting as a test! \n");
3213 ROSE_ABORT();
3214#endif
3215 break;
3216 }
3217
3218 case V_SgMemberFunctionDeclaration:
3219 case V_SgTemplateMemberFunctionDeclaration:
3220 case V_SgTemplateInstantiationMemberFunctionDecl:
3221 {
3222 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(declaration);
3223 ROSE_ASSERT(memberFunctionDeclaration != NULL);
3224#if 0
3225 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgMemberFunctionDeclaration: not implemented \n");
3226#endif
3227 // We might at some point want the qualified name.
3228 string original_name = memberFunctionDeclaration->get_name();
3229
3230 // string member_function_name = memberFunctionDeclaration->get_mangled_name();
3231 // string member_function_name = memberFunctionDeclaration->get_qualified_name();
3232 // string member_function_name = SageInterface::get_name(memberFunctionDeclaration);
3233 // string member_function_scope = SageInterface::get_name(memberFunctionDeclaration->get_scope());
3234 string member_function_name_part = mangleFunctionName(original_name,"return_type");
3235 // string member_function_name = string("scope_") + member_function_scope + "_function_name_" + member_function_name_part;
3236 string member_function_name = string("scope_") + scope + "_member_function_name_" + member_function_name_part;
3237
3238 // DQ (3/16/2016): Detect name collisions so that we can
3239 // std::map<std::string,int> dsl_attribute_name_collision_map;
3240 if (local_name_collision_map.find(member_function_name) == local_name_collision_map.end())
3241 {
3242 local_name_collision_map.insert(pair<string,int>(member_function_name,0));
3243 }
3244 else
3245 {
3246 local_name_collision_map[member_function_name]++;
3247
3248 int count = local_name_collision_map[member_function_name];
3249#if 0
3250 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3251#endif
3252 member_function_name += StringUtility::numberToString(count);
3253 }
3254
3255 s = member_function_name;
3256#if 0
3257 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgMemberFunctionDeclaration: Exiting as a test! \n");
3258 ROSE_ABORT();
3259#endif
3260 break;
3261 }
3262
3263 default:
3264 {
3265 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Unsupported declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3266// ROSE_ASSERT(false);
3267 }
3268 }
3269
3270#if 0
3271 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3272#endif
3273#if 0
3274 if (s != "")
3275 {
3276 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3277 }
3278#endif
3279
3280#if 0
3281 printf ("Exiting as a test! \n");
3282 ROSE_ABORT();
3283#endif
3284
3285 return s;
3286 }
3287
3288// Generate unique name for use as a class name for the generated attribute classes.
3289// std::string AttributeGeneratorTraversal::generateUniqueNameForUseAsIdentifier ( SgDeclarationStatement* declaration )
3290// std::string AttributeGeneratorTraversal::generateUniqueName ( SgDeclarationStatement* declaration )
3291std::string
3293 {
3294 // DQ (3/21/2016): The support for unique name generation for use across translation
3295 // units is not refactored into the SageInterface.
3296 // string s = SageInterface::generateUniqueNameForUseAsIdentifier(declaration);
3297 string s;
3298
3299#if 0
3300 printf ("In generateUniqueNameForUseAsIdentifier(): evaluating declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3301#endif
3302
3303 ROSE_ASSERT(local_node_to_name_map.empty() == false);
3304 ROSE_ASSERT(local_name_to_node_map.empty() == false);
3305
3307 {
3309 }
3310 else
3311 {
3312 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3313 if (definingDeclaration != NULL)
3314 {
3315#if 0
3316 printf ("In generateUniqueName(): Using the defining declaration = %p since %p was not in the map \n",definingDeclaration,declaration);
3317#endif
3318 // s = generateUniqueName(definingDeclaration);
3319 s = generateUniqueNameForUseAsIdentifier_support(definingDeclaration);
3320 }
3321 else
3322 {
3323 // Note that builtin functions will not have a defining declaration.
3324 printf ("Warning: defining declaration not in SageInterface::local_node_to_name_map: declaration = %p = %s using name = %s \n",
3325 declaration,declaration->class_name().c_str(),SageInterface::get_name(declaration).c_str());
3326 // ROSE_ASSERT(false);
3327
3328 // If there is no defining declaration then go ahead and use the non-defining one.
3329 // s = SageInterface::get_name(declaration);
3330 SgDeclarationStatement* nondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3331 ROSE_ASSERT(nondefiningDeclaration != NULL);
3332 s = generateUniqueNameForUseAsIdentifier_support(nondefiningDeclaration);
3333 }
3334 }
3335
3336#if 0
3337 printf ("Exiting as a test! \n");
3338 ROSE_ABORT();
3339#endif
3340
3341 return s;
3342 }
3343
3344
3345void
3347 {
3348 ROSE_ASSERT(astNode != NULL);
3349
3350 ROSE_ASSERT(local_name_collision_map.empty() == true);
3351 ROSE_ASSERT(local_name_to_node_map.empty() == true);
3352 ROSE_ASSERT(local_node_to_name_map.empty() == true);
3353
3354 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
3355 class UniqueNameTraversal : public AstSimpleProcessing
3356 {
3357 public:
3358 void visit (SgNode* node)
3359 {
3360 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
3361 if (decl != NULL)
3362 {
3363 SgClassDeclaration* classDeclaration = isSgClassDeclaration(decl);
3364 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(decl);
3365 if (classDeclaration != NULL || functionDeclaration != NULL)
3366 {
3368 local_name_to_node_map.insert(pair<string,SgNode*>(s,decl));
3369 local_node_to_name_map.insert(pair<SgNode*,string>(decl,s));
3370 }
3371 }
3372 }
3373 };
3374
3375 // Now buid the traveral object and call the traversal (preorder) on the function definition.
3376 UniqueNameTraversal traversal;
3377 traversal.traverse(astNode, preorder);
3378 }
3379
3380
3381
3384 {
3385 SgMemberFunctionDeclaration* defaultConstructor = NULL;
3386
3387 ROSE_ASSERT(classDeclaration != NULL);
3388 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3389 ROSE_ASSERT(definingDeclaration != NULL);
3390 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3391
3392 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3393 // would be associated with a class declaration but no definition would exist).
3394 if (definingClassDeclaration != NULL)
3395 {
3396 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3397 ROSE_ASSERT(classDefinition != NULL);
3398
3399 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3400 while ( i != classDefinition->get_members().end() )
3401 {
3402 // Check the parent pointer to make sure it is properly set
3403 ROSE_ASSERT( (*i)->get_parent() != NULL);
3404 ROSE_ASSERT( (*i)->get_parent() == classDefinition);
3405
3406 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3407 if (memberFunction != NULL)
3408 {
3409 // printf ("memberFunction = %p = %s \n",memberFunction,memberFunction->get_name().str());
3410 if ( memberFunction->get_specialFunctionModifier().isConstructor() == true )
3411 defaultConstructor = memberFunction;
3412 }
3413
3414 // iterate through the class members
3415 i++;
3416 }
3417 }
3418
3419 // This should be true for the specific case that we are currently debugging!
3420 // ROSE_ASSERT(defaultConstructor != NULL);
3421
3422 return defaultConstructor;
3423 }
3424
3427 {
3428 SgMemberFunctionDeclaration* defaultDestructor = NULL;
3429
3430 ROSE_ASSERT(classDeclaration != NULL);
3431 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3432 if (definingDeclaration != NULL)
3433 {
3434 ROSE_ASSERT(definingDeclaration != NULL);
3435 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3436
3437 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3438 // would be associated with a class declaration but no definition would exist).
3439 if (definingClassDeclaration != NULL)
3440 {
3441 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3442 ROSE_ASSERT(classDefinition != NULL);
3443
3444 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3445 while ( i != classDefinition->get_members().end() )
3446 {
3447 // Check the parent pointer to make sure it is properly set
3448 SgNode* i_parent = (*i)->get_parent();
3449 ROSE_ASSERT(i_parent != NULL);
3450
3451 // DQ (11/1/2005): Note that a template instantiation can have a parent which is the
3452 // variable which forced it's instantiation. Since it does not really exist in the
3453 // source code explicitly (it is compiler generated) this is as reasonable as anything else.
3454 if ( i_parent != classDefinition )
3455 {
3456 printf ("Error: (*i)->get_parent() = %p = %s \n",i_parent,i_parent->class_name().c_str());
3457 printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),(*i)->unparseToString().c_str());
3458 (*i)->get_file_info()->display("Called from SageInterface::getDefaultDestructor: debug");
3459 }
3460 ROSE_ASSERT( i_parent == classDefinition);
3461
3462 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3463 if (memberFunction != NULL)
3464 {
3465 if ( memberFunction->get_specialFunctionModifier().isDestructor() == true )
3466 defaultDestructor = memberFunction;
3467 }
3468
3469 // iterate through the class members
3470 i++;
3471 }
3472 }
3473 }
3474
3475 return defaultDestructor;
3476 }
3477
3478
3479
3480bool
3481SageInterface::addDefaultConstructorIfRequired ( SgClassType* classType, int physical_file_id /* = Sg_File_Info::TRANSFORMATION_FILE_ID */ )
3482 {
3483 // DQ (11/9/2020): Added function to support adding a default constructor definition to a class
3484 // if it does not have a default constructor, but has any other constructor that would prevent
3485 // a compiler generated default constructor from being generated by the compiler.
3486
3487#define DEBUG_ADD_DEFAULT_CONSTRUCTOR 0
3488
3489 // Note the physical_file_id is so that it can be marked to be unparsed when header file unparsing is active.
3490
3491 ASSERT_not_null(classType);
3492
3493 bool returnValue = false;
3494
3495 // To setup this transformation we need to see if there is a default constructor in the associated class.
3496 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
3497 ROSE_ASSERT(classDeclaration != NULL);
3498 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(classDeclaration->get_definingDeclaration());
3499 ROSE_ASSERT(definingClassDeclaration != NULL);
3500 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3501 ROSE_ASSERT(classDefinition != NULL);
3502
3503 SgDeclarationStatementPtrList & declarationList = classDefinition->get_members();
3504
3505 bool foundConstructor = false;
3506 bool foundDefaultConstructor = false;
3507
3508#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3509 printf ("In addDefaultConstructorIfRequired(): class name = %s \n",classDeclaration->get_name().str());
3510#endif
3511
3512 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
3513 while (i != declarationList.end())
3514 {
3515 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(*i);
3516 if (memberFunctionDeclaration != NULL)
3517 {
3518 bool isConstructor = memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
3519 if (isConstructor == true)
3520 {
3521 foundConstructor = true;
3522
3523#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3524 printf ("Found a constructor! \n");
3525#endif
3526 SgFunctionParameterList* functionParameterList = memberFunctionDeclaration->get_parameterList();
3527 ROSE_ASSERT(functionParameterList != NULL);
3528
3529 // DQ (7/19/2021): Fixed to allow for previously found default constructor to be registered as found.
3530 // foundDefaultConstructor = (functionParameterList->get_args().size() == 0);
3531 foundDefaultConstructor = ((foundDefaultConstructor == true) || (functionParameterList->get_args().size() == 0));
3532
3533#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3534 if (foundDefaultConstructor == true)
3535 {
3536 printf ("Found a default constructor! \n");
3537 }
3538 else
3539 {
3540 printf ("This is not a default constructor: functionParameterList->get_args().size() = %zu \n",functionParameterList->get_args().size());
3541 }
3542#endif
3543 }
3544 else
3545 {
3546#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3547 printf ("This is not a constructor \n");
3548#endif
3549 }
3550 }
3551
3552 i++;
3553 }
3554
3555#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3556 printf ("foundConstructor = %s \n",foundConstructor ? "true" : "false");
3557 printf ("foundDefaultConstructor = %s \n",foundDefaultConstructor ? "true" : "false");
3558#endif
3559
3560 if (foundConstructor == true)
3561 {
3562 // Since there is at least one constructor, we can't rely on compiler generated constructors.
3563#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3564 printf ("Since there is at least one constructor, we can't rely on compiler generated constructors \n");
3565#endif
3566 if (foundDefaultConstructor == true)
3567 {
3568 // We can use the existing default constructor.
3569#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3570 printf ("We can use the existing default constructor (no need to build one) \n");
3571#endif
3572 }
3573 else
3574 {
3575 // We don't have a default constructor, so we need to build one explicitly, and insert it into the class definition.
3576
3577#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3578 printf ("########################################################### \n");
3579 printf ("Need to build a default constructor in the associated class \n");
3580#endif
3581 SgMemberFunctionDeclaration* constructorDeclaration = SageBuilder::buildDefaultConstructor(classType);
3582 ROSE_ASSERT(constructorDeclaration != NULL);
3583
3584#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3585 printf (" --- constructorDeclaration = %p = %s name = %s \n",constructorDeclaration,constructorDeclaration->class_name().c_str(),constructorDeclaration->get_name().str());
3586#endif
3587 ROSE_ASSERT (constructorDeclaration->get_declarationModifier().get_accessModifier().isPublic() == true);
3588
3589 classDefinition->prepend_statement(constructorDeclaration);
3590
3591 // constructorDeclaration->set_parent(classDefinition);
3592 ROSE_ASSERT(constructorDeclaration->get_parent() != NULL);
3593
3594 // int physical_file_id = variableDeclaration->get_startOfConstruct()->get_physical_file_id();
3595 markSubtreeToBeUnparsed(constructorDeclaration,physical_file_id);
3596
3597 returnValue = true;
3598#if 0
3599 constructorDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3600 constructorDeclaration->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3601
3602 // We also need to set the source position of the function definition, else the
3603 // function declaration will not be output.
3604 ROSE_ASSERT(constructorDeclaration->get_definition() != NULL);
3605 ROSE_ASSERT(constructorDeclaration->get_definition()->get_startOfConstruct() != NULL);
3606 ROSE_ASSERT(constructorDeclaration->get_definition()->get_endOfConstruct() != NULL);
3607 constructorDeclaration->get_definition()->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3608 constructorDeclaration->get_definition()->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3609#endif
3610
3611#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3612 printf ("DONE: Need to build a default constructor in the associated class \n");
3613 printf ("################################################################# \n");
3614#endif
3615#if 0
3616 printf ("Exiting as a test! \n");
3617 ROSE_ABORT();
3618#endif
3619 }
3620 }
3621 else
3622 {
3623 // No constructors found, so we don't need to add an explicit default constructor.
3624
3625#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3626 printf ("No constructors found, so we don't need to add an explicit default constructor \n");
3627#endif
3628 }
3629
3630#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3631 printf ("Leaving addDefaultConstructorIfRequired(): returnValue = %s \n",returnValue ? "true" : "false");
3632#endif
3633
3634 return returnValue;
3635 }
3636
3637
3638
3639
3640void
3642 {
3643 // DQ (6/27/2005): This function outputs the global table of function type symbols
3644 // it is built during the EDG/Sage translation phase, and it built initially with
3645 // the EDG names of all instantiated templates. At a later phase (incomplete at
3646 // the moment) the AST fixup rebuilds the table to use the modified template names
3647 // (that is mangled names built from the modified template names used in Sage III).
3648
3649 // DQ (1/31/2006): Modified to build all types in the memory pools
3650 // extern SgFunctionTypeTable Sgfunc_type_table;
3651 // Sgfunc_type_table.print_functypetable();
3652 ROSE_ASSERT(SgNode::get_globalFunctionTypeTable() != NULL);
3653 SgNode::get_globalFunctionTypeTable()->print_functypetable();
3654 }
3655
3656void
3658 {
3659 // This simplifies how the traversal is called!
3660 OutputLocalSymbolTables astTraversal;
3661
3662 // I think the default should be preorder so that the interfaces would be more uniform
3663 astTraversal.traverse(node,preorder);
3664 }
3665
3666void
3668 {
3669 // DQ (6/27/2005): Output the local symbol table from each scope.
3670 // printf ("node = %s \n",node->sage_class_name());
3671
3672#if 0
3673 printf ("Exiting as a test! \n");
3674 ROSE_ABORT();
3675#endif
3676
3677 SgScopeStatement* scope = isSgScopeStatement(node);
3678 if (scope != NULL)
3679 {
3680 // SgSymbolTable* symbolTable = scope->get_symbol_table();
3681 // ROSE_ASSERT(symbolTable != NULL);
3682
3683 printf ("Symbol Table from %p = %s at: \n",scope,scope->sage_class_name());
3684 scope->get_file_info()->display("Symbol Table Location (Called from SageInterface::OutputLocalSymbolTables::visit())");
3685 // symbolTable->print("Called from SageInterface::OutputLocalSymbolTables::visit()");
3686 scope->print_symboltable("Called from SageInterface::OutputLocalSymbolTables::visit()");
3687 }
3688 }
3689
3690#if 0
3691// DQ (8/28/2005): This is already a member function of the SgFunctionDeclaration
3692// (so that it can handle template functions and member functions)
3693
3694// DQ (8/27/2005):
3695bool
3696SageInterface::isTemplateMemberFunction( SgTemplateInstantiationMemberFunctionDecl* memberFunctionDeclaration )
3697 {
3698 // This function determines if the member function is associated with a template
3699 // or just a template class (where it is a normal non-template member function).
3700
3701 bool result = false;
3702
3703 result = memberFunctionDeclaration->isTemplateFunction();
3704
3705 return result;
3706 }
3707#endif
3708
3709// DQ (8/27/2005):
3710bool
3712 {
3713 // This function determines if the template declaration associated withthis member function instantiation is
3714 // defined in the class or outside of the class.
3715
3716 bool result = false;
3717
3718#if 0
3719 // Check if this is a template or non-template member function
3720 if (isTemplateMemberFunction(memberFunctionDeclaration) == true)
3721 {
3722 SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3723 printf ("templateDeclaration = %p parent of templateDeclaration = %p \n",templateDeclaration,templateDeclaration->get_parent());
3724
3725 // SgTemplateInstantiationDecl* classTemplateInstantiation = memberFunctionDeclaration->get_class_scope()->get_declaration();
3726 SgClassDeclaration* classDeclaration = memberFunctionDeclaration->get_class_scope()->get_declaration();
3727 ROSE_ASSERT(classDeclaration != NULL);
3728 SgTemplateInstantiationDecl* classTemplateInstantiation = isSgTemplateInstantiationDecl(classDeclaration);
3729
3730 if (classTemplateInstantiation != NULL)
3731 {
3732 SgTemplateDeclaration* classTemplateDeclaration = classTemplateInstantiation->get_templateDeclaration();
3733 if (classTemplateDeclaration != NULL && classTemplateDeclaration != templateDeclaration)
3734 {
3735 result = true;
3736 }
3737 }
3738 }
3739#endif
3740
3741 // Alternative approach
3742 // SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3743 SgDeclarationStatement* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3744// printf ("In templateDefinitionIsInClass(): templateDeclaration = %p parent of templateDeclaration = %p = %s \n",templateDeclaration,
3745// templateDeclaration->get_parent(),templateDeclaration->get_parent()->class_name().c_str());
3746
3747 if (templateDeclaration != NULL && templateDeclaration->get_parent() != NULL)
3748 {
3749 SgScopeStatement* parentScope = isSgScopeStatement(templateDeclaration->get_parent());
3750 if (isSgClassDefinition(parentScope) != NULL)
3751 {
3752 result = true;
3753 }
3754 }
3755
3756 return result;
3757 }
3758#if 0
3760generateUniqueDeclaration ( SgDeclarationStatement* declaration )
3761 {
3762 // DQ (10/11/2007): This is no longer used.
3763 printf ("Error: This is no longer used. \n");
3764 ROSE_ABORT();
3765
3766 // Get the defining or first non-defining declaration so that we can use it as a key to know
3767 // when we have found the same function. So we don't count a redundant forward declaration
3768 // found outside of the class as matching the first non-defining declaration or the defining
3769 // declaration in the class by mistake. All declarations share the same firstNondefining
3770 // declaration and defining declaration so either could be a key declaration, but there are
3771 // times when either one of then (but not both) can be NULL (function defined withouth forward
3772 // declaration or not defined at all).
3773 SgDeclarationStatement* firstNondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3774 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3775 SgDeclarationStatement* keyDeclaration = NULL;
3776 if (firstNondefiningDeclaration != NULL)
3777 keyDeclaration = firstNondefiningDeclaration;
3778 else
3779 keyDeclaration = definingDeclaration;
3780 ROSE_ASSERT(keyDeclaration != NULL);
3781
3782 return keyDeclaration;
3783 }
3784#endif
3787{
3788 string pragmaString = pragmaDeclaration->get_pragma()->get_pragma();
3789 istringstream istr(pragmaString);
3790 std::string key;
3791 istr >> key;
3792 return key;
3793}
3794
3796// TODO: move all Omp*statement under a parent SgOmpStatement
3798{
3799 ROSE_ASSERT (n != NULL);
3800 bool result = false;
3801 if (isSgOmpBarrierStatement(n)||
3802 isSgOmpBodyStatement(n)||
3803 isSgOmpDeclareSimdStatement(n) ||
3804 isSgOmpFlushStatement(n)||
3805 isSgOmpThreadprivateStatement(n)||
3806 isSgOmpTaskwaitStatement(n) )
3807 result = true;
3808
3809 return result;
3810
3811}
3812// DQ (8/28/2005):
3813bool
3815 {
3816 // This function looks for any other function that might overload the input function.
3817 // for member functions we only look in the scope where the member function is defined.
3818 // for non-member functions we look only in the scope where the function is declared.
3819
3820 // Note that there are scenarios where this approach of searching only these locations
3821 // might not catch an overloaded function.
3822 // * member functions:
3823 // - overloaded functions might be declared in base classes
3824 // * non-member functions:
3825 // - function declarations might be friend functions in classes
3826 // - functions might be declared in differen namespace definitions
3827 // (SgNamespaceDefinitionStatement), since a namespace in re-entrant
3828 // and can have many namespace declarations and definitions.
3829
3830 // bool result = false;
3831 int counter = 0;
3832
3833 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
3834 if (memberFunctionDeclaration != NULL)
3835 {
3836 // This is a member function declaration
3837
3838 // DQ (10/11/2007): Fix this to NOT use the generateUniqueDeclaration() function.
3839 // Generate a key to use for comparision (avoids false positives)
3840 // SgMemberFunctionDeclaration* keyDeclaration = isSgMemberFunctionDeclaration(generateUniqueDeclaration(functionDeclaration));
3841 // ROSE_ASSERT(keyDeclaration != NULL);
3842
3843 SgScopeStatement * scope = memberFunctionDeclaration->get_scope();
3844 ROSE_ASSERT(scope != NULL);
3845
3846 // TV (09/17/2018): ROSE-1378
3847 if (isSgDeclarationScope(scope)) {
3848 printf("TODO SageInterface::isOverloaded case when scope is SgDeclarationScope. See ROSE-1378.\n");
3849 return false;
3850 }
3851
3852 // Get the class definition
3853 SgClassDefinition* classDefinition =
3854 isSgClassDefinition(memberFunctionDeclaration->get_scope());
3855 ROSE_ASSERT(classDefinition != NULL);
3856
3857 // Get the class declaration associated with the class definition
3858 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classDefinition->get_declaration());
3859 ROSE_ASSERT(classDeclaration != NULL);
3860
3861 // Get the list of member declarations in the class
3862 SgDeclarationStatementPtrList & memberList = classDefinition->get_members();
3863#if 0
3864 // DQ (10/11/2007): Fix this function better by checking for more than one member function declaration in the class definition.
3865 printf (" memberList.size() = %" PRIuPTR " \n",memberList.size());
3866#endif
3867 for (SgDeclarationStatementPtrList::iterator i = memberList.begin(); i != memberList.end(); i++)
3868 {
3869#if 0
3870 printf (" counter = %d declaration = %p = %s \n",counter,*i,(*i)->class_name().c_str());
3871#endif
3872 SgMemberFunctionDeclaration* tempMemberFunction = isSgMemberFunctionDeclaration(*i);
3873 SgTemplateDeclaration* tempTemplateDeclaration = isSgTemplateDeclaration(*i);
3874
3875 // Member functions could be overloaded
3876 if (tempMemberFunction != NULL)
3877 {
3878#if 0
3879 // DQ (10/11/2007): This is a problem for where s member function prototype from outside the class is checked to be an ovverloaded function.
3880 // Check using the key declaration
3881 if ( keyDeclaration == generateUniqueDeclaration(tempMemberFunction) )
3882 {
3883#if 0
3884 printf ("Skipping the case of keyDeclaration == generateUniqueDeclaration(tempMemberFunction) = %p \n",keyDeclaration);
3885#endif
3886 continue;
3887 }
3888#endif
3889 ROSE_ASSERT(tempMemberFunction->get_name() != "");
3890#if 0
3891 printf (" tempMemberFunction = (name) %s = (qualified) %s \n",
3892 tempMemberFunction->get_name().str(),
3893 tempMemberFunction->get_qualified_name().str());
3894#endif
3895 if (tempMemberFunction->get_name() == memberFunctionDeclaration->get_name())
3896 {
3897#if 0
3898 printf (" Found a matching overloaded member function! \n");
3899#endif
3900 // result = true;
3901 counter++;
3902 }
3903 }
3904 else
3905 {
3906 // Or templates could be overloaded, but nothing else.
3907 if (tempTemplateDeclaration != NULL)
3908 {
3909 // If this is a template declaration, it could be a template
3910 // declaration for an overloaded member function of the same name.
3911#if 0
3912 // printf ("keyDeclaration->get_name() = %s \n",keyDeclaration->get_name().str());
3913 printf ("tempTemplateDeclaration->get_name() = %s \n",tempTemplateDeclaration->get_name().str());
3914#endif
3915 if (memberFunctionDeclaration->get_name() == tempTemplateDeclaration->get_name())
3916 {
3917#if 0
3918 printf (" Found a matching overloaded member function! \n");
3919#endif
3920 // result = true;
3921 counter++;
3922 }
3923 }
3924 else
3925 {
3926 // DQ (10/12/2007): Could friend functions defined in a class be overloaded? Need to check this!
3927 if (functionDeclaration->variantT() == V_SgFunctionDeclaration)
3928 {
3929 printf ("In SageInterface::isOverloaded(): could friend functions be overloaded in a class? \n");
3930 }
3931 }
3932 }
3933
3934 // If we have detected two, so we have an overloaded function.
3935 if (counter > 1)
3936 break;
3937 }
3938 }
3939 else
3940 {
3941 // This is a non-member function declaration
3942 printf ("In SageInterface::isOverloaded(): case of non-member function not yet implemented! \n");
3943 ROSE_ABORT();
3944 }
3945
3946 // DQ (10/11/2007): Fixup to use the counter and consider more than 1 function with the same name an overloaded member function.
3947 // This might be a problem for friend functions, so test this separately.
3948 // return result;
3949 return (counter > 1);
3950 }
3951
3952
3953
3954
3957 {
3958 // DQ (9/6/2005): This function builds a copy of the input function for the
3959 // construction of a forward declaration of the function. Required in the
3960 // instantiated functions definition is to be output as a specialization by ROSE.
3961 // Since the shallow copy mechanism will cause IR nodes to be shared, we have
3962 // to fix it up with deep copies of the parameter list and the CtorInitializerList.
3963
3964 ROSE_ASSERT(memberFunctionInstantiation != NULL);
3965
3966#if 0
3967 printf ("buildForwardFunctionDeclaration: Member function = %p = %s = definition = %p \n",
3968 memberFunctionInstantiation,
3969 memberFunctionInstantiation->get_name().str(),
3970 memberFunctionInstantiation->get_definition());
3971 memberFunctionInstantiation->get_file_info()->display("memberFunctionInstantiation: debug");
3972#endif
3973
3974 // This is a better implementation using a derived class from SgCopyHelp to control the
3975 // copying process (skipping the copy of any function definition). This is a variable
3976 // declaration with an explicitly declared class type.
3977 class NondefiningFunctionDeclarationCopyType : public SgCopyHelp
3978 {
3979 // DQ (9/26/2005): This class demonstrates the use of the copy mechanism
3980 // within Sage III (originally designed and implemented by Qing Yi).
3981 // One problem with it is that there is no context information permitted.
3982
3983 public:
3984 virtual SgNode *copyAst(const SgNode *n)
3985 {
3986 // If still NULL after switch then make the copy
3987 SgNode* returnValue = NULL;
3988
3989 switch(n->variantT())
3990 {
3991 // DQ (10/21/2007): Now that s bug is fixed in the SgDeclarationStatement::fixupCopy()
3992 // member function, I think we might not need this case.
3993
3994 // Don't copy the associated non-defining declaration when building a function prototype!
3995 case V_SgFunctionDeclaration:
3996 case V_SgMemberFunctionDeclaration:
3997 case V_SgTemplateInstantiationFunctionDecl:
3998 case V_SgTemplateInstantiationMemberFunctionDecl:
3999 {
4000 // printf ("Skip copying an associated non-defining declaration if it is present \n");
4001 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(n);
4002 ROSE_ASSERT(functionDeclaration != NULL);
4003 if (functionDeclaration == functionDeclaration->get_definingDeclaration())
4004 {
4005 // This is the defining declaration (make a shallow copy)
4006 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the DEFINING declaration! \n");
4007 // return const_cast<SgNode *>(n);
4008 returnValue = const_cast<SgNode *>(n);
4009 }
4010 else
4011 {
4012 // This is the non-defining declaration where we want to make a deep copy.
4013 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the NONDEFINING declaration! \n");
4014 }
4015
4016 break;
4017 }
4018
4019 // Don't copy the function definitions (roughly the body of the function)
4020 case V_SgFunctionDefinition:
4021 {
4022 printf ("Skip copying the function definition if it is present \n");
4023 // return const_cast<SgNode *>(n);
4024 returnValue = const_cast<SgNode *>(n);
4025 break;
4026 }
4027
4028 default:
4029 {
4030 // Nothing to do here
4031 break;
4032 }
4033 }
4034
4035 // return n->copy(*this);
4036
4037 // If not set at this point then make the copy!
4038 if (returnValue == NULL)
4039 returnValue = n->copy(*this);
4040
4041 ROSE_ASSERT(returnValue != NULL);
4042 return returnValue;
4043 }
4044 } nondefiningFunctionDeclarationCopy;
4045
4046 // DQ (10/20/2007): The more accurate copy mechanism now builds us a defining declaration to go with the non-defining declaration!
4047 // This is because we have to remove the pointers from non-defining declaration to the definition (which should be pointed to ONLY by the defining declaration!
4048 // delete copyOfMemberFunction->get_definingDeclaration();
4049 if (memberFunctionInstantiation->get_definition() != NULL)
4050 {
4051 printf ("\n\nNEED TO REMOVE POINTERS IN THE NON-DEFINING DECLARATION TO THE SgClassDefinition objects. \n");
4052 ROSE_ABORT();
4053
4054 // If we see the assertion above fail then we might want to use this code:
4055 ROSE_ASSERT( memberFunctionInstantiation != memberFunctionInstantiation->get_definingDeclaration() );
4056 memberFunctionInstantiation->set_definition(NULL);
4057 }
4058 SgNode* copyOfMemberFunctionNode = memberFunctionInstantiation->copy(nondefiningFunctionDeclarationCopy);
4059 SgTemplateInstantiationMemberFunctionDecl* copyOfMemberFunction = static_cast<SgTemplateInstantiationMemberFunctionDecl*>(copyOfMemberFunctionNode);
4060
4061 // printf ("\n\nHOW DO WE KNOW WHEN TO NOT COPY THE DEFINING DECLARATION SO THAT WE CAN JUST BUILD A FUNCTION PROTOTYPE! \n");
4062 // ROSE_ASSERT(false);
4063
4064#if 0
4065 printf ("copyOfMemberFunction->get_firstNondefiningDeclaration() = %p \n",copyOfMemberFunction->get_firstNondefiningDeclaration());
4066#endif
4067 // DQ (10/11/2007): The copy function sets the firstNondefiningDeclaration to itself if in the original declaration it had the
4068 // firstNondefiningDeclaration set to itself, this is incorrect in the case where we only make a copy of function declaration,
4069 // and causes the symbol table tests for get_declaration_associated_with_symbol() to fail because it uses the
4070 // firstNondefiningDeclaration which is not the one associated with the symbol in the parent scope. So reset the
4071 // firstNondefiningDeclaration in the copy of the member function.
4072 copyOfMemberFunction->set_firstNondefiningDeclaration(memberFunctionInstantiation->get_firstNondefiningDeclaration());
4073
4074#if 0
4075 printf ("memberFunctionInstantiation->get_firstNondefiningDeclaration() = %p \n",memberFunctionInstantiation->get_firstNondefiningDeclaration());
4076
4077 printf ("copyOfMemberFunction->isForward() = %s \n",copyOfMemberFunction->isForward() ? "true" : "false");
4078 printf ("memberFunctionInstantiation->isForward() = %s \n",memberFunctionInstantiation->isForward() ? "true" : "false");
4079#endif
4080#if 0
4081 printf ("memberFunctionInstantiation->isSpecialization() = %s \n",memberFunctionInstantiation->isSpecialization() ? "true" : "false");
4082 printf ("copyOfMemberFunctionNode = %p = %s = %s memberFunctionInstantiation->isSpecialization() = %s \n",
4083 copyOfMemberFunction,copyOfMemberFunction->class_name().c_str(),SageInterface::get_name(copyOfMemberFunction).c_str(),copyOfMemberFunction->isSpecialization() ? "true" : "false");
4084 copyOfMemberFunction->get_file_info()->display("copyOfMemberFunction: debug");
4085#endif
4086
4087 // Make sure that we have the same number of arguments on the copy that we build
4088 ROSE_ASSERT(memberFunctionInstantiation->get_args().size() == copyOfMemberFunction->get_args().size());
4089
4090 // DQ (11/5/2007): Additional tests
4091 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isOutputInCodeGeneration() == copyOfMemberFunction->get_startOfConstruct()->isOutputInCodeGeneration());
4092 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isCompilerGenerated() == copyOfMemberFunction->get_startOfConstruct()->isCompilerGenerated());
4093
4094 ROSE_ASSERT(copyOfMemberFunction != NULL);
4095 return copyOfMemberFunction;
4096 }
4097
4098
4099void
4100supportForBaseTypeDefiningDeclaration ( SgSymbolTable* symbolTable, SgDeclarationStatement* declarationForType )
4101 {
4102 // DQ (10/14/2007): Supporting function for
4103
4104 ROSE_ASSERT(declarationForType != NULL);
4105
4106 // DQ (11/7/2007): Added more cases...
4107 switch(declarationForType->variantT())
4108 {
4109 // DQ (12/26/2012): Added support for templates.
4110 case V_SgTemplateInstantiationDecl:
4111 case V_SgTemplateClassDeclaration:
4112
4113 case V_SgClassDeclaration:
4114 {
4115 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declarationForType);
4116 // SgSymbol* symbol = new SgClassSymbol(classDeclaration);
4117 SgSymbol* symbol = NULL;
4118 if (isSgTemplateClassDeclaration(declarationForType) != NULL)
4119 {
4120 symbol = new SgTemplateClassSymbol(classDeclaration);
4121 }
4122 else
4123 {
4124 symbol = new SgClassSymbol(classDeclaration);
4125 }
4126
4127 ROSE_ASSERT(symbol != NULL);
4128 SgName name = classDeclaration->get_name();
4129 symbolTable->insert(name,symbol);
4130 break;
4131 }
4132
4133 case V_SgEnumDeclaration:
4134 {
4135 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(declarationForType);
4136 SgSymbol* symbol = new SgEnumSymbol(enumDeclaration);
4137 ROSE_ASSERT(symbol != NULL);
4138 SgName name = enumDeclaration->get_name();
4139 symbolTable->insert(name,symbol);
4140 break;
4141 }
4142
4143 case V_SgFunctionDeclaration:
4144 {
4145 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declarationForType);
4146 SgSymbol* symbol = new SgFunctionSymbol(functionDeclaration);
4147 ROSE_ASSERT(symbol != NULL);
4148 SgName name = functionDeclaration->get_name();
4149 symbolTable->insert(name,symbol);
4150 break;
4151 }
4152
4153 case V_SgMemberFunctionDeclaration:
4154 {
4155 SgMemberFunctionDeclaration* functionDeclaration = isSgMemberFunctionDeclaration(declarationForType);
4156 SgSymbol* symbol = new SgMemberFunctionSymbol(functionDeclaration);
4157 ROSE_ASSERT(symbol != NULL);
4158
4159 // printf ("In supportForBaseTypeDefiningDeclaration(): symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4160
4161 SgName name = functionDeclaration->get_name();
4162 symbolTable->insert(name,symbol);
4163 break;
4164 }
4165
4166 default:
4167 {
4168 printf ("Default reached in evaluation of typedef inner definition = %p = %s and building a symbol for it for the symbol table \n",declarationForType,declarationForType->class_name().c_str());
4169 ROSE_ABORT();
4170 }
4171 }
4172 }
4173
4174
4175void
4176supportForVariableLists ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgInitializedNamePtrList & variableList )
4177 {
4178 // DQ (11/1/2007): Added supporting function to refactor code.
4179 SgInitializedNamePtrList::iterator i = variableList.begin();
4180 while (i != variableList.end())
4181 {
4183 ROSE_ASSERT(variable != NULL);
4184 if (variable->get_scope() == scope)
4185 {
4186 // printf ("Scopes match, OK! \n");
4187 }
4188 else
4189 {
4190 if (SgProject::get_verbose() > 0)
4191 {
4192 printf ("WARNING: Scopes do NOT match! variable = %p = %s (could this be a static variable, or has the symbol table been setup before the scopes have been set?) \n",variable,variable->get_name().str());
4193 }
4194 }
4195
4196 SgSymbol* symbol = new SgVariableSymbol(variable);
4197 ROSE_ASSERT(symbol != NULL);
4198 SgName name = variable->get_name();
4199 symbolTable->insert(name,symbol);
4200
4201 i++;
4202 }
4203 }
4204#if 0
4205// DQ (3/2/2014): Added a new interface function (used in the snippet insertion support).
4206void
4207SageInterface::supportForInitializedNameLists ( SgScopeStatement* scope, SgInitializedNamePtrList & variableList )
4208 {
4209 SgSymbolTable* symbolTable = scope->get_symbol_table();
4210 ROSE_ASSERT(symbolTable != NULL);
4211
4212 supportForVariableLists(scope,symbolTable,variableList);
4213 }
4214#endif
4215
4216void
4217supportForVariableDeclarations ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgVariableDeclaration* variableDeclaration )
4218 {
4219 // DQ (10/24/2007): Added supporting function to refactor code.
4220 SgInitializedNamePtrList & variableList = variableDeclaration->get_variables();
4221 supportForVariableLists(scope,symbolTable,variableList);
4222
4223 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4224 // that also force symbols to be built in the current scope!
4225 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4226 if (variableDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4227 {
4228 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4229 ROSE_ASSERT(symbolTable != NULL);
4230 ROSE_ASSERT(variableDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4231 supportForBaseTypeDefiningDeclaration ( symbolTable, variableDeclaration->get_baseTypeDefiningDeclaration() );
4232 }
4233 }
4234
4235void
4236supportForLabelStatements ( SgScopeStatement* scope, SgSymbolTable* symbolTable )
4237 {
4238 // Update the symbol table in SgFunctionDefinition with all the labels in the function.
4239
4240 std::vector<SgNode*> labelList = NodeQuery::querySubTree (scope,V_SgLabelStatement);
4241
4242 int numberOfLabels = labelList.size();
4243 for (int i=0; i < numberOfLabels; i++)
4244 {
4245 SgLabelStatement* labelStatement = isSgLabelStatement(labelList[i]);
4246
4247 ROSE_ASSERT(labelStatement != NULL);
4248 ROSE_ASSERT(labelStatement->get_scope() == scope);
4249
4250 SgSymbol* symbol = new SgLabelSymbol(labelStatement);
4251 ROSE_ASSERT(symbol != NULL);
4252
4253 // printf ("In SageInterface::rebuildSymbolTable() labelStatement = %p building a new SgLabelSymbol = %p \n",labelStatement,symbol);
4254
4255 SgName name = labelStatement->get_name();
4256 symbolTable->insert(name,symbol);
4257 }
4258 }
4259
4260
4261void
4263 {
4264 // This function is called from the implementation of the copy member functions.
4265
4266 ROSE_ASSERT(scope != NULL);
4267#if 0
4268 printf ("In SageInterface::rebuildSymbolTable(): Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4269#endif
4270#if 0
4271 printf ("Exiting as a test \n");
4272 ROSE_ABORT();
4273#endif
4274
4275 SgSymbolTable* symbolTable = scope->get_symbol_table();
4276
4277 if (symbolTable != NULL)
4278 {
4279 // This must be an empty symbol table!
4280 if (symbolTable->size() != 0)
4281 {
4282 printf ("symbolTable->size() = %d \n",symbolTable->size());
4283 }
4284 ROSE_ASSERT(symbolTable->size() == 0);
4285#if 0
4286 printf ("Symbol Table from %p = %s of size = %" PRIuPTR " \n",scope,scope->class_name().c_str(),symbolTable->size());
4287 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
4288#endif
4289 }
4290 else
4291 {
4292#if 0
4293 printf ("In SageInterface::rebuildSymbolTable(): No symbol table found \n");
4294#endif
4295 ROSE_ASSERT(symbolTable == NULL);
4296
4297 // DQ (10/8/2007): Build a new symbol table if there was not already one built.
4298 symbolTable = new SgSymbolTable();
4299
4300 ROSE_ASSERT(symbolTable != NULL);
4301 ROSE_ASSERT(symbolTable->get_table() != NULL);
4302
4303 // DQ (2/16/2006): Set this parent directly (now tested)
4304 symbolTable->set_parent(scope);
4305 ROSE_ASSERT(symbolTable->get_parent() != NULL);
4306
4307 scope->set_symbol_table(symbolTable);
4308 }
4309
4310 // DQ (10/8/2007): If there is already a symbol table then don't over write it. This fixes copies generated with more than one symbol table.
4311 ROSE_ASSERT(scope->get_symbol_table() != NULL);
4312 ROSE_ASSERT(scope->get_symbol_table()->get_table() != NULL);
4313
4314 // This implements SgScopeStatement specific details (e.g function declarations have parameters and their declaration causes variable
4315 // symbols to be placed into the SgFunctionDefinition scope (but only for defining declarations).
4316 switch(scope->variantT())
4317 {
4318 case V_SgForStatement:
4319 {
4320 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4321 // printf ("Symbol tables could contain symbols outside of the inclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4322
4323 SgForStatement* forStatement = isSgForStatement(scope);
4324
4325 SgStatementPtrList::iterator i = forStatement->get_init_stmt().begin();
4326
4327 // printf ("i != forStatement->get_init_stmt().end() = %s \n",i != forStatement->get_init_stmt().end() ? "true" : "false");
4328
4329 while (i != forStatement->get_init_stmt().end())
4330 {
4331 // printf ("For statement initialization list: *i = %p = %s \n",*i,(*i)->class_name().c_str());
4332 SgVariableDeclaration* variableDeclarationInitializer = isSgVariableDeclaration(*i);
4333 if (variableDeclarationInitializer != NULL)
4334 {
4335 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4336 // printf ("There is a variable declaration in the for statement initializer, it needs to be added to the symbol table scope = %p = %s \n",scope,scope->class_name().c_str());
4337 // ROSE_ASSERT(false);
4338 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationInitializer );
4339 }
4340
4341 i++;
4342 }
4343
4344 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(forStatement->get_test());
4345 if (variableDeclarationCondition != NULL)
4346 {
4347 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4348 // printf ("There is a variable declaration in the for statement test, it needs to be added to the symbol table scope = %p = %s \n",scope,scope->class_name().c_str());
4349 // ROSE_ASSERT(false);
4350 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4351 }
4352
4353 return;
4354 break;
4355 }
4356
4357 case V_SgJovialForThenStatement:
4358 case V_SgMatlabForStatement:
4359 {
4360 return;
4361 break;
4362 }
4363
4364
4365 // DQ (12/23/2012): Added support for templates.
4366 case V_SgTemplateFunctionDefinition:
4367
4368 case V_SgFunctionDefinition:
4369 {
4370 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4371 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4372
4373 // DQ (10/8/2007): If this is a SgFunctionDefinition, then include the parameters in the SgFunctionDeclaration.
4374 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
4375 if (functionDefinition != NULL)
4376 {
4377 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
4378 // printf ("In SageInterface::rebuildSymbolTable(): functionDefinition = %p functionDeclaration = %p \n",functionDefinition,functionDeclaration);
4379
4380 // DQ (10/8/2007): It turns out that this is always NULL, because the parent of the functionDeclaration has not yet been set in the copy mechanism!
4381 if (functionDeclaration != NULL)
4382 {
4383 // DQ (3/28/2014): After a call with Philippe, this Java specific issues is fixed and we don't seem to see this problem any more.
4384 if (functionDeclaration->isForward() == true)
4385 {
4386 printf ("ERROR: functionDeclaration = %p = %s = %s \n",functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
4387 printf (" --- functionDeclaration (get_name()) = %s \n",get_name(functionDeclaration).c_str());
4388 printf (" --- functionDeclaration (mangled name) = %s \n",functionDeclaration->get_mangled_name().str());
4389 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
4390 if (memberFunctionDeclaration != NULL)
4391 {
4392 printf ("memberFunctionDeclaration != NULL \n");
4393 }
4394 }
4395 ROSE_ASSERT(functionDeclaration->isForward() == false);
4396 SgInitializedNamePtrList & argumentList = functionDeclaration->get_args();
4397 supportForVariableLists(scope,symbolTable,argumentList);
4398 }
4399 else
4400 {
4401 // This happens in the copy function because the function definition is copied from the SgFunctionDeclaration
4402 // and only after the copy is made is the parent of the definition set to be the function declaration. Thus
4403 // the get_declaration() member function returns NULL.
4404 // printf ("There is no function declaration associated with this function definition! \n");
4405 // ROSE_ASSERT(functionDeclaration->isForward() == true);
4406 }
4407 }
4408
4409 // DQ (10/25/2007): Label symbols are now places into the SgFunctionDefinition (they have to be collected from the function).
4410 supportForLabelStatements(scope,symbolTable);
4411
4412 return;
4413 break;
4414 }
4415
4416 case V_SgIfStmt:
4417 {
4418 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4419 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4420
4421 SgIfStmt* ifStatement = isSgIfStmt(scope);
4422 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(ifStatement->get_conditional());
4423 if (variableDeclarationCondition != NULL)
4424 {
4425 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4426 // printf ("There is a variable declaration in the conditional, it needs to be added to the symbol table \n");
4427 // ROSE_ASSERT(false);
4428 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4429 }
4430 return;
4431 break;
4432 }
4433
4434 case V_SgSwitchStatement:
4435 {
4436 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4437 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4438
4439 SgSwitchStatement* switchStatement = isSgSwitchStatement(scope);
4440 SgVariableDeclaration* variableDeclarationSelector = isSgVariableDeclaration(switchStatement->get_item_selector());
4441 if (variableDeclarationSelector != NULL)
4442 {
4443 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4444 // printf ("There is a variable declaration in the item selector of the switch statement, it needs to be added to the symbol table \n");
4445
4446 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationSelector );
4447 }
4448 return;
4449 break;
4450 }
4451
4452 case V_SgWhileStmt:
4453 {
4454 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4455 // commented out like for others, otherwise show up each time a While is being copied. Liao, 1/31/2008
4456 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4457
4458 SgWhileStmt* whileStatement = isSgWhileStmt(scope);
4459 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(whileStatement->get_condition());
4460 if (variableDeclarationCondition != NULL)
4461 {
4462 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4463 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4464 // ROSE_ASSERT(false);
4465
4466 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4467 }
4468 return;
4469 break;
4470 }
4471
4472 case V_SgCatchOptionStmt:
4473 case V_SgDoWhileStmt:
4474 {
4475 // These scopes contain a SgBasicBlock as a data member and the scope is held there.
4476 // printf ("Symbol tables can must be computed by the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4477 return;
4478 break;
4479 }
4480
4481 // DQ (12/24/2012): Added support for templates.
4482 case V_SgTemplateClassDefinition:
4483
4484 case V_SgBasicBlock:
4485 case V_SgClassDefinition:
4486 case V_SgTemplateInstantiationDefn:
4487 case V_SgGlobal:
4488 case V_SgNamespaceDefinitionStatement:
4489 case V_SgFortranDo: // Liao 12/19/2008, My understanding is that Fortran do loop header does not introduce new symbols like a C/C++ for loop does
4490 {
4491 // printf ("Used the list of statements/declarations that are held deirectly by this scope \n");
4492 break;
4493 }
4494
4495 // DQ (3/29/2014): Added support for SgJavaForEachStatement.
4496 case V_SgJavaForEachStatement:
4497 {
4498 SgJavaForEachStatement* javaForEachStatement = isSgJavaForEachStatement(scope);
4499 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(javaForEachStatement->get_element());
4500 if (variableDeclarationCondition != NULL)
4501 {
4502 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4503 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4504 // ROSE_ASSERT(false);
4505
4506 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4507 }
4508 return;
4509 break;
4510 }
4511
4512 default:
4513 {
4514 printf ("Default reached in SageInterface::rebuildSymbolTable() scope = %p = %s \n",scope,scope->class_name().c_str());
4515 ROSE_ABORT();
4516 }
4517 }
4518
4519#if 0
4520 printf ("In SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4521#endif
4522
4523 // Generate a copy of the statement list (this is simpler than handling the cases of a
4524 // declaration list and a statement list separately for the scopes that contain one or the other.
4525 SgStatementPtrList statementList = scope->generateStatementList();
4526
4527 // Loop through the statements and for each declaration build a symbol and add it to the symbol table
4528 for (SgStatementPtrList::iterator i = statementList.begin(); i != statementList.end(); i++)
4529 {
4530 // At some point we should move this mechanism in to a factory patterns for SgSymbol
4531
4532 // printf ("Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4533
4534 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
4535 if (declaration != NULL)
4536 {
4537 // DQ (11/7/2007): Where there can be multiple declaration (e.g. function declarations with prototypes) only use one of them.
4538 bool useThisDeclaration = (declaration->get_firstNondefiningDeclaration() == declaration) ||
4539 ( (declaration->get_firstNondefiningDeclaration() == NULL) && (declaration->get_definingDeclaration() == declaration) );
4540
4541 list<SgSymbol*> symbolList;
4542 switch(declaration->variantT())
4543 {
4544 case V_SgTemplateInstantiationMemberFunctionDecl:
4545 {
4546 SgTemplateInstantiationMemberFunctionDecl* derivedDeclaration = isSgTemplateInstantiationMemberFunctionDecl(declaration);
4547 // DQ (11/6/2007): Don't build a symbol for the defining declaration defined in another scope and put the resulting symbol into the wrong scope
4548 if (scope == derivedDeclaration->get_scope())
4549 {
4550 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4551 ROSE_ASSERT(symbol != NULL);
4552
4553 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4554
4555 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s inserting a symbol = %p \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str(),symbol);
4556
4557 SgName name = derivedDeclaration->get_name();
4558 symbolTable->insert(name,symbol);
4559 }
4560 else
4561 {
4562 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4563
4564 // These IR nodes might only exist as a template declaration and thus not be structureally present in their scope.
4565 // So we would never traverse them in the correct scope and so never build sysmbols for them and add the symbols
4566 // to the correct symbol table. This is a fundamental problem. So we have to try to add these sorts of symbols
4567 // to the scope were they belong.
4568 SgScopeStatement* derivedDeclarationScope = derivedDeclaration->get_scope();
4569 ROSE_ASSERT(derivedDeclarationScope != NULL);
4570
4571 // If this is a copy then it would be nice to make sure that the scope has been properly set.
4572 // Check this by looking for the associated template declaration in the scope.
4573 // SgTemplateDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4574 // SgDeclarationStatement* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4575 SgTemplateMemberFunctionDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4576 ROSE_ASSERT(templateDeclaration != NULL);
4577 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_name());
4578
4579 // DQ (8/13/2013): Fixed the interface to avoid use of lookup_template_symbol() (removed).
4580 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
4581 // In this case these are unavailable from this point.
4582 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name());
4583 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4584 SgType* functionType = templateDeclaration->get_type();
4585 SgTemplateParameterPtrList & templateParameterList = templateDeclaration->get_templateParameters();
4586 // SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4587 SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_member_function_symbol(templateDeclaration->get_template_name(),functionType,&templateParameterList);
4588 if (templateSymbol != NULL)
4589 {
4590 // The symbol is not present, so we have to build one and add it.
4591#if 0
4592 printf ("Building a symbol for derivedDeclaration = %p = %s to an alternative symbol table in derivedDeclarationScope = %p \n",
4593 derivedDeclaration,get_name(derivedDeclaration).c_str(),derivedDeclarationScope);
4594#endif
4595 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4596 ROSE_ASSERT(symbol != NULL);
4597 SgName name = derivedDeclaration->get_name();
4598 derivedDeclarationScope->insert_symbol(name,symbol);
4599 }
4600 else
4601 {
4602 // printf ("The symbol was already present in the derivedDeclarationScope = %p \n",derivedDeclarationScope);
4603 }
4604 }
4605 break;
4606 }
4607
4608 // DQ (12/26/2012): Added support for templates.
4609 case V_SgTemplateMemberFunctionDeclaration:
4610
4611 case V_SgMemberFunctionDeclaration:
4612 {
4613 SgMemberFunctionDeclaration* derivedDeclaration = isSgMemberFunctionDeclaration(declaration);
4614
4615 // DQ (11/6/2007): Don't build a symbol for the defining declaration defined in another scope and put the resulting symbol into the wrong scope
4616 if (scope == derivedDeclaration->get_scope())
4617 {
4618 // SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4619 SgSymbol* symbol = NULL;
4620 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4621 symbol = new SgTemplateMemberFunctionSymbol(derivedDeclaration);
4622 else
4623 symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4624
4625 ROSE_ASSERT(symbol != NULL);
4626
4627 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4628
4629 SgName name = derivedDeclaration->get_name();
4630 symbolTable->insert(name,symbol);
4631 }
4632 else
4633 {
4634 // This happens when a defining declaration is located outside of the class where it is associated.
4635 // printf ("SgMemberFunctionDeclaration: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4636 }
4637 break;
4638 }
4639
4640 // DQ (2/26/2009): These have to be reformatted from where someone removed the formatting previously.
4641 case V_SgTemplateInstantiationFunctionDecl:
4642 {
4643 SgTemplateInstantiationFunctionDecl* derivedDeclaration = isSgTemplateInstantiationFunctionDecl(declaration);
4644 // DQ (10/21/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4645 if (scope == derivedDeclaration->get_scope())
4646 {
4647 SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4648 ROSE_ASSERT(symbol != NULL);
4649 SgName name = derivedDeclaration->get_name();
4650 symbolTable->insert(name,symbol);
4651 }
4652 else
4653 {
4654 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4655 {
4656#if PRINT_DEVELOPER_WARNINGS
4657 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4658#endif
4659 }
4660 }
4661
4662 break;
4663 }
4664
4665 // DQ (12/24/2012): Added support for templates.
4666 case V_SgTemplateFunctionDeclaration:
4667
4668 case V_SgFunctionDeclaration:
4669 {
4670 SgFunctionDeclaration* derivedDeclaration = isSgFunctionDeclaration(declaration);
4671
4672 // DQ (10/20/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4673
4674 if (useThisDeclaration == true)
4675 {
4676 if (scope == derivedDeclaration->get_scope())
4677 {
4678 // DQ (12/24/2012): Added support for templates.
4679 // SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4680 SgSymbol* symbol = NULL;
4681 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4682 symbol = new SgTemplateFunctionSymbol(derivedDeclaration);
4683 else
4684 symbol = new SgFunctionSymbol(derivedDeclaration);
4685
4686 ROSE_ASSERT(symbol != NULL);
4687 SgName name = derivedDeclaration->get_name();
4688 symbolTable->insert(name,symbol);
4689 }
4690 else
4691 {
4692 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4693 {
4694#if PRINT_DEVELOPER_WARNINGS
4695 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4696#endif
4697 }
4698 }
4699 }
4700 break;
4701 }
4702
4703 // DQ (12/28/2012): Adding support for templates.
4704 case V_SgTemplateVariableDeclaration:
4705
4706 case V_SgVariableDeclaration:
4707 {
4708 SgVariableDeclaration* derivedDeclaration = isSgVariableDeclaration(declaration);
4709 SgInitializedNamePtrList & variableList = derivedDeclaration->get_variables();
4710 SgInitializedNamePtrList::iterator i = variableList.begin();
4711 while ( i != variableList.end() )
4712 {
4714 ROSE_ASSERT(variable != NULL);
4715
4716 // DQ (10/20/2007): static data members declared outside the class scope don't generate symbols.
4717 if (variable->get_scope() == scope)
4718 {
4719 SgSymbol* symbol = new SgVariableSymbol(variable);
4720 ROSE_ASSERT(symbol != NULL);
4721
4722 // printf ("In SageInterface::rebuildSymbolTable() variable = %p building a new SgVariableSymbol = %p \n",variable,symbol);
4723
4724 SgName name = variable->get_name();
4725 symbolTable->insert(name,symbol);
4726 }
4727 else
4728 {
4729 // I think there is nothing to do in this case
4730 // printf ("In SageInterface::rebuildSymbolTable() This variable has a scope inconsistant with the symbol table: variable->get_scope() = %p scope = %p \n",variable->get_scope(),scope);
4731 }
4732
4733 i++;
4734 }
4735
4736 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4737 // that also force symbols to be built in the current scope!
4738 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4739 if (derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4740 {
4741 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4742 ROSE_ASSERT(symbolTable != NULL);
4743 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4744 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4745 }
4746
4747 // ROSE_ASSERT(symbolList.empty() == false);
4748 break;
4749 }
4750
4751 case V_SgTemplateInstantiationDecl:
4752 {
4753 SgTemplateInstantiationDecl* derivedDeclaration = isSgTemplateInstantiationDecl(declaration);
4754#if 1
4755 // printf ("case SgTemplateInstantiationDecl: derivedDeclaration name = %s derivedDeclaration->get_declarationModifier().isFriend() = %s \n",
4756 // derivedDeclaration->get_name().str(),derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4757
4758 if (scope == derivedDeclaration->get_scope())
4759 {
4760 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4761 // printf ("Inserting SgClassSymbol = %p into scope = %p = %s \n",symbol,scope,scope->class_name().c_str());
4762 ROSE_ASSERT(symbol != NULL);
4763 SgName name = derivedDeclaration->get_name();
4764#if 0
4765 // DQ (10/21/2007): The scopes should match
4766 if (scope != derivedDeclaration->get_scope())
4767 {
4768 printf ("Error: scopes don't match for derivedDeclaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4769 }
4770 ROSE_ASSERT(scope == derivedDeclaration->get_scope());
4771#endif
4772 symbolTable->insert(name,symbol);
4773 }
4774 else
4775 {
4776 // printf ("SgTemplateInstantiationDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4777
4778 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4779 {
4780#if PRINT_DEVELOPER_WARNINGS
4781 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4782#endif
4783 }
4784 }
4785#else
4786 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4787 ROSE_ASSERT(symbol != NULL);
4788 SgName name = derivedDeclaration->get_name();
4789 symbolTable->insert(name,symbol);
4790#endif
4791 break;
4792 }
4793
4794
4795 // DQ (12/24/2012): Added support for templates.
4796 case V_SgTemplateClassDeclaration:
4797
4798 case V_SgClassDeclaration:
4799 {
4800 SgClassDeclaration* derivedDeclaration = isSgClassDeclaration(declaration);
4801#if 1
4802 if (scope == derivedDeclaration->get_scope())
4803 {
4804 SgSymbol* symbol = NULL;
4805 if (isSgTemplateClassDeclaration(declaration) != NULL)
4806 symbol = new SgTemplateClassSymbol(derivedDeclaration);
4807 else
4808 symbol = new SgClassSymbol(derivedDeclaration);
4809
4810 ROSE_ASSERT(symbol != NULL);
4811 SgName name = derivedDeclaration->get_name();
4812 symbolTable->insert(name,symbol);
4813 }
4814 else
4815 {
4816 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4817 {
4818#if PRINT_DEVELOPER_WARNINGS
4819 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4820#endif
4821 }
4822 }
4823#else
4824 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4825 ROSE_ASSERT(symbol != NULL);
4826 SgName name = derivedDeclaration->get_name();
4827 symbolTable->insert(name,symbol);
4828#endif
4829 break;
4830 }
4831
4832 case V_SgEnumDeclaration:
4833 {
4834 SgEnumDeclaration* derivedDeclaration = isSgEnumDeclaration(declaration);
4835 ROSE_ASSERT(derivedDeclaration != NULL);
4836 SgSymbol* symbol = new SgEnumSymbol(derivedDeclaration);
4837 ROSE_ASSERT(symbol != NULL);
4838 SgName name = derivedDeclaration->get_name();
4839 symbolTable->insert(name,symbol);
4840
4841 // DQ (10/18/2007): Fixed construction of symbol tabel to include enum fields.
4842 SgInitializedNamePtrList & enumFieldList = derivedDeclaration->get_enumerators();
4843 SgInitializedNamePtrList::iterator i = enumFieldList.begin();
4844
4845 // Iterate over enum fields and add each one to the symbol table.
4846 while (i != enumFieldList.end())
4847 {
4848 SgSymbol* enum_field_symbol = new SgEnumFieldSymbol(*i);
4849 ROSE_ASSERT(enum_field_symbol != NULL);
4850 SgName enum_field_name = (*i)->get_name();
4851 symbolTable->insert(enum_field_name,enum_field_symbol);
4852
4853 i++;
4854 }
4855
4856 break;
4857 }
4858
4859
4860 // DQ (2/18/2017): Added support for C++11 SgTemplateTypedefDeclaration.
4861 case V_SgTemplateTypedefDeclaration:
4862
4863 case V_SgTypedefDeclaration:
4864 {
4865 SgTypedefDeclaration* derivedDeclaration = isSgTypedefDeclaration(declaration);
4866 SgSymbol* symbol = new SgTypedefSymbol(derivedDeclaration);
4867 ROSE_ASSERT(symbol != NULL);
4868 SgName name = derivedDeclaration->get_name();
4869 symbolTable->insert(name,symbol);
4870#if 0
4871 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration \n");
4872#endif
4873 // DQ (10/13/2007): Need to look into typedefs to see if there are defining declaration
4874 // that also force symbols to be built in the current scope!
4875 // ROSE_ASSERT(derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == false);
4876 if (derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == true)
4877 {
4878 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4879 ROSE_ASSERT(symbolTable != NULL);
4880 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4881#if 0
4882 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == true calling supportForBaseTypeDefiningDeclaration() \n");
4883#endif
4884 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4885 }
4886 else
4887 {
4888 // DQ (11/7/2007): If the typedef has a definition (e.g. function pointer) then build a symbol.
4889 SgDeclarationStatement* declaration = derivedDeclaration->get_declaration();
4890 if (declaration != NULL)
4891 {
4892#if 0
4893 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false calling supportForBaseTypeDefiningDeclaration() \n");
4894#endif
4895 // DQ (12/27/2012): Debugging the support for copytest_2007_40_cpp.C (we don't want to build this symbol since it is associated with an outer scope).
4896 // supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_declaration() );
4897
4898 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false: skipping call to supportForBaseTypeDefiningDeclaration() \n");
4899 }
4900 }
4901#if 0
4902 printf ("In SageInterface::rebuildSymbolTable(): Leaving case of SgTypedefDeclaration \n");
4903#endif
4904 break;
4905 }
4906
4907 case V_SgTemplateDeclaration:
4908 {
4909 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4910#if 1
4911 // DQ (10/21/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4912#if 0
4913 printf ("case V_SgTemplateDeclaration: derivedDeclaration = %p \n",derivedDeclaration);
4914 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_declarationModifier().isFriend() = %s \n",derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4915 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_name() = %s \n",derivedDeclaration->get_name().str());
4916 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_string() = %s \n",derivedDeclaration->get_string().str());
4917#endif
4918 if (scope == derivedDeclaration->get_scope())
4919 {
4920 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4921 ROSE_ASSERT(symbol != NULL);
4922 SgName name = derivedDeclaration->get_name();
4923 symbolTable->insert(name,symbol);
4924 }
4925 else
4926 {
4927 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4928 {
4929#if PRINT_DEVELOPER_WARNINGS
4930 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4931#endif
4932 }
4933 }
4934#else
4935 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4936 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4937 ROSE_ASSERT(symbol != NULL);
4938 SgName name = derivedDeclaration->get_name();
4939 symbolTable->insert(name,symbol);
4940#endif
4941 break;
4942 }
4943
4944 // Does this cause a symbol to be built? Seems that it should,
4945 // unless we always reference the non-aliased symbol (reuse it)!
4946 case V_SgNamespaceAliasDeclarationStatement:
4947 {
4948 SgNamespaceAliasDeclarationStatement* aliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
4949 ROSE_ASSERT(aliasDeclaration != NULL);
4950 ROSE_ASSERT(aliasDeclaration->get_namespaceDeclaration() != NULL);
4951
4952 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(aliasDeclaration->get_namespaceDeclaration());
4953 ROSE_ASSERT(derivedDeclaration != NULL);
4954
4955 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4956 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4957 ROSE_ASSERT(symbol != NULL);
4958 SgName name = derivedDeclaration->get_name();
4959 symbolTable->insert(name,symbol);
4960 // symbolList.push_back(symbol);
4961 // ROSE_ASSERT(symbolList.empty() == false);
4962 break;
4963 }
4964
4965 // Does this cause a symbol to be built? Seems that it should,
4966 // unless we always reference the non-aliased symbol (reuse it)!
4967 case V_SgNamespaceDeclarationStatement:
4968 {
4969 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(declaration);
4970 ROSE_ASSERT(derivedDeclaration != NULL);
4971
4972 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4973 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4974 ROSE_ASSERT(symbol != NULL);
4975 SgName name = derivedDeclaration->get_name();
4976 symbolTable->insert(name,symbol);
4977 // symbolList.push_back(symbol);
4978 // ROSE_ASSERT(symbolList.empty() == false);
4979 break;
4980 }
4981
4982 case V_SgUsingDirectiveStatement:
4983 case V_SgPragmaDeclaration:
4984 case V_SgTemplateInstantiationDirectiveStatement:
4985 case V_SgUsingDeclarationStatement:
4986 {
4987 // DQ (10/22/2005): Not sure if we have to worry about this declaration's appearance in the symbol table!
4988#if 0
4989 printf ("This declaration is ignored in rebuilding symbol table %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4990#endif
4991 break;
4992 }
4993
4994 case V_SgAsmStmt:
4995 {
4996 // DQ (8/13/2006): This is not really a declaration (I think). This will be fixed later.
4997#if 0
4998 printf ("An ASM statement (SgAsmStmt) declaration is not really a declaration %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4999#endif
5000 break;
5001 }
5002
5003 // Cases where declations are not used or referenced and so symbols are not required!
5004 case V_SgVariableDefinition:
5005 case V_SgFunctionParameterList:
5006 case V_SgCtorInitializerList:
5007 // These are not referenced so they don't need a symbol!
5008 {
5009 printf ("Special cases not handled %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5010 ROSE_ABORT();
5011 }
5012
5013 case V_SgStaticAssertionDeclaration:
5014 {
5015 // DQ (2/18/2017): This is not really a declaration (I think). This will be fixed later.
5016#if 0
5017 printf ("A static assertion statement (SgStaticAssertionDeclaration) declaration is not really a declaration %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5018#endif
5019 break;
5020 }
5021
5022 default:
5023 {
5024 printf ("Error: Default reached in rebuildSymbolTable declaration = %p = %s \n",declaration,declaration->class_name().c_str());
5025 ROSE_ABORT();
5026 }
5027 }
5028
5029 ROSE_ASSERT(symbolTable != NULL);
5030 ROSE_ASSERT(symbolTable->get_table() != NULL);
5031 }
5032 // printf ("DONE: Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5033
5034 }
5035
5036 ROSE_ASSERT(symbolTable != NULL);
5037 ROSE_ASSERT(symbolTable->get_table() != NULL);
5038
5039#if 0
5040 printf ("Leaving SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
5041#endif
5042
5043#if 0
5044 printf ("Symbol Table from %p = %s at: \n",scope,scope->class_name().c_str());
5045 scope->get_file_info()->display("Symbol Table Location");
5046 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
5047#endif
5048 }
5049
5050
5051// #ifndef USE_ROSE
5052
5053void
5055 {
5056 // This function is called by the SageInterface::rebuildSymbolTable().
5057 // It resets references to old symbols to the new symbols (just built).
5058 // All pairs of old/new symbols are also saved in the object:
5059 // SgCopyHelp::copiedNodeMapType copiedNodeMap
5060
5061#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
5062 ROSE_ASSERT(this_scope != NULL);
5063 ROSE_ASSERT(copy_scope != NULL);
5064
5065#if 0
5066 printf ("In fixupReferencesToSymbols(this_scope = %p = %s = %s, copy_scope = %p = %s = %s) \n",
5067 this_scope,this_scope->class_name().c_str(),get_name(this_scope).c_str(),
5068 copy_scope,copy_scope->class_name().c_str(),get_name(copy_scope).c_str());
5069#endif
5070
5071 SgSymbolTable* this_symbolTable = this_scope->get_symbol_table();
5072 SgSymbolTable* copy_symbolTable = copy_scope->get_symbol_table();
5073#if 0
5074 printf ("Before fixup: this scope = %p = %s this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_scope,this_scope->class_name().c_str(),this_symbolTable->get_table()->size());
5075 printf ("Before fixup: copy scope = %p = %s copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_scope,copy_scope->class_name().c_str(),copy_symbolTable->get_table()->size());
5076#endif
5077
5078 // DQ (3/4/2009): For now just output a warning, but this might be a more serious problem.
5079 // Since the symbol table size of the copy is larger than that of the original it might
5080 // be that a symbol is enterted twice by the copy mechanism. If so I want to fix this.
5081 if (this_symbolTable->get_table()->size() != copy_symbolTable->get_table()->size())
5082 {
5083 if (SgProject::get_verbose() > 0)
5084 {
5085 printf ("Before fixup: this scope = %p = %s this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_scope,this_scope->class_name().c_str(),this_symbolTable->get_table()->size());
5086 printf ("Before fixup: copy scope = %p = %s copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_scope,copy_scope->class_name().c_str(),copy_symbolTable->get_table()->size());
5087 printf ("Warning the symbols tables in these different scopes are different sizes \n");
5088 }
5089 }
5090 // ROSE_ASSERT(this_symbolTable->get_table()->size() <= copy_symbolTable->get_table()->size());
5091
5092 SgSymbolTable::hash_iterator i = this_symbolTable->get_table()->begin();
5093
5094 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
5095 std::map<SgNode*, SgNode*> replacementMap;
5096 int counter = 0;
5097 while (i != this_symbolTable->get_table()->end())
5098 {
5099 ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL );
5100
5101 SgName name = (*i).first;
5102 // SgSymbol* symbol = isSgSymbol((*i).second);
5103 SgSymbol* symbol = (*i).second;
5104 ROSE_ASSERT ( symbol != NULL );
5105
5106 SgSymbol* associated_symbol = NULL;
5107#if 0
5108 printf ("Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) = %p sage_class_name() = %s \n",counter,i->first.str(),i->second,i->second->class_name().c_str());
5109#endif
5110 // Look for the associated symbol in the copy_scope's symbol table.
5111 SgSymbolTable::hash_iterator associated_symbol_iterator = copy_symbolTable->get_table()->find(name);
5112
5113 // Note that this is a multi-map and for C++ a number of symbols can have the same name
5114 // (though not the same type of symbol) so we have to iterator over the symbols of the
5115 // same name so that we can identify the associated symbol.
5116 while (associated_symbol_iterator != copy_symbolTable->get_table()->end() && associated_symbol_iterator->first == name)
5117 {
5118 if ( associated_symbol_iterator->second->variantT() == symbol->variantT() )
5119 {
5120 associated_symbol = associated_symbol_iterator->second;
5121 }
5122
5123 associated_symbol_iterator++;
5124 }
5125
5126 if (associated_symbol != NULL)
5127 {
5128 ROSE_ASSERT ( associated_symbol != NULL );
5129
5130 // Check to make sure that this is correct
5131 ROSE_ASSERT(copy_scope->symbol_exists(associated_symbol) == true);
5132
5133 // Add the SgGlobal referenece to the replacementMap
5134 // replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
5135 // DQ (23/1/2009): Find the reference to symbol and replace it with associated_symbol.
5136 replacementMap.insert(pair<SgNode*,SgNode*>(symbol,associated_symbol));
5137
5138 // DQ (3/1/2009): This is backwards
5139 // replacementMap.insert(pair<SgNode*,SgNode*>(associated_symbol,symbol));
5140
5141 // DQ (3/2/2009): accumulate the symbol pair into the SgCopyHelp object (to support the outliner).
5142 // Actually this should also improve the robustness of the outliner.
5143 help.get_copiedNodeMap().insert(pair<const SgNode*,SgNode*>(symbol,associated_symbol));
5144 }
5145 else
5146 {
5147 // DQ (3/4/2009): This case was broken out because copytest2007_14.C fails here.
5148 if (SgProject::get_verbose() > 0)
5149 {
5150 printf ("Warning: Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) = %p sage_class_name() = %s \n",counter,i->first.str(),i->second,i->second->class_name().c_str());
5151 printf ("Warning: associated_symbol == NULL, need to investigate this (ignoring for now) \n");
5152 }
5153 }
5154
5155 counter++;
5156
5157 i++;
5158 }
5159
5160#if 0
5161 printf ("\n\n************************************************************\n");
5162 printf ("fixupReferencesToSymbols(this_scope = %p copy_scope = %p = %s = %s): calling Utils::edgePointerReplacement() \n",this_scope,copy_scope,copy_scope->class_name().c_str(),get_name(copy_scope).c_str());
5163#endif
5164
5165 Rose::AST::Utility::edgePointerReplacement(copy_scope,replacementMap);
5166
5167#if 0
5168 printf ("fixupReferencesToSymbols(): calling Utils::edgePointerReplacement(): DONE \n");
5169 printf ("************************************************************\n\n");
5170
5171 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
5172 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
5173
5174 printf ("After fixup: this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_symbolTable->get_table()->size());
5175 printf ("After fixup: copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_symbolTable->get_table()->size());
5176#endif
5177
5178 // DQ (3/1/2009): find a case where this code is tested.
5179 // ROSE_ASSERT(this_symbolTable->get_table()->size() == 0);
5180 // ROSE_ASSERT(isSgClassDefinition(copy_scope) == NULL);
5181#endif
5182
5183#if 0
5184 printf ("Exiting as a test in fixupReferencesToSymbols() \n");
5185 ROSE_ABORT();
5186#endif
5187 }
5188
5189// #endif
5190
5191#ifndef USE_ROSE
5192
5193std::vector<SgFile*>
5195 {
5196 // This function uses a memory pool traversal specific to the SgFile IR nodes
5197 class FileTraversal : public ROSE_VisitTraversal
5198 {
5199 public:
5200 vector<SgFile*> fileList;
5201 void visit ( SgNode* node)
5202 {
5203 SgFile* file = isSgFile(node);
5204 ROSE_ASSERT(file != NULL);
5205 if (file != NULL)
5206 {
5207 fileList.push_back(file);
5208 }
5209 };
5210
5211 virtual ~FileTraversal() {}
5212 };
5213
5214 FileTraversal fileTraversal;
5215
5216 // traverse just the SgFile nodes (both the SgSourceFile and SgBinaryComposite IR nodes)!
5217 // SgFile::visitRepresentativeNode(fileTraversal);
5219#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5221#endif
5222
5223 // This would alternatively traverse all IR nodes in thememory pool!
5224 // fileTraversal.traverseMemoryPool();
5225
5226 // TV (06/24/2013): This fail when calling SageBuilder::buildVariableDeclaration(...) without any file created.
5227 // DQ (10/11/2014): This is allowed to be empty (required for new aterm support).
5228 // ROSE_ASSERT(fileTraversal.fileList.empty() == false);
5229
5230 return fileTraversal.fileList;
5231 }
5232
5233#endif
5234
5235// #ifndef USE_ROSE
5236
5237// DQ (4/17/2015): I think this function should be removed since it interferes
5238// with the concept of having more than one SgProject node.
5239// This function uses a memory pool traversal specific to the SgProject IR nodes
5240SgProject*
5242{
5243#if 0
5244 class ProjectTraversal : public ROSE_VisitTraversal
5245 {
5246 public:
5247 SgProject * project;
5248 void visit ( SgNode* node)
5249 {
5250 project = isSgProject(node);
5251 ROSE_ASSERT(project!= NULL);
5252 };
5253 virtual ~ProjectTraversal() {}
5254 };
5255
5256 ProjectTraversal projectTraversal;
5257 SgProject::visitRepresentativeNode(projectTraversal);
5258 return projectTraversal.project;
5259#endif
5260 std::vector<SgProject* > resultlist = getSgNodeListFromMemoryPool<SgProject>();
5261 if (resultlist.empty())
5262 return NULL;
5263 ROSE_ASSERT(resultlist.size()==1);
5264 return resultlist[0];
5265}
5266
5267SgProject*
5269 return getEnclosingNode<SgProject>(node, true /*includingSelf*/);
5270}
5271
5273 SgFunctionDeclaration * ret = NULL;
5274 if (isSgFunctionRefExp(func))
5275 {
5276 return isSgFunctionRefExp(func)->get_symbol()->get_declaration();
5277 }
5278 else if (isSgDotExp(func) || isSgArrowExp(func))
5279 {
5280 SgExpression* func2 = isSgBinaryOp(func)->get_rhs_operand();
5281 if (isSgMemberFunctionRefExp(func2))
5282 return isSgMemberFunctionRefExp(func2)->get_symbol()->get_declaration();
5283 else
5284 {
5285 cerr<<"Warning in SageInterface::getDeclarationOfNamedFunction(): rhs operand of dot or arrow operations is not a member function, but a "<<func2->class_name()<<endl;
5286 }
5287 }
5288
5289 return ret;
5290}
5291
5293 SgExprListExp* el = stmt->get_forall_header();
5294 const SgExpressionPtrList& ls = el->get_expressions();
5295 if (ls.empty()) return 0;
5296 if (isSgAssignOp(ls.back())) return 0;
5297 return ls.back();
5298}
5299
5300//Find all SgPntrArrRefExp under astNode, add the referenced dim_info SgVarRefExp (if any) into NodeList_t
5301void SageInterface::addVarRefExpFromArrayDimInfo(SgNode * astNode, Rose_STL_Container<SgNode *>& NodeList_t)
5302{
5303 ASSERT_not_null(astNode);
5304 Rose_STL_Container<SgNode*> arr_exp_list = NodeQuery::querySubTree(astNode,V_SgPntrArrRefExp);
5305 for (SgNode* expr : arr_exp_list)
5306 {
5307 SgPntrArrRefExp* arr_exp = isSgPntrArrRefExp(expr);
5308 ASSERT_not_null(arr_exp);
5309 Rose_STL_Container<SgNode*> refList = NodeQuery::querySubTree(arr_exp->get_lhs_operand(),V_SgVarRefExp);
5310 for (SgNode* ref : refList)
5311 {
5312 SgVarRefExp* cur_ref = isSgVarRefExp(ref);
5313 ASSERT_not_null(cur_ref);
5314 SgVariableSymbol * sym = cur_ref->get_symbol();
5315 ASSERT_not_null(sym);
5316 SgInitializedName * iname = sym->get_declaration();
5317 ASSERT_not_null(iname);
5318 SgArrayType * a_type = isSgArrayType(iname->get_typeptr());
5319 if (a_type && a_type->get_dim_info())
5320 {
5321 Rose_STL_Container<SgNode*> dim_ref_list = NodeQuery::querySubTree(a_type->get_dim_info(),V_SgVarRefExp);
5322 for (Rose_STL_Container<SgNode*>::iterator iter2 = dim_ref_list.begin(); iter2 != dim_ref_list.end(); iter2++)
5323 {
5324 SgVarRefExp* dim_ref = isSgVarRefExp(*iter2);
5325 NodeList_t.push_back(dim_ref);
5326 }
5327 }
5328 }
5329 } // end for
5330}
5331
5332
5333// DQ (11/25/2020): This disables these non-inlined functions in favor of
5334// inlined versions of the functions in the sageInterface.h (header file).
5335#if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5336bool
5338 {
5339#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5340 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5341 return Rose::is_Ada_language;
5342#else
5343 bool returnValue = false;
5344
5345 vector<SgFile*> fileList = generateFileList();
5346
5347 int size = (int)fileList.size();
5348 for (int i = 0; i < size; i++)
5349 {
5350 if (fileList[i]->get_Ada_only() == true)
5351 returnValue = true;
5352 }
5353
5354 return returnValue;
5355#endif
5356 }
5357
5358bool
5360 {
5361#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5362 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5363 return Rose::is_C_language;
5364#else
5365 bool returnValue = false;
5366
5367 vector<SgFile*> fileList = generateFileList();
5368
5369 int size = (int)fileList.size();
5370 for (int i = 0; i < size; i++)
5371 {
5372 if (fileList[i]->get_C_only() == true)
5373 returnValue = true;
5374 }
5375
5376 return returnValue;
5377#endif
5378 }
5379
5380bool
5382 {
5383#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5384 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5385 return Rose::is_OpenMP_language;
5386#else
5387 bool returnValue = false;
5388
5389 vector<SgFile*> fileList = generateFileList();
5390
5391 int size = (int)fileList.size();
5392 for (int i = 0; i < size; i++)
5393 {
5394 if (fileList[i]->get_openmp() == true)
5395 returnValue = true;
5396 }
5397
5398 return returnValue;
5399#endif
5400 }
5401
5402bool
5404 {
5405#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5406 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5407 return Rose::is_UPC_language;
5408#else
5409 bool returnValue = false;
5410
5411 vector<SgFile*> fileList = generateFileList();
5412
5413 int size = (int)fileList.size();
5414 for (int i = 0; i < size; i++)
5415 {
5416 if (fileList[i]->get_UPC_only() == true)
5417 returnValue = true;
5418 }
5419
5420 return returnValue;
5421#endif
5422 }
5423
5424//FMZ
5425bool
5427 {
5428#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5429 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5430 return Rose::is_CAF_language;
5431#else
5432 bool returnValue = false;
5433
5434 vector<SgFile*> fileList = generateFileList();
5435
5436 int size = (int)fileList.size();
5437 for (int i = 0; i < size; i++)
5438 {
5439 if (fileList[i]->get_CoArrayFortran_only()==true)
5440 returnValue = true;
5441 }
5442
5443 return returnValue;
5444#endif
5445 }
5446
5447
5448// true if any of upc_threads is set to >0 via command line: -rose:upc_threads n
5449bool
5451 {
5452#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5453 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5454 return Rose::is_UPC_dynamic_threads;
5455#else
5456 bool returnValue = false;
5457
5458 vector<SgFile*> fileList = generateFileList();
5459
5460 int size = (int)fileList.size();
5461 for (int i = 0; i < size; i++)
5462 {
5463 if (fileList[i]->get_upc_threads() > 0)
5464 returnValue = true;
5465 }
5466
5467 return returnValue;
5468#endif
5469 }
5470
5471
5472
5473bool
5475 {
5476#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5477 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5478 return Rose::is_C99_language;
5479#else
5480 bool returnValue = false;
5481
5482 vector<SgFile*> fileList = generateFileList();
5483
5484 int size = (int)fileList.size();
5485 for (int i = 0; i < size; i++)
5486 {
5487 if (fileList[i]->get_C99_only() == true)
5488 returnValue = true;
5489 }
5490
5491 return returnValue;
5492#endif
5493 }
5494
5495bool
5497 {
5498#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5499 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5500 return Rose::is_Cxx_language;
5501#else
5502 bool returnValue = false;
5503
5504 vector<SgFile*> fileList = generateFileList();
5505
5506 int size = (int)fileList.size();
5507 for (int i = 0; i < size; i++)
5508 {
5509 // DQ (8/19/2007): Make sure this is not a Fortran code!
5510 if (fileList[i]->get_Cxx_only() == true)
5511 {
5512 ROSE_ASSERT(fileList[i]->get_Fortran_only() == false && fileList[i]->get_C99_only() == false && fileList[i]->get_C_only() == false && fileList[i]->get_binary_only() == false);
5513
5514 returnValue = true;
5515 }
5516 }
5517
5518 return returnValue;
5519#endif
5520 }
5521
5522bool
5524 {
5525#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5526 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5527 return Rose::is_Java_language;
5528#else
5529 bool returnValue = false;
5530
5531 vector<SgFile*> fileList = generateFileList();
5532
5533 int size = (int)fileList.size();
5534 for (int i = 0; i < size; i++)
5535 {
5536 if (fileList[i]->get_Java_only() == true)
5537 returnValue = true;
5538 }
5539
5540 return returnValue;
5541#endif
5542 }
5543
5544bool
5546 {
5547#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5548 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5549 return Rose::is_Jvm_language;
5550#else
5551 bool returnValue = false;
5552
5553 vector<SgFile*> fileList = generateFileList();
5554
5555 int size = (int)fileList.size();
5556 for (int i = 0; i < size; i++)
5557 {
5558 if (fileList[i]->get_Jvm_only() == true)
5559 returnValue = true;
5560 }
5561
5562 return returnValue;
5563#endif
5564 }
5565
5566// Rasmussen (4/4/2018): Added Jovial
5567bool
5569 {
5570#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5571 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5572 return Rose::is_Jovial_language;
5573#else
5574 bool returnValue = false;
5575
5576 vector<SgFile*> fileList = generateFileList();
5577
5578 int size = (int)fileList.size();
5579 for (int i = 0; i < size; i++)
5580 {
5581 if (fileList[i]->get_Jovial_only() == true)
5582 returnValue = true;
5583 }
5584
5585 return returnValue;
5586#endif
5587 }
5588
5589
5590bool
5592 {
5593#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5594 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5595 return Rose::is_Fortran_language;
5596#else
5597 bool returnValue = false;
5598
5599 vector<SgFile*> fileList = generateFileList();
5600
5601 int size = (int)fileList.size();
5602 for (int i = 0; i < size; i++)
5603 {
5604 if (fileList[i]->get_Fortran_only() == true)
5605 returnValue = true;
5606 }
5607
5608 return returnValue;
5609#endif
5610 }
5611
5612
5613bool
5615 {
5616#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5617 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5618 return Rose::is_binary_executable;
5619#else
5620 bool returnValue = false;
5621
5622 vector<SgFile*> fileList = generateFileList();
5623
5624 int size = (int)fileList.size();
5625 for (int i = 0; i < size; i++)
5626 {
5627 if (fileList[i]->get_binary_only() == true)
5628 returnValue = true;
5629 }
5630
5631 return returnValue;
5632#endif
5633 }
5634
5635bool
5637 {
5638#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5639 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5640 return Rose::is_PHP_language;
5641#else
5642 bool returnValue = false;
5643
5644 vector<SgFile*> fileList = generateFileList();
5645
5646 int size = (int)fileList.size();
5647 for (int i = 0; i < size; i++)
5648 {
5649 if (fileList[i]->get_PHP_only() == true)
5650 returnValue = true;
5651 }
5652
5653 return returnValue;
5654#endif
5655 }
5656
5657bool
5659 {
5660#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5661 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5662 return Rose::is_Python_language;
5663#else
5664 bool returnValue = false;
5665
5666 vector<SgFile*> fileList = generateFileList();
5667
5668 int size = (int)fileList.size();
5669 for (int i = 0; i < size; i++)
5670 {
5671 if (fileList[i]->get_Python_only() == true)
5672 returnValue = true;
5673 }
5674
5675 return returnValue;
5676#endif
5677 }
5678
5679bool
5681 {
5682#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5683 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5684 return Rose::is_Cuda_language;
5685#else
5686 bool returnValue = false;
5687
5688 vector<SgFile*> fileList = generateFileList();
5689
5690 int size = (int)fileList.size();
5691 for (int i = 0; i < size; i++)
5692 {
5693 if (fileList[i]->get_Cuda_only() == true)
5694 returnValue = true;
5695 }
5696
5697 return returnValue;
5698#endif
5699 }
5700
5701bool
5703 {
5704#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5705 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5706 return Rose::is_OpenCL_language;
5707#else
5708 bool returnValue = false;
5709
5710 vector<SgFile*> fileList = generateFileList();
5711
5712 int size = (int)fileList.size();
5713 for (int i = 0; i < size; i++)
5714 {
5715 if (fileList[i]->get_OpenCL_only() == true)
5716 returnValue = true;
5717 }
5718
5719 return returnValue;
5720#endif
5721 }
5722
5723// for if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5724#endif
5725
5730
5735
5740
5745
5750
5751// Languages that may have scopes that contain statements that are not only declarations.
5752// For Fortran and Jovial (at least), function definitions may be declared at the end of procedures.
5757
5758// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5759// labels for scopes in a function (as required for name mangling).
5760void
5762 {
5763 ASSERT_not_null(functionDefinition);
5764 std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5765
5766 // Clear the cache of stored (scope,integer) pairs
5767 scopeMap.erase(scopeMap.begin(),scopeMap.end());
5768
5769 ASSERT_require(scopeMap.empty() == true);
5770 ASSERT_require(functionDefinition->get_scope_number_list().empty() == true);
5771 }
5772
5773#ifndef USE_ROSE
5774
5775// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5776// labels for scopes in a function (as required for name mangling).
5777void
5779 {
5780 ROSE_ASSERT(functionDefinition != NULL);
5781 // std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5782 // ROSE_ASSERT(scopeMap.empty() == true);
5783 ROSE_ASSERT(functionDefinition->get_scope_number_list().empty() == true);
5784
5785 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5786 class ScopeNumberingTraversal : public AstSimpleProcessing
5787 {
5788 public:
5789 ScopeNumberingTraversal() : count (0), storedFunctionDefinition(NULL) {}
5790 void visit (SgNode* node)
5791 {
5792 SgScopeStatement* scope = isSgScopeStatement (node);
5793 if (scope != NULL)
5794 {
5795 // Set the function definition
5796 SgFunctionDefinition* testFunctionDefinition = isSgFunctionDefinition(scope);
5797 if (testFunctionDefinition != NULL && storedFunctionDefinition == NULL)
5798 {
5799 ROSE_ASSERT(storedFunctionDefinition == NULL);
5800 storedFunctionDefinition = testFunctionDefinition;
5801 }
5802
5803 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5804 ROSE_ASSERT(storedFunctionDefinition != NULL);
5805
5806 count++;
5807
5808 std::map<SgNode*,int> & scopeMap = storedFunctionDefinition->get_scope_number_list();
5809 scopeMap.insert(pair<SgNode*,int>(scope,count));
5810#if 0
5811 string functionName = storedFunctionDefinition->get_declaration()->get_name().str();
5812 printf ("In function = %s insert scope = %p = %s with count = %d into local map (size = %d) \n",
5813 functionName.c_str(),scope,scope->class_name().c_str(),count,scopeMap.size());
5814#endif
5815 }
5816 }
5817
5818 private:
5819 int count; // running total of scopes found in the input function
5820 SgFunctionDefinition* storedFunctionDefinition;
5821 };
5822
5823 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5824 ScopeNumberingTraversal traversal;
5825 traversal.traverse(functionDefinition, preorder);
5826 }
5827
5828#endif
5829
5830#ifndef USE_ROSE
5831
5832#if 0
5833// DQ (6/26/2007): These are removed and the support is added to SgNode to support a single mangled name cache.
5834// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5835// labels for scopes in a function (as required for name mangling).
5836void
5838 {
5839 ROSE_ASSERT(globalScope != NULL);
5840 std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5841
5842 // Clear the cache of stored (scope,integer) pairs
5843 mangledNameCache.erase(mangledNameCache.begin(),mangledNameCache.end());
5844
5845 ROSE_ASSERT(mangledNameCache.empty() == true);
5846 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5847 }
5848
5849// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5850// labels for scopes in a function (as required for name mangling).
5851void
5853 {
5854 ROSE_ASSERT(globalScope != NULL);
5855 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5856
5857 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5858 class MangledNameTraversal : public AstSimpleProcessing
5859 {
5860 public:
5861 MangledNameTraversal() : storedGlobalScope(NULL) {}
5862 void visit (SgNode* node)
5863 {
5864 SgFunctionDeclaration* mangleableNode = isSgFunctionDeclaration(node);
5865 if ( (mangleableNode != NULL) || (isSgGlobal(node) != NULL) )
5866 {
5867 // Set the global scope
5868 SgGlobal* testGlobalScope = isSgGlobal(mangleableNode);
5869 if (testGlobalScope != NULL && storedGlobalScope == NULL)
5870 {
5871 ROSE_ASSERT(storedGlobalScope == NULL);
5872 storedGlobalScope = testGlobalScope;
5873 }
5874
5875 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5876 ROSE_ASSERT(storedGlobalScope != NULL);
5877
5878 string mangledName = mangleableNode->get_mangled_name();
5879 // printf ("mangledName = %s \n",mangledName.c_str());
5880
5881 std::map<SgNode*,std::string> & mangledNameCache = storedGlobalScope->get_mangledNameCache();
5882 mangledNameCache.insert(pair<SgNode*,std::string>(mangleableNode,mangledName));
5883#if 0
5884 string nodeName = get_name(mangleableNode);
5885 printf ("At node = %p = %s = %s in local map (size = %d) \n",
5886 mangleableNode,mangleableNode->class_name().c_str(),nodeName.c_str(),mangledNameCache.size());
5887#endif
5888 }
5889 }
5890
5891 private:
5892 SgGlobal* storedGlobalScope;
5893 };
5894
5895 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5896 MangledNameTraversal traversal;
5897 traversal.traverse(globalScope, preorder);
5898 }
5899#endif
5900
5901
5902string
5904 {
5905 // The TransformationSupport is not defined yet (I forget the
5906 // details but I recall that there is a reason why this is this way).
5907 // SgGlobal* globalScope = TransformationSupport::getGlobalScope(astNode);
5908#if 0
5909 SgGlobal* globalScope = isSgGlobal(astNode);
5910
5911 if (globalScope == NULL && isSgFile(astNode) != NULL)
5912 {
5913 globalScope = isSgFile(astNode)->get_globalScope();
5914 ROSE_ASSERT(globalScope != NULL);
5915 }
5916
5917 if (globalScope == NULL && isSgProject(astNode) != NULL)
5918 {
5919 // Check to make sure that the SgFile can be uniquely determined
5920 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5921 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5922 ROSE_ASSERT(globalScope != NULL);
5923 }
5924
5925 SgNode* temp = astNode;
5926 while (temp->get_parent() != NULL && globalScope == NULL)
5927 {
5928 temp = temp->get_parent();
5929 globalScope = isSgGlobal(temp);
5930 }
5931 ROSE_ASSERT(globalScope != NULL);
5932#endif
5933
5934 // std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5935 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
5936
5937 // Build an iterator
5938 std::map<SgNode*,std::string>::iterator i = mangledNameCache.find(astNode);
5939
5940 string mangledName;
5941 if (i != mangledNameCache.end())
5942 {
5943 // get the precomputed mangled name!
5944 //~ printf ("Mangled name IS found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5945 mangledName = i->second;
5946 }
5947 else
5948 {
5949 // mangled name not found in cache!
5950 //~ printf ("Mangled name NOT found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5951 }
5952
5953 return mangledName;
5954 }
5955
5956#define DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE 0
5957#define DEBUG_MANGLED_SHORTNAME 1
5958
5959//#ifdef DEBUG_MANGLED_SHORTNAME
5960//std::unordered_map<uint64_t, std::string> SageInterface::mangledNameHashCollisionCheckMap;
5961//#endif
5962
5963std::string
5964SageInterface::addMangledNameToCache( SgNode* astNode, const std::string & oldMangledName)
5965 {
5966#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
5967 printf ("In SageInterface::addMangledNameToCache(): TOP: astNode = %p = %s oldMangledName = %s \n",astNode,astNode->class_name().c_str(),oldMangledName.c_str());
5968#endif
5969
5970//#define DEBUG_MANGLED_SHORTNAME 1
5971#ifdef DEBUG_MANGLED_SHORTNAME
5972 static std::unordered_map<uint64_t, std::string> mangledNameHashCollisionCheckMap;
5973#endif
5974
5975
5976#if 0
5977 SgGlobal* globalScope = isSgGlobal(astNode);
5978
5979 if (globalScope == NULL && isSgFile(astNode) != NULL)
5980 {
5981 globalScope = isSgFile(astNode)->get_globalScope();
5982 ROSE_ASSERT(globalScope != NULL);
5983 }
5984
5985 if (globalScope == NULL && isSgProject(astNode) != NULL)
5986 {
5987 // Check to make sure that the SgFile can be uniquely determined
5988 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5989 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5990 ROSE_ASSERT(globalScope != NULL);
5991 }
5992
5993 SgNode* temp = astNode;
5994 while (temp->get_parent() != NULL && globalScope == NULL)
5995 {
5996 temp = temp->get_parent();
5997 globalScope = isSgGlobal(temp);
5998 }
5999 ROSE_ASSERT(globalScope != NULL);
6000#endif
6001
6002 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
6003
6004 std::string mangledName;
6005
6006 if (SgProject::get_mangled_noshortname() == false) {
6007 std::map<std::string, uint64_t> & shortMangledNameCache = SgNode::get_shortMangledNameCache();
6008
6009 if (oldMangledName.size() > 40) {
6010 std::map<std::string, uint64_t>::const_iterator shortMNIter = shortMangledNameCache.find(oldMangledName);
6011 uint64_t idNumber = 0;
6012 if (shortMNIter != shortMangledNameCache.end())
6013 {
6014 idNumber = shortMNIter->second;
6015
6016#ifdef DEBUG_MANGLED_SHORTNAME
6017 //Check for hash colisions, if we found an idNumber, but the long mangled name is different, we have a problem
6018 auto collisionIt = mangledNameHashCollisionCheckMap.find(idNumber);
6019 if(collisionIt != mangledNameHashCollisionCheckMap.end() &&
6020 oldMangledName != shortMNIter->first)
6021 {
6022 mlog[Sawyer::Message::Common::ERROR] <<" Got a short mangled name collision. \n "<<
6023 oldMangledName << " and \n " << shortMNIter->first << " \n" <<
6024 "have the same idNumber of: " << Combinatorics::toBase62String(idNumber) << " " << shortMNIter->second << endl;
6025 exit(12);
6026 } else {
6027 mangledNameHashCollisionCheckMap[idNumber] = oldMangledName;
6028 }
6029#endif //DEBUG_MANGLED_SHORTNAME
6030
6031 }
6032 else
6033 {
6035 hasher.insert(oldMangledName);
6036 hasher.digest();
6037 idNumber = hasher.make64Bits();
6038 shortMangledNameCache.insert(std::pair<std::string, uint64_t>(oldMangledName, idNumber));
6039 }
6040
6041 std::ostringstream mn;
6042 mn << 'L' << Combinatorics::toBase62String(idNumber) << 'R';
6043 mangledName = mn.str();
6044 } else {
6045 mangledName = oldMangledName;
6046 }
6047 } else {
6048
6049 // DQ (7/24/2012): Note that using this option can cause some test codes using operators that have
6050 // difficult names (conversion operators to user-defined types) to fail. See test2004_141.C for example.
6051 // The conversion operator "operator T&() const;" will fail because the character "&" will remain in
6052 // mangled name. The substring coding changes the strings for the mangled names and this effectively
6053 // removes the special characters, but there could be cases where they might remain.
6054
6055 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
6056 static unsigned long counter = 0;
6057
6058 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
6059 // This supports debugging the new EDG 4.x interface...
6060 if (counter++ % 500 == 0)
6061 {
6062 printf ("WARNING: In SageInterface::addMangledNameToCache(): Using longer forms of mangled names (can cause some function names with embedded special characters to fail; test2004_141.C) \n");
6063 }
6064 mangledName = oldMangledName;
6065}
6066
6067 // DQ (6/26/2007): Output information useful for understanding Jeremiah's shortended name merge caching.
6068 // std::cerr << "Changed MN " << oldMangledName << " to " << mangledName << std::endl;
6069
6070#if 0
6071 printf ("Updating mangled name cache for node = %p = %s with mangledName = %s \n",astNode,astNode->class_name().c_str(),mangledName.c_str());
6072#endif
6073
6074#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
6075 SgStatement* statement = isSgStatement(astNode);
6076 if (statement != NULL && statement->hasExplicitScope() == true)
6077 {
6078 if (statement->get_scope() == NULL)
6079 {
6080 printf ("Warning: SageInterface::addMangledNameToCache(): In it might be premature to add this IR node and name to the mangledNameCache: statement = %p = %s oldMangledName = %s \n",
6081 statement,statement->class_name().c_str(),oldMangledName.c_str());
6082 }
6083 }
6084#endif
6085
6086 mangledNameCache.insert(pair<SgNode*,string>(astNode,mangledName));
6087
6088#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
6089 printf ("In SageInterface::addMangledNameToCache(): returning mangledName = %s \n",mangledName.c_str());
6090#endif
6091
6092 return mangledName;
6093 }
6094
6095
6096// #endif
6097
6098#ifndef USE_ROSE
6099
6100bool
6102 {
6103 // This function is used in the unparser, but might be more generally useful. Since it is
6104 // related to general AST tests, I have put it here. It might be alternatively put in the
6105 // src/backend/unparser or related utility directory.
6106
6107 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6108 // declarations in the preorder traversal of the AST.
6109 class DeclarationOrderTraversal : public AstSimpleProcessing
6110 {
6111 public:
6112 DeclarationOrderTraversal( SgDeclarationStatement* nonDefiningDeclaration, SgDeclarationStatement* definingDeclaration )
6113 : storedNondefiningDeclaration(nonDefiningDeclaration),
6114 storedDefiningDeclaration(definingDeclaration)
6115 {
6116 storedDeclarationFound = false;
6117 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6118 }
6119
6120 void visit (SgNode* node)
6121 {
6122 ROSE_ASSERT(storedNondefiningDeclaration != NULL);
6123 ROSE_ASSERT(storedDefiningDeclaration != NULL);
6124 ROSE_ASSERT(storedNondefiningDeclaration != storedDefiningDeclaration);
6125 // ROSE_ASSERT(storedNondefiningDeclaration->get_definingDeclaration() == storedDefiningDeclaration);
6126
6127 // Even though we only care about the SgClassDeclaration IR nodes we have to traverse them
6128 // in the AST in the order defined by the traversal (order of apprearance in the AST). We
6129 // also can't just search the declarations of a single scope (since the nondefining declaration
6130 // can appear in a different scope than the defining declaration).
6131 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6132 if ( declaration != NULL )
6133 {
6134 if (storedDeclarationFound == false)
6135 {
6136 if (declaration == storedDefiningDeclaration)
6137 {
6138 storedDeclarationFound = true;
6139 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6140 }
6141 if (declaration == storedNondefiningDeclaration)
6142 {
6143 storedDeclarationFound = true;
6144 nonDefiningDeclarationPreceedsDefiningDeclaration = true;
6145 }
6146 }
6147 }
6148 }
6149
6150 public:
6151 bool storedDeclarationFound;
6152 bool nonDefiningDeclarationPreceedsDefiningDeclaration;
6153
6154 private:
6155 SgDeclarationStatement* storedNondefiningDeclaration;
6156 SgDeclarationStatement* storedDefiningDeclaration;
6157 };
6158
6159 ROSE_ASSERT(nonDefiningDeclaration != NULL);
6160#if 0
6161 printf ("In SageInterface::declarationPreceedsDefinition(): \n");
6162 printf (" nondefiningDeclaration = %p = %s \n",nonDefiningDeclaration,nonDefiningDeclaration->class_name().c_str());
6163 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6164 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6165 printf (" definingDeclaration = %p = %s \n",definingDeclaration,definingDeclaration->class_name().c_str());
6166 definingDeclaration->get_file_info()->display("definingDeclaration");
6167 printf ("************************************************************* \n");
6168#endif
6169
6170#if 0
6171 // The nonDefiningDeclaration can be a different type of declaration than the definingDeclaration
6172 if (nonDefiningDeclaration->get_definingDeclaration() != definingDeclaration)
6173 {
6174 printf ("In SageInterface::declarationPreceedsDefinition() (warning): \n");
6175 printf (" nondefiningDeclaration = %p \n",nonDefiningDeclaration);
6176 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6177 printf (" definingDeclaration = %p \n",definingDeclaration);
6178 }
6179#endif
6180
6181 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6182 bool returnResult = false;
6183 if (nonDefiningDeclaration != definingDeclaration)
6184 {
6185 // Get the global scope from a traversal back (up) through the AST.
6186 SgGlobal* globalScope = TransformationSupport::getGlobalScope(definingDeclaration);
6187 ROSE_ASSERT(globalScope != NULL);
6188
6189 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6190 DeclarationOrderTraversal traversal (nonDefiningDeclaration,definingDeclaration);
6191
6192#if 0
6193 traversal.traverse(globalScope, preorder);
6194#else
6195 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6196 printf ("Skipping traversal within SageInterface::declarationPreceedsDefinition() \n");
6197 traversal.storedDeclarationFound = true;
6198 traversal.nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6199#endif
6200
6201 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6202 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6203 // nondefining declarations that are not in the traversal).
6204
6205 if (traversal.storedDeclarationFound == false)
6206 {
6207#if 0
6208 printf ("In SageInterface::declarationPreceedsDefinition(): warning, nonDefiningDeclaration not found in the AST \n");
6209 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6210 definingDeclaration->get_file_info()->display("definingDeclaration");
6211 printf ("---------------------------------------------------- \n\n");
6212#endif
6213 // Set this error case to return true so that we will not assume incorrectly
6214 // that the classNonDefiningDeclaration apears after the classDefiningDeclaration.
6215 returnResult = true;
6216 }
6217 else
6218 {
6219 returnResult = traversal.nonDefiningDeclarationPreceedsDefiningDeclaration;
6220 }
6221
6222 // ROSE_ASSERT(traversal.storedDeclarationFound == true);
6223 }
6224#if 0
6225 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6226 printf ("************************************************************* \n\n");
6227#endif
6228 return returnResult;
6229 }
6230
6231
6232bool
6234 {
6235 // This function is used in the unparser, but might be more generally useful. Since it is
6236 // related to general AST tests, I have put it here. It might be alternatively put in the
6237 // src/backend/unparser or related utility directory.
6238
6239 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6240 // declarations in the preorder traversal of the AST.
6241 class DeclarationOrderTraversal : public AstSimpleProcessing
6242 {
6243 public:
6244 DeclarationOrderTraversal( SgFunctionCallExp* functionCall )
6245 : storedFunctionCall(functionCall)
6246 {
6247 ROSE_ASSERT(functionCall != NULL);
6248 ROSE_ASSERT(functionCall->get_function() != NULL);
6249 SgExpression* functionExpression = functionCall->get_function();
6250
6251 switch (functionExpression->variantT())
6252 {
6253 // these are the acceptable cases
6254 case V_SgDotExp:
6255 case V_SgDotStarOp:
6256 case V_SgArrowExp:
6257 case V_SgArrowStarOp:
6258 case V_SgPointerDerefExp:
6259 {
6260 // These are the acceptable cases, but not handled yet.
6261 printf ("These are the acceptable cases, but not handled yet... \n");
6262 ROSE_ABORT();
6263 }
6264
6265 case V_SgFunctionRefExp:
6266 {
6267 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionExpression);
6268 ROSE_ASSERT(functionRefExp != NULL);
6269 SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol();
6270 ROSE_ASSERT(functionSymbol != NULL);
6271
6272 // Make sure that the function has a valid declaration
6273 ROSE_ASSERT(functionSymbol->get_declaration() != NULL);
6274 storedFunctionDeclaration = functionSymbol->get_declaration();
6275 break;
6276 }
6277
6278 case V_SgMemberFunctionRefExp:
6279 {
6280 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(functionExpression);
6281 ROSE_ASSERT(memberFunctionRefExp != NULL);
6282 SgMemberFunctionSymbol* memberFunctionSymbol = memberFunctionRefExp->get_symbol();
6283 ROSE_ASSERT(memberFunctionSymbol != NULL);
6284
6285 storedFunctionDeclaration = memberFunctionSymbol->get_declaration();
6286
6287 printf ("V_SgMemberFunctionRefExp case not handled yet... \n");
6288 ROSE_ABORT();
6289 }
6290
6291 default:
6292 {
6293 printf ("default reached in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() functionExpression = %s \n",
6294 functionExpression->class_name().c_str());
6295 ROSE_ABORT();
6296 }
6297 }
6298 // ROSE_ASSERT(functionCall->get_declaration() != NULL);
6299 // ROSE_ASSERT(functionCall->get_function()->get_firstNondefiningDeclaration() != NULL);
6300 // storedFunctionDeclaration = functionCall->get_declaration()->get_firstNondefiningDeclaration();
6301 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6302
6303 storedFunctionCallFound = false;
6305 }
6306
6307 void visit (SgNode* node)
6308 {
6309 ROSE_ASSERT(storedFunctionCall != NULL);
6310 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6311 // ROSE_ASSERT(storedFunctionCall != storedFunctionDeclaration);
6312
6313 if (storedFunctionCallFound == false)
6314 {
6315 SgFunctionCallExp* functionCall = isSgFunctionCallExp(node);
6316 if ( functionCall != NULL )
6317 {
6318 if (functionCall == storedFunctionCall)
6319 {
6320 storedFunctionCallFound = true;
6321
6322 // A declaration for the function in a scope where the function could be defined
6323 // (and a scope associated with it) has not been found so the function call
6324 // preceeds such a declaration (if it even exists).
6326 }
6327 }
6328
6329 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6330 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6331
6332 // Note that all firstNondefiningDeclaration are set to the same declaration (for all associated declarations).
6333 // Need to check the result of get_firstNondefiningDeclaration() since this will be the same for all declarations
6334 // of the same function and thus can be used to match that we have an associated declaration for the same function.
6335 if ( declaration != NULL && declaration->get_firstNondefiningDeclaration() == storedFunctionDeclaration->get_firstNondefiningDeclaration())
6336 {
6337 // Test if this is a declaration is a scope where the existance of the forward
6338 // declaration will define the scope fo the function declaration.
6339 SgScopeStatement* parentScopeOfDeclaration = isSgScopeStatement(declaration->get_parent());
6340 if (parentScopeOfDeclaration != NULL && parentScopeOfDeclaration->supportsDefiningFunctionDeclaration() == true)
6341 {
6342 // We are done so we can skip further testing
6343 storedFunctionCallFound = true;
6344
6345 // We have found a declaration which will associated the scope of a function declaration
6346 // (so all function calls after this point can be qualified (and might have to be).
6348#if 0
6349 printf ("Found a declaration which preceeds the function \n");
6350 declaration->get_file_info()->display("Found a declaration which preceeds the function: declaration");
6351 storedFunctionCall->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionCall");
6352 storedFunctionDeclaration->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionDeclaration");
6353#endif
6354 }
6355 else
6356 {
6357 // Error checking!
6358 if (parentScopeOfDeclaration == NULL)
6359 {
6360 // This might be a function declaration (non-defining) used in a type or buried deeply in some sort of declaration!
6361 printf ("Strange case of parentScopeOfDeclaration == NULL in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6362 SgNode* parent = declaration->get_parent();
6363 if (parent != NULL) {
6364 printf ("declaration->get_parent() = %s \n",parent->class_name().c_str());
6365 }
6366 else {
6367 printf ("declaration->get_parent() = NULL \n");
6368 }
6369 declaration->get_file_info()->display("case of parentScopeOfDeclaration == NULL");
6370 ROSE_ABORT();
6371 }
6372 }
6373 }
6374 }
6375 }
6376
6377 public:
6378 bool storedFunctionCallFound;
6380
6381 private:
6382 SgFunctionCallExp* storedFunctionCall;
6383 SgDeclarationStatement* storedFunctionDeclaration;
6384 };
6385
6386 ROSE_ASSERT(functionCall != NULL);
6387#if 0
6388 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): \n");
6389 printf (" storedFunctionCall = %p = %s \n",functionCall,functionCall->class_name().c_str());
6390 functionCall->get_file_info()->display("storedFunctionCall");
6391 printf (" storedFunctionCall->get_function() = %p = %s \n",functionCall->get_function(),functionCall->get_function()->class_name().c_str());
6392 printf ("************************************************************* \n");
6393#endif
6394
6395 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6396 bool returnResult = false;
6397
6398 // Get the global scope from a traversal back (up) through the AST.
6399 SgGlobal* globalScope = TransformationSupport::getGlobalScope(functionCall);
6400 ROSE_ASSERT(globalScope != NULL);
6401
6402 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6403 DeclarationOrderTraversal traversal (functionCall);
6404
6405#if 0
6406 traversal.traverse(globalScope, preorder);
6407#else
6408 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6409 printf ("Skipping traversal within SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6410 traversal.storedFunctionCallFound = true;
6411 traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope = false;
6412#endif
6413
6414 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6415 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6416 // nondefining declarations that are not in the traversal).
6417
6418 if (traversal.storedFunctionCallFound == false)
6419 {
6420#if 0
6421 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): warning, storedFunctionCall not found in the AST \n");
6422 functionCall->get_file_info()->display("functionCall");
6423 printf ("---------------------------------------------------- \n\n");
6424#endif
6425 // Set this error case to return true so that we will not assume incorrectly
6426 // that the function call is used after a declaration that associated the scope
6427 // with the function. This still causes the global name qualifier to be omitted.
6428 returnResult = true;
6429 }
6430 else
6431 {
6432 returnResult = traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope;
6433 }
6434
6435 // I hope that this is nearly always be true!
6436 ROSE_ASSERT(traversal.storedFunctionCallFound == true);
6437#if 0
6438 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6439 printf ("************************************************************* \n\n");
6440#endif
6441 return returnResult;
6442 }
6443
6444#endif
6445
6446// #ifndef USE_ROSE
6447
6448string
6449SageInterface::generateProjectName( const SgProject* project, bool supressSuffix )
6450 {
6451 // This function generates a string to use as a unique project name for
6452 // a collection of files. The last file will include it's suffix so that
6453 // we generate proper names that communicate the source language.
6454 // Also also allows the single file case to be consistant with the previous
6455 // version of names generated for "DOT" files in the tutorial.
6456
6457 // DQ (9/6/2008): Introduced optional parameter to supresse the suffix in the
6458 // generation of the project name so that we can support more complex name
6459 // construction as required for the generation of names for the whole AST
6460 // graphs which append an additional suffix to avoid filename collision.
6461
6462 ROSE_ASSERT(project != NULL);
6463 string projectName;
6464
6465 // DQ (9/2/2008): Removed the redundant function getFileNames().
6466 // Rose_STL_Container<string> fileList = project->get_sourceFileNameList();
6467 Rose_STL_Container<string> fileList = project->getAbsolutePathFileNames();
6468
6469 Rose_STL_Container<string>::iterator i = fileList.begin();
6470
6471 // Handle the case of an empty list (e.g. for link lines).
6472 if ( fileList.empty() == true )
6473 {
6474 return "empty_file_list";
6475 }
6476
6477 do {
6478 string filename = *i;
6479
6480 // printf ("In SageInterface::generateProjectName(): absolute filename = %s \n",filename.c_str());
6481
6482 // string filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6483
6484 if (i != fileList.begin())
6485 projectName += "--";
6486
6487 i++;
6488
6489 string filenameWithoutSuffix;
6490 if ( i != fileList.end() || supressSuffix == true )
6491 filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6492 else
6493 filenameWithoutSuffix = filename;
6494
6495 string filenameWithoutPathOrSuffix = StringUtility::stripPathFromFileName(filenameWithoutSuffix);
6496
6497 // printf ("filenameWithoutSuffix = %s \n",filenameWithoutSuffix.c_str());
6498 // printf ("filenameWithoutPathOrSuffix = %s \n",filenameWithoutPathOrSuffix.c_str());
6499
6500 filename = filenameWithoutPathOrSuffix;
6501
6502 unsigned long int n = 0;
6503 while (n < filename.size())
6504 {
6505 if (filename[n] == '/')
6506 filename[n] = '_';
6507 n++;
6508 }
6509
6510 // printf ("In SageInterface:generateProjectName(): modified absolute filename = %s \n",filename.c_str());
6511
6512 projectName += filename;
6513
6514 // printf ("In SageInterface:generateProjectName(): evolving projectName = %s \n",projectName.c_str());
6515 }
6516 while (i != fileList.end());
6517
6518 // printf ("In SageInterface:generateProjectName(): projectName = %s \n",projectName.c_str());
6519
6520 return projectName;
6521 }
6522
6523// #endif
6524
6525// #ifndef USE_ROSE
6526
6529 {
6530 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6531 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6532
6533 // enable default search from top of StackScope, Liao, 1/24/2008
6534 SgFunctionSymbol* functionSymbol = NULL;
6535 if (currentScope == NULL)
6536 currentScope = SageBuilder::topScopeStack();
6537 ROSE_ASSERT(currentScope != NULL);
6538
6539 SgScopeStatement* tempScope = currentScope;
6540 while ((functionSymbol == NULL) && (tempScope != NULL))
6541 {
6542 functionSymbol = tempScope->lookup_function_symbol(functionName);
6543#if 0
6544 printf ("In lookupFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6545#endif
6546 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6547 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6548 else
6549 tempScope = NULL;
6550 }
6551 return functionSymbol;
6552 }
6553
6555SageInterface::lookupTemplateFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6556 {
6557 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6558 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6559
6560 // enable default search from top of StackScope, Liao, 1/24/2008
6561 SgFunctionSymbol* functionSymbol = NULL;
6562 if (currentScope == NULL)
6563 currentScope = SageBuilder::topScopeStack();
6564 ROSE_ASSERT(currentScope != NULL);
6565
6566 SgScopeStatement* tempScope = currentScope;
6567 while ((functionSymbol == NULL) && (tempScope != NULL))
6568 {
6569 functionSymbol = tempScope->lookup_template_function_symbol(functionName, ftype, tplparams);
6570#if 0
6571 printf ("In lookupTemplateFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6572#endif
6573 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6574 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6575 else
6576 tempScope = NULL;
6577 }
6578 return functionSymbol;
6579 }
6580
6582SageInterface::lookupTemplateMemberFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6583 {
6584 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6585 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6586
6587 // enable default search from top of StackScope, Liao, 1/24/2008
6588 SgFunctionSymbol* functionSymbol = NULL;
6589 if (currentScope == NULL)
6590 currentScope = SageBuilder::topScopeStack();
6591 ROSE_ASSERT(currentScope != NULL);
6592
6593 SgScopeStatement* tempScope = currentScope;
6594 while ((functionSymbol == NULL) && (tempScope != NULL))
6595 {
6596 functionSymbol = tempScope->lookup_template_member_function_symbol(functionName, ftype, tplparams);
6597#if 0
6598 printf ("In lookupTemplateMemberFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6599#endif
6600 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6601 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6602 else
6603 tempScope = NULL;
6604 }
6605 return functionSymbol;
6606 }
6607
6608void
6609SageInterface::addTextForUnparser ( SgNode* astNode, string s, AstUnparseAttribute::RelativePositionType inputlocation )
6610 {
6611 // printf ("addText(): using new attribute interface (s = %s) \n",s.c_str());
6612
6613 if (isSgType(astNode) != NULL)
6614 {
6615 printf ("Error: the mechanism to add text to be unparsed at IR nodes is not intended to operate on SgType IR nodes (since they are shared) \n");
6616 ROSE_ABORT();
6617 }
6618
6619 if (astNode->attributeExists(AstUnparseAttribute::markerName) == true)
6620 {
6621 AstUnparseAttribute* code = dynamic_cast<AstUnparseAttribute*>(astNode->getAttribute(AstUnparseAttribute::markerName));
6622 ROSE_ASSERT(code != NULL);
6623
6624 // DQ (2/23/2009): commented added.
6625 // Since there is at least one other string (there is an existing attribute) the relative order of the strings is significant.
6626 code->addString(s,inputlocation);
6627 }
6628 else
6629 {
6630 // DQ (2/25/2016): I think it is significant, because inputlocation refers to the order relative to
6631 // the statement, not relative to other AstUnparseAttribute objects. Fixed to use the inputlocation.
6632 // DQ (2/23/2009): commented added.
6633 // Note that this will be the only string in the attribute, so inputlocation is not significant (and e_before is the default used).
6634 // AstUnparseAttribute* code = new AstUnparseAttribute(s,AstUnparseAttribute::e_before);
6635 AstUnparseAttribute* code = new AstUnparseAttribute(s,inputlocation);
6636 ROSE_ASSERT(code != NULL);
6637
6638 astNode->addNewAttribute(AstUnparseAttribute::markerName,code);
6639 }
6640 }
6641
6642
6643#if 0
6644// DQ (7/20/2011): Resolving conflict, this was added in previous work in dq-cxx-rc branch.
6645// DQ (7/17/2011): Added function from cxx branch that I need here for the Java support.
6648 {
6649 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6650 SgClassSymbol* symbol = NULL;
6651 if (cscope == NULL)
6652 cscope = SageBuilder::topScopeStack();
6653 ROSE_ASSERT(cscope != NULL);
6654
6655 while ((cscope != NULL) && (symbol == NULL))
6656 {
6657 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6658 symbol = cscope->lookup_class_symbol(name,NULL);
6659
6660 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6661 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6662 else
6663 cscope = NULL;
6664 }
6665
6666 return symbol;
6667 }
6668#endif
6669
6670
6671
6672SgType* SageInterface::lookupNamedTypeInParentScopes(const std::string& type_name, SgScopeStatement* scope/*=NULL*/)
6673 {
6674 if (scope == NULL)
6676
6677 // DQ (8/16/2013): Added NULL pointers to at least handle the API change.
6678 SgSymbol* symbol = lookupSymbolInParentScopes (type_name,scope,NULL,NULL);
6679
6680 if (symbol == NULL)
6681 return NULL;
6682 else
6683 return symbol->get_type();
6684 }
6685
6687 const SgType* t,
6688 SgScopeStatement *currentScope)
6689 //SgScopeStatement *currentScope=NULL)
6690{
6691 SgFunctionSymbol* functionSymbol = NULL;
6692 if (currentScope == NULL)
6693 currentScope = SageBuilder::topScopeStack();
6694 ROSE_ASSERT(currentScope != NULL);
6695 SgScopeStatement* tempScope = currentScope;
6696 while (functionSymbol == NULL && tempScope != NULL)
6697 {
6698 functionSymbol = tempScope->lookup_function_symbol(functionName,t);
6699 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6700 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6701 else tempScope = NULL;
6702 }
6703 return functionSymbol;
6704}
6705
6706SgSymbol*
6707SageInterface::lookupSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6708 {
6709 SgSymbol* symbol = nullptr;
6710 if (cscope == nullptr) {
6711 cscope = SageBuilder::topScopeStack();
6712 }
6713 ASSERT_not_null(cscope);
6714
6715 while ((cscope != nullptr) && (symbol == nullptr))
6716 {
6717 symbol = cscope->lookup_symbol(name,templateParameterList,templateArgumentList);
6718 if (cscope->get_parent() != nullptr) // avoid calling get_scope when parent is not set
6719 cscope = isSgGlobal(cscope) ? nullptr : cscope->get_scope();
6720 else
6721 cscope = nullptr;
6722 }
6723
6724 return symbol;
6725 }
6726
6727
6728
6729SgSymbol*
6730SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols (const SgName & name, SgScopeStatement *currentScope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6731 {
6732// DQ (8/5/2020): the "using namespace" directive will not hide existing visability of symbols in resolving visability.
6733// So we need to test if a symbol is visible exclusing matching alises due to using direectives before we can decide to
6734// persue name space qualification. This is best demonstrated by Cxx_tests/test2020_18.C, test2020_19.C, test2020_20.C,
6735// and test2020_21.C.
6736
6737 SgSymbol* symbol = NULL;
6738 if (currentScope == NULL)
6739 {
6740 currentScope = SageBuilder::topScopeStack();
6741 }
6742
6743 ROSE_ASSERT(currentScope != NULL);
6744
6745#define DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS 0
6746
6747#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6748 printf ("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): currentScope = %p = %s (templateParameterList = %p templateArgumentList = %p) \n",
6749 currentScope,currentScope->class_name().c_str(),templateParameterList,templateArgumentList);
6750#endif
6751
6752 while ((currentScope != NULL) && (symbol == NULL))
6753 {
6754#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6755 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): name = %s currentScope = %p = %s \n",
6756 name.str(),currentScope,currentScope->class_name().c_str());
6757#endif
6758
6759 // DQ (8/16/2013): Changed API to support template parameters and template arguments.
6760 // symbol = cscope->lookup_symbol(name);
6761 symbol = currentScope->lookup_symbol(name,templateParameterList,templateArgumentList);
6762
6763 if (isSgAliasSymbol(symbol) != NULL)
6764 {
6765#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6766 printf ("Found a SgAliasSymbol: reset to NULL: symbol = %p = %s \n",symbol,symbol->class_name().c_str());
6767#endif
6768 symbol = NULL;
6769 }
6770
6771#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS && 1
6772 // debug
6773 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): symbol = %p \n",symbol);
6774 currentScope->print_symboltable("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): debug");
6775#endif
6776 if (currentScope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6777 currentScope = isSgGlobal(currentScope) ? NULL : currentScope->get_scope();
6778 else
6779 currentScope = NULL;
6780
6781#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6782 printf (" --- In SageInterface:: (base of loop) lookupSymbolInParentScopesIgnoringAliasSymbols(): cscope = %p symbol = %p \n\n",currentScope,symbol);
6783#endif
6784 }
6785
6786 if (symbol == NULL)
6787 {
6788#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6789 printf ("Warning: In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): could not locate the specified name %s in any outer symbol table (templateParameterList = %p templateArgumentList = %p) \n",
6790 name.str(),templateParameterList,templateArgumentList);
6791#endif
6792 // ROSE_ASSERT(false);
6793 }
6794
6795#if 0
6796 printf ("Support for lookupSymbolInParentScopesIgnoringAliasSymbols() is not yet implemented \n");
6797 ROSE_ABORT();
6798#endif
6799
6800 return symbol;
6801 }
6802
6803
6804
6805
6806
6807
6808
6809
6810#if 0
6811// DQ (7/13/2011): This was part of a merge conflict with the above modified function.
6812// It appeas they are the same so this one is commented out.
6814{
6815 SgSymbol* symbol = NULL;
6816 if (cscope == NULL)
6817 cscope = SageBuilder::topScopeStack();
6818 ROSE_ASSERT(cscope);
6819
6820 while ((cscope!=NULL)&&(symbol==NULL))
6821 {
6822 symbol = cscope->lookup_symbol(name);
6823 //debug
6824 // cscope->print_symboltable("debug sageInterface.C L3749...");
6825 if (cscope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6826 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6827 else
6828 cscope = NULL;
6829 }
6830
6831 if (symbol==NULL)
6832 {
6833 // printf ("Warning: could not locate the specified name %s in any outer symbol table \n"e,
6834 // name.str());
6835 // ROSE_ASSERT(false);
6836 }
6837 return symbol;
6838}
6839#endif
6840
6843 {
6844 // DQ (1/24/2011): This function is inconsistant with an implementation that would correctly handle SgAliasSymbols.
6845 // Also this function might get a SgClassSymbol instead of a SgVariableSymbol when both names are used.
6846 // This function needs to be fixed to handle the multi-map semantics of the symbol tables.
6847
6848#if 0
6849 // DQ (5/7/2011): I think this implementation is not correct (does not resolve past hidden types) and so should
6850 // be fixed to be consistant with the implementation of SageInterface::lookupClassSymbolInParentScopes().
6851 // Since I don't know where this function is used, I don't want to change it just yet.
6852 printf ("WARNING: SageInterface::lookupVariableSymbolInParentScopes() should be implemented similar to SageInterface::lookupClassSymbolInParentScopes() \n");
6853
6854 SgVariableSymbol* result = NULL;
6855 SgSymbol* symbol=lookupSymbolInParentScopes(name,cscope);
6856 if (symbol != NULL)
6857 {
6858 if (isSgAliasSymbol(symbol) != NULL)
6859 {
6860 printf ("Error: This SageInterface::lookupVariableSymbolInParentScopes() function does not handle SgAliasSymbols \n");
6861 ROSE_ABORT();
6862 }
6863 result = isSgVariableSymbol(symbol);
6864 }
6865 return result;
6866#else
6867 // I think this is the better implementation.
6868 SgVariableSymbol* symbol = NULL;
6869 if (cscope == NULL)
6870 cscope = SageBuilder::topScopeStack();
6871 ROSE_ASSERT(cscope != NULL);
6872
6873 while ((cscope != NULL) && (symbol == NULL))
6874 {
6875 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6876 symbol = cscope->lookup_variable_symbol(name);
6877
6878 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6879 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6880 else
6881 cscope = NULL;
6882 }
6883
6884 return symbol;
6885#endif
6886 }
6887
6888#define DEBUG_LOOKUP_TEMPLATE_VARIABLE 0
6889
6891SageInterface::lookupTemplateVariableSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList * tplparams, SgTemplateArgumentPtrList* tplargs, SgScopeStatement *cscope)
6892 {
6893#if DEBUG_LOOKUP_TEMPLATE_VARIABLE
6894 printf ("In SageInterface::lookupTemplateVariableSymbolInParentScopes():\n");
6895 printf (" -- name = %s\n", name.str());
6896 printf (" -- tplparams = %p [%zd]\n", tplparams, tplparams ? tplparams->size() : 0);
6897 printf (" -- tplargs = %p [%zd]\n", tplargs, tplargs ? tplargs->size() : 0);
6898 printf (" -- cscope = %p (%s)\n", cscope, cscope ? cscope->class_name().c_str() : "");
6899#endif
6900
6901 SgTemplateVariableSymbol* symbol = NULL;
6902 if (cscope == NULL)
6903 cscope = SageBuilder::topScopeStack();
6904 ROSE_ASSERT(cscope != NULL);
6905
6906 while ((cscope != NULL) && (symbol == NULL))
6907 {
6908 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6909 symbol = cscope->lookup_template_variable_symbol(name, tplparams, tplargs);
6910
6911 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6912 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6913 else
6914 cscope = NULL;
6915 }
6916
6917 return symbol;
6918 }
6919
6920// SgClassSymbol* SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
6922SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateArgumentPtrList* templateArgumentList)
6923 {
6924 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6925 SgClassSymbol* symbol = NULL;
6926 if (cscope == NULL)
6927 cscope = SageBuilder::topScopeStack();
6928 ROSE_ASSERT(cscope != NULL);
6929
6930 while ((cscope != NULL) && (symbol == NULL))
6931 {
6932 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6933 // symbol = cscope->lookup_class_symbol(name,NULL);
6934 symbol = cscope->lookup_class_symbol(name,templateArgumentList);
6935
6936 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6937 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6938 else
6939 cscope = NULL;
6940 }
6941
6942 return symbol;
6943 }
6944
6946SageInterface::lookupNonrealSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6947 {
6948 SgNonrealSymbol* symbol = NULL;
6949 if (cscope == NULL)
6950 cscope = SageBuilder::topScopeStack();
6951 ROSE_ASSERT(cscope != NULL);
6952
6953 while ((cscope != NULL) && (symbol == NULL))
6954 {
6955 symbol = cscope->lookup_nonreal_symbol(name,templateParameterList,templateArgumentList);
6956
6957 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6958 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6959 else
6960 cscope = NULL;
6961 }
6962
6963 return symbol;
6964 }
6965
6968 {
6969 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6970 SgTypedefSymbol* symbol = NULL;
6971 if (cscope == NULL)
6972 cscope = SageBuilder::topScopeStack();
6973 ROSE_ASSERT(cscope != NULL);
6974
6975#if 0
6976 printf ("In lookupTypedefSymbolInParentScopes(): name = %s starting with cscope = %p = %s \n",name.str(),cscope,cscope->class_name().c_str());
6977 printf ("--- parent scope = %p = %s \n",cscope->get_scope(),(cscope->get_scope() != NULL) ? cscope->get_scope()->class_name().c_str() : "null");
6978#endif
6979
6980 while ((cscope != NULL) && (symbol == NULL))
6981 {
6982 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6983 symbol = cscope->lookup_typedef_symbol(name);
6984
6985 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6986 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6987 else
6988 cscope = NULL;
6989
6990#if 0
6991 printf ("In lookupTypedefSymbolInParentScopes(): symbol = %p next cscope = %p = %s \n",symbol,cscope,(cscope != NULL) ? cscope->class_name().c_str() : "null");
6992#endif
6993 }
6994
6995#if 0
6996 printf ("Leaving lookupTypedefSymbolInParentScopes(): symbol = %p \n",symbol);
6997#endif
6998
6999 return symbol;
7000 }
7001
7002#if 0
7003// DQ (8/13/2013): This function does not make since any more, now that we have make the symbol
7004// table handling more precise and we have to provide template parameters for any template lookup.
7005// We also have to know if we want to lookup template classes, template functions, or template
7006// member functions (since each have specific requirements).
7008SageInterface::lookupTemplateSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
7009 {
7010 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7011 SgTemplateSymbol* symbol = NULL;
7012 if (cscope == NULL)
7013 cscope = SageBuilder::topScopeStack();
7014 ROSE_ASSERT(cscope != NULL);
7015
7016 while ((cscope != NULL) && (symbol == NULL))
7017 {
7018 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7019 // In this case these are unavailable from this point.
7020 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7021 // symbol = cscope->lookup_template_symbol(name);
7022 symbol = cscope->lookup_template_symbol(name,NULL,NULL);
7023#if 0
7024 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7025#endif
7026 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7027 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7028 else
7029 cscope = NULL;
7030 }
7031
7032 return symbol;
7033 }
7034#endif
7035
7036
7038SageInterface::lookupTemplateClassSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList, SgScopeStatement *cscope)
7039 {
7040 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7041 SgTemplateClassSymbol* symbol = NULL;
7042 if (cscope == NULL)
7043 cscope = SageBuilder::topScopeStack();
7044 ROSE_ASSERT(cscope != NULL);
7045
7046 while ((cscope != NULL) && (symbol == NULL))
7047 {
7048 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7049 // In this case these are unavailable from this point.
7050 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7051 // symbol = cscope->lookup_template_symbol(name);
7052 symbol = cscope->lookup_template_class_symbol(name,templateParameterList,templateArgumentList);
7053#if 0
7054 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7055#endif
7056 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7057 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7058 else
7059 cscope = NULL;
7060 }
7061
7062 return symbol;
7063 }
7064
7065
7068 {
7069 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7070 // A templated solution might make for a better implementation.
7071 SgEnumSymbol* symbol = NULL;
7072 if (cscope == NULL)
7073 cscope = SageBuilder::topScopeStack();
7074 ROSE_ASSERT(cscope != NULL);
7075
7076 while ((cscope != NULL) && (symbol == NULL))
7077 {
7078 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7079 symbol = cscope->lookup_enum_symbol(name);
7080
7081 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7082 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7083 else
7084 cscope = NULL;
7085 }
7086
7087 return symbol;
7088 }
7089
7092 {
7093 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7094 SgNamespaceSymbol* symbol = NULL;
7095 if (cscope == NULL)
7096 cscope = SageBuilder::topScopeStack();
7097 ROSE_ASSERT(cscope != NULL);
7098
7099 while ((cscope != NULL) && (symbol == NULL))
7100 {
7101 // I think this will resolve SgAliasSymbols to be a SgNamespaceSymbol where the alias is of a SgNamespaceSymbol.
7102 symbol = cscope->lookup_namespace_symbol(name);
7103
7104 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7105 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7106 else
7107 cscope = NULL;
7108 }
7109
7110 return symbol;
7111 }
7112
7113template<class T>
7114void
7115SageInterface::setSourcePositionToDefault( T* node )
7116 {
7117 // This is a templated function because SgPragma is not yet derived from SgLocatedNode.
7118
7119 // DQ (2/17/2013): This function is called a lot, so it might be a performance issue.
7120 // All IR nodes built by the Build Interface are assighed source position information
7121 // using this function and then reset afterward as we use information within EDG to
7122 // reset the source position information. Ideally, the EDG/ROSE connection would
7123 // use NULL pointers as the behavior for the front-end mode. We can move to that
7124 // later to maek the source position handling more efficient.
7125
7126 // DQ (1/24/2009): It might be that this function is only called from the Fortran support.
7127
7128 // This function sets the source position to be marked as not
7129 // available (since we often don't have token information)
7130 // These nodes WILL be unparsed in the conde generation phase.
7131
7132 // The SgLocatedNode has both a startOfConstruct and endOfConstruct source position.
7133 ROSE_ASSERT(node != NULL);
7134
7135 // We have to support this being called where the Sg_File_Info have previously been set.
7136 if (node->get_endOfConstruct() == NULL && node->get_startOfConstruct() == NULL)
7137 {
7138#if 0
7139 printf ("Both startOfConstruct and endOfConstruct are NOT yet initialized with pointers to Sg_File_Info objects (node = %p = %s) \n",node,node->class_name().c_str());
7140#endif
7141 // Check the endOfConstruct first since it is most likely NULL (helpful in debugging)
7142 ROSE_ASSERT(node->get_endOfConstruct() == NULL);
7143 ROSE_ASSERT(node->get_startOfConstruct() == NULL);
7144
7147
7148 // DQ (5/2/2012): I think we don't want to do this.
7149#if 0
7150 printf ("In SageInterface::setSourcePositionToDefault(): Calling setSourcePositionUnavailableInFrontend() \n");
7151#endif
7152 start_fileInfo->setSourcePositionUnavailableInFrontend();
7153 end_fileInfo->setSourcePositionUnavailableInFrontend();
7154
7155 // DQ (5/2/2012): I think we don't want to do this.
7156#if 0
7157 printf ("In SageInterface::setSourcePositionToDefault(): Calling setOutputInCodeGeneration() \n");
7158#endif
7159 // This is required for the unparser to output the code from the AST.
7160 start_fileInfo->setOutputInCodeGeneration();
7161 end_fileInfo->setOutputInCodeGeneration();
7162
7163 node->set_startOfConstruct(start_fileInfo);
7164 node->set_endOfConstruct (end_fileInfo);
7165
7166 node->get_startOfConstruct()->set_parent(node);
7167 node->get_endOfConstruct ()->set_parent(node);
7168 }
7169 else
7170 {
7171 // If both the starting and ending Sg_File_Info pointers are not NULL then both must be valid.
7172 // We don't want to support partially completed source code position information.
7173#if 0
7174 printf ("Both startOfConstruct and endOfConstruct are ALREADY initialized with pointers to Sg_File_Info objects (node = %p = %s) \n",node,node->class_name().c_str());
7175#endif
7176 if (node->get_startOfConstruct() == NULL)
7177 {
7178 printf ("ERROR: startOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7179 }
7180 if (node->get_endOfConstruct() == NULL)
7181 {
7182 printf ("ERROR: endOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7183 }
7184
7185 ROSE_ASSERT(node->get_startOfConstruct() != NULL);
7186 ROSE_ASSERT(node->get_endOfConstruct() != NULL);
7187 ROSE_ASSERT(node->get_endOfConstruct() != NULL && node->get_startOfConstruct() != NULL);
7188 }
7189
7190 // DQ (11/2/2012): This is an important fix to support the new EDG 4.x branch.
7191 // Note that because the unparser will use the function isFromAnotherFile() in the unparsing
7192 // of expressions, specifically: SgAggregateInitializer, SgCompoundInitializer, and anything
7193 // in their expression lists (which could be any expression). The isFromAnotherFile() will
7194 // use the get_file_info() function on the SgExpression IR nodes and the data from that
7195 // Sg_File_Info object to determine if that expression subtree should be unparsed. This
7196 // expression level granularity of unparsing capability is extremely useful in handling
7197 // now #includes and other CPP directives are woven back into the AST. But since the
7198 // get_file_info() function is used, and it returns the value of get_operatorPosition(),
7199 // it is critically important to have correct data in the SgExpression::p_operatorPosition
7200 // Sg_File_Info object (it counts more that the startOfConstruct and endOfConstruct
7201 // Sg_File_Info objects in controlling what expressions are unparsed. So we have to set these
7202 // up for all expressions (since any SgExpression could appear in the list contained in
7203 // a SgAggregateInitializer or SgCompoundInitializer.
7204
7205 // DQ (11/2/2012): Set the operator source position information to default values.
7206 // This will trigger it to be reset to valid source position information in the front-end.
7207 SgExpression* expression = isSgExpression(node);
7208 if (expression != NULL)
7209 {
7210#if 0
7211 SgBinaryOp* binaryOp = isSgBinaryOp(expression);
7212 if (binaryOp != NULL)
7213 {
7214 if (binaryOp->get_operatorPosition() == NULL)
7215 {
7217 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7218 operator_fileInfo->setOutputInCodeGeneration();
7219 binaryOp->set_operatorPosition(operator_fileInfo);
7220
7221 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7222 binaryOp->get_operatorPosition()->set_parent(binaryOp);
7223 }
7224 }
7225#else
7226 // Setup all of the SgExpression operatorPosition pointers to default objects.
7227 if (expression->get_operatorPosition() == NULL)
7228 {
7230 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7231 operator_fileInfo->setOutputInCodeGeneration();
7232 expression->set_operatorPosition(operator_fileInfo);
7233
7234 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7235 // expression->get_operatorPosition()->set_parent(expression);
7236 operator_fileInfo->set_parent(expression);
7237 ROSE_ASSERT(expression->get_operatorPosition()->get_parent() == expression);
7238 }
7239#endif
7240 }
7241 }
7242
7243
7244void
7246 {
7247 // DQ (5/1/2012): Older depricated function.
7248#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
7249 printf ("+++++ Depricated function (use setSourcePositionAsTransformation() instead) (no using internal source position mode) \n");
7250#endif
7251
7252 // setSourcePositionAsTransformation(node);
7253 setSourcePosition(node);
7254 }
7255
7256
7257void
7259 {
7260 // DQ (5/1/2012): Newer function to support specification of IR nodes being a part of a transformation.
7261
7262 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionAsTransformation(SgNode *node)"
7263 // The logic should be make more independent of if (locatedNode->get_startOfConstruct() == NULL)
7264 // Since that make understanding where the function is applied too complex.
7265 // If (locatedNode->get_startOfConstruct() != NULL), then we should just make that Sg_File_Info as
7266 // a transforamtion directly, this function misses that step.
7267
7268 ROSE_ASSERT(node != NULL);
7269
7270 // DQ (10/12/2012): Commented out since we are past AST regression tests passing and now trying to get this work checked in.
7271// printf ("In SageInterface::setSourcePositionAsTransformation() for node = %p = %s (make this an error while debugging AST construction) \n",node,node->class_name().c_str());
7272 // ROSE_ASSERT(false);
7273
7274 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7275 SgExpression* expression = isSgExpression(node);
7276 // SgInitializedName* initName = isSgInitializedName(node);
7277 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7278 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7279
7280#if 0
7281 SgVariableDefinition * v_d = isSgVariableDefinition(node);
7282 if (v_d )
7283 printf ("Debug, Found a variable definition: %p\n", v_d);
7284#endif
7285
7286 if (locatedNode != NULL)
7287 {
7289 locatedNode->get_startOfConstruct()->set_parent(locatedNode);
7290
7291 if (global==NULL)
7292 {
7294 locatedNode->get_endOfConstruct ()->set_parent(locatedNode);
7295 }
7296
7297 // Only SgExpression IR nodes have a 3rd source position data structure.
7298 if (expression!=NULL)
7299 {
7300 expression->set_operatorPosition(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7301 expression->get_operatorPosition()->set_parent(expression);
7302 }
7303 }
7304 else // special non-located node with file info
7305 {
7306 if ( (pragma != NULL) && (pragma->get_startOfConstruct() == NULL) )
7307 {
7308 pragma->set_startOfConstruct(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7309 pragma->get_startOfConstruct()->set_parent(pragma);
7310 }
7311 }
7312 }
7313
7314
7315void
7317 {
7318 // DQ (5/1/2012): Older depricated function (use setSourcePositionPointersToNull() instead).
7319#if 0
7320 printf ("+++++ Depricated name setOneSourcePositionNull() (use setSourcePositionPointersToNull() instead) (no using internal source position mode) \n");
7321#endif
7322
7323 setSourcePosition(node);
7324 }
7325
7326// DQ (5/1/2012): Newly renamed function (previous name preserved for backward compatability).
7327void
7329 {
7330 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionToNULL(SgNode *node)"
7331 // However, if this is doen then the logic should be that it asserts that: (locatedNode->get_startOfConstruct() == NULL)
7332 // so that we know when we are leaking memory. Similarly, we should assert that:
7333 // (locatedNode->get_endOfConstruct() == NULL).
7334 // But then this function just asserts that everything is already NULL and is less about setting them to NULL.
7335 // If (locatedNode->get_startOfConstruct() != NULL), should we delete the existing Sg_File_Info object?
7336 // This function misses that step.
7337
7338 ROSE_ASSERT(node != NULL);
7339
7340 SgLocatedNode * locatedNode = isSgLocatedNode(node);
7341 SgExpression* expression = isSgExpression(node);
7342 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7343 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7344
7345 // DQ (1/24/2009): If the point is to set the source position to NULL pointers,
7346 // why do we only handle the case when (get_startOfConstruct() == NULL)
7347 // (i.e. when the start source postion is already NULL).
7348
7349 if (locatedNode != NULL)
7350 {
7351 if (locatedNode->get_startOfConstruct() != NULL)
7352 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of startOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7353
7354 locatedNode->set_startOfConstruct(NULL);
7355
7356 // Note that SgGlobal should have NULL endOfConstruct()
7357 if (global == NULL)
7358 {
7359 if (locatedNode->get_endOfConstruct() != NULL)
7360 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of endOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7361
7362 locatedNode->set_endOfConstruct(NULL);
7363 }
7364
7365 // Only SgExpression IR nodes have a 3rd source position data structure.
7366 if (expression != NULL)
7367 {
7368 if (expression->get_operatorPosition() != NULL)
7369 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of operatorPosition Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7370
7371 expression->set_operatorPosition(NULL);
7372 }
7373 }
7374 else
7375 {
7376 if ( (pragma != NULL) && (pragma->get_startOfConstruct() != NULL) )
7377 {
7378 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7379
7380 pragma->set_startOfConstruct(NULL);
7381 }
7382 }
7383 }
7384
7385// DQ (1/24/2009): Could we change the name to be "setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)"
7386void
7388 {
7389#if 1
7390#if 0
7391 printf ("+++++ Depricated name setSourcePositionForTransformation() (use setSourcePositionAtRootAndAllChildrenAsTransformation() instead) \n");
7392#endif
7393
7394 // This is the semantically correct function to call.
7395 // setSourcePositionAtRootAndAllChildrenAsTransformation(root);
7396
7397 // DQ (5/2/2012): This is a test to replace the support we have to mark every thing as a transformation with the new mechanism using source position modes.
7398 // setSourcePosition(root);
7399 // Liao 11/21/2012. This function should only be called when the mode is transformation
7400 // Liao 8/2/2013. It can actually be called inside frontend by OmpSupport::lower_omp().
7401 //ROSE_ASSERT(SageBuilder::SourcePositionClassificationMode == SageBuilder::e_sourcePositionTransformation);
7403#else
7404 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7405 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7406 {
7408 }
7409#endif
7410 }
7411
7412
7413#if 0
7414// DQ (5/1/2012): New function with improved name (still preserving the previous interface).
7415void
7416SageInterface::setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)
7417 {
7418 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7419 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7420 {
7422 }
7423 }
7424#endif
7425
7426#if 0
7427void
7428SageInterface::setSourcePositionAtRootAndAllChildrenAsDefault(SgNode *root)
7429 {
7430 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7431 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7432 {
7433 setSourcePositionAsDefault(*i);
7434 }
7435 }
7436#endif
7437
7438void
7440 {
7441 // DQ (2/17/2013): This is a relatively expensive operation so we might look into this.
7442
7443 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7444
7445#if 0
7446 printf ("In setSourcePositionAtRootAndAllChildren(): nodeList.size() = %" PRIuPTR " \n",nodeList.size());
7447#endif
7448
7449 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
7450 {
7451#if 0
7452 printf ("In setSourcePositionAtRootAndAllChildren(): *i = %p = %s \n",*i,(*i)->class_name().c_str());
7453#endif
7455 }
7456 }
7457
7458// DQ (5/1/2012): This function queries the SageBuilder::SourcePositionClassification mode (stored in the SageBuilder
7459// interface) and used the specified mode to initialize the source position data (Sg_File_Info objects). This
7460// function is the only function that should be called directly (though in a namespace we can't define permissions).
7461void
7463 {
7464 // Check the mode and build the correct type of source code position.
7466
7467 // DQ (2/17/2013): Note that the SourcePositionClassification will be e_sourcePositionFrontendConstruction
7468 // during construction of the AST from the EDG frontend.
7469
7470#if 0
7471 printf ("In SageInterface::setSourcePosition(): SourcePositionClassification scp = %s \n",display(scp).c_str());
7472#endif
7473
7474 switch(scp)
7475 {
7476 case e_sourcePositionError: // Error value for enum.
7477 {
7478 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7479 ROSE_ABORT();
7480 }
7481
7482 case e_sourcePositionDefault: // Default source position.
7483 {
7484#if 0
7485 printf ("e_sourcePositionDefault in SageInterface::setSourcePosition() \n");
7486#endif
7487 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7488 if (locatedNode != NULL)
7489 {
7490 setSourcePositionToDefault(locatedNode);
7491 }
7492 else
7493 {
7494 // This is not supported (not clear if it need be).
7495 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionDefault with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7496 ROSE_ABORT();
7497 }
7498 break;
7499 }
7500
7501 case e_sourcePositionTransformation: // Classify as a transformation.
7502 {
7503#if 0
7504 printf ("e_sourcePositionTransformation in SageInterface::setSourcePosition() \n");
7505#endif
7506 // setSourcePositionAtRootAndAllChildrenAsTransformation(node);
7508 break;
7509 }
7510
7511 case e_sourcePositionCompilerGenerated: // Classify as compiler generated code (e.g. template instantiation).
7512 {
7513 printf ("e_sourcePositionCompilerGenerated in SageInterface::setSourcePosition() \n");
7514
7515 printf ("Sorry, not implemented \n");
7516 ROSE_ABORT();
7517 }
7518
7519 case e_sourcePositionNullPointers: // Set pointers to Sg_File_Info objects to NULL.
7520 {
7521 // DQ (2/17/2013): We want to move to this mode as the one used for EDG/ROSE connection so that we can
7522 // avoid building and rebuilding source position information.
7523#if 0
7524 printf ("e_sourcePositionNullPointers in SageInterface::setSourcePosition() \n");
7525#endif
7527 break;
7528 }
7529
7530 case e_sourcePositionFrontendConstruction: // Specify as source position to be filled in as part of AST construction in the front-end.
7531 {
7532 // DQ (2/17/2013): The setSourcePositionToDefault() function is called a lot, so it might be a performance issue.
7533 // All IR nodes built by the Build Interface are assighed source position information
7534 // using this function and then reset afterward as we use information within EDG to
7535 // reset the source position information. Ideally, the EDG/ROSE connection would
7536 // use NULL pointers as the behavior for the front-end mode. We can move to that
7537 // later to make the source position handling more efficient.
7538
7539 // This function builds an empty Sg_File_Info entry (valid object but filled with default values; must be reset in front-end processing).
7540#if 0
7541 printf ("e_sourcePositionFrontendConstruction in SageInterface::setSourcePosition() \n");
7542#endif
7543 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7544 if (locatedNode != NULL)
7545 {
7546 // setSourcePositionAtRootAndAllChildrenAsDefault(locatedNode);
7547 setSourcePositionToDefault(locatedNode);
7548 }
7549 else
7550 {
7551 // This is not supported (not clear if it need be).
7552 SgPragma* pragma = isSgPragma(node);
7553 if (pragma != NULL)
7554 {
7555 setSourcePositionToDefault(pragma);
7556 }
7557 else
7558 {
7559 // printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7560 // ROSE_ASSERT(false);
7561 SgType* type = isSgType(node);
7562 if (type != NULL)
7563 {
7564 // Ignore this case, OK.
7565 }
7566 else
7567 {
7568 SgFunctionParameterTypeList* functionParameterTypeList = isSgFunctionParameterTypeList(node);
7569 if (functionParameterTypeList != NULL)
7570 {
7571 // Ignore this case, OK.
7572 }
7573 else
7574 {
7575 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7576 ROSE_ABORT();
7577 }
7578 }
7579 }
7580 }
7581
7582 break;
7583 }
7584
7585
7587 {
7588 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7589 ROSE_ABORT();
7590 }
7591
7592 default:
7593 {
7594 printf ("Error: default reached in SageInterface::setSourcePosition() \n");
7595 break;
7596 }
7597 }
7598
7599#if 0
7600 if (node->get_file_info() != NULL)
7601 {
7602 node->get_file_info()->display("Leaving SageInterface::setSourcePosition()");
7603 }
7604#endif
7605 }
7606
7607#if 0
7608void
7609SageInterface::setSourcePositionForTransformation_memoryPool()
7610 {
7611 // DQ (1/24/2009): This seems like a very dangerous function to have, is it required!
7612
7613 // DQ (5/1/2012): Make it an error to call this function.
7614 printf ("ERROR: In setSourcePositionForTransformation_memoryPool(): This seems like a very dangerous function to have, is it required? \n");
7615 ROSE_ABORT();
7616
7617 VariantVector vv(V_SgNode);
7618 Rose_STL_Container<SgNode*> nodeList = NodeQuery::queryMemoryPool(vv);
7619 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++ )
7620 {
7622 }
7623 }
7624#endif
7625
7627 {
7628 // Liao, 1/9/2008, get the first global scope from current project
7629 // mostly used to prepare for AST construction under the global scope
7630 ROSE_ASSERT(project != NULL);
7631
7632 // DQ (1/24/2009): Added a check to make sure STL list is non-empty.
7633 ROSE_ASSERT(project->get_fileList().empty() == false);
7634
7635 // SgGlobal* global = project->get_file(0).get_root();
7636 SgSourceFile* file = isSgSourceFile(project->get_fileList()[0]);
7637 SgGlobal* global = file->get_globalScope();
7638
7639#if 0
7640 SgFilePtrListPtr fileList = project->get_fileList();
7641 SgFilePtrList::const_iterator i= fileList->begin();
7642
7643 SgGlobal* global = (*i)->get_globalScope();
7644#endif
7645 ROSE_ASSERT(global != NULL);
7646
7647 return global;
7648 }
7649
7650// Liao, 1/10/2008, get the last stmt from the scope
7651// two cases
7652// SgScopeStatement::getDeclarationList
7653// SgScopeStatement::getStatementList()
7655 {
7656 ROSE_ASSERT(scope);
7657 SgStatement* stmt = NULL;
7658
7659 if (scope->containsOnlyDeclarations())
7660 {
7661 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7662 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7663 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7664
7665 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7666 if (declList.empty() == false)
7667 {
7668 stmt = isSgStatement(declList.back());
7669 }
7670 }
7671 else
7672 {
7673 // DQ (2/17/2013): Fixed stmtList to be a reference instead of a copy.
7674 SgStatementPtrList & stmtList = scope->getStatementList();
7675
7676 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7677 if (stmtList.empty() == false)
7678 {
7679 stmt = stmtList.back();
7680 }
7681 }
7682
7683 return stmt;
7684 }
7685
7686
7687SgStatement* SageInterface::getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated/*=false*/)
7688 {
7689 // DQ (2/17/2013): This function appears to be a performance problem (so a pass was made to
7690 // use lower complexity operations that are equivalent in funcionality for this context).
7691
7692 ROSE_ASSERT(scope);
7693 SgStatement* stmt = NULL;
7694
7695 if (scope->containsOnlyDeclarations())
7696 {
7697 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7698 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7699 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7700 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7701 if (includingCompilerGenerated)
7702 {
7703 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7704 // DQ Note: (declList.empty() == false) is a much faster test O(1) than (declList.size() > 0), which is O(n).
7705 if (declList.empty() == false)
7706 {
7707 stmt = isSgStatement(declList.front());
7708 }
7709 }
7710 else
7711 {
7712 // skip compiler-generated declarations
7713 SgDeclarationStatementPtrList::iterator i=declList.begin();
7714 while (i != declList.end())
7715 {
7716 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7717 // some content from headers included are not marked as compiler-generated
7718 //
7719 // cout<<(*i)->unparseToString()<<endl;
7720 // ((*i)->get_file_info())->display("debug.......");
7721 Sg_File_Info * fileInfo = (*i)->get_file_info();
7722 // include transformation-generated statements, but not the hidden ones
7723 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7724 if ((fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation() && fileInfo->isOutputInCodeGeneration()))
7725 {
7726 stmt = *i;
7727 break;
7728 }
7729 else
7730 {
7731 i++;
7732 continue;
7733 }
7734 }
7735 }
7736 }
7737 else
7738 {
7739 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7740 SgStatementPtrList & stmtList = scope->getStatementList();
7741 if (includingCompilerGenerated)
7742 {
7743 // DQ (2/17/2013): Fixed evaluation of empty list use SgStatementPtrList::empty() member function for faster performance.
7744 // DQ Note: (stmtList.empty() == false) is a much faster test O(1) than (stmtList.size() > 0), which is O(n).
7745 if (stmtList.empty() == false)
7746 {
7747 stmt = stmtList.front();
7748 }
7749 }
7750 else
7751 {
7752 // skip compiler-generated declarations
7753 SgStatementPtrList::iterator i = stmtList.begin();
7754 while (i!=stmtList.end())
7755 {
7756 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7757 // some content from headers included are not marked as compiler-generated
7758 //
7759 // cout<<(*i)->unparseToString()<<endl;
7760 // ((*i)->get_file_info())->display("debug.......");
7761 Sg_File_Info * fileInfo = (*i)->get_file_info();
7762 // include transformation-generated statements, but not the hidden ones
7763 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7764 if ( (fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration()))
7765 {
7766 stmt=*i;
7767 break;
7768 }
7769 else
7770 {
7771 i++;
7772 continue;
7773 }
7774 }
7775 }
7776 }
7777
7778 return stmt;
7779 }
7780
7781
7783 {
7784 ROSE_ASSERT(scope);
7785 SgFunctionDeclaration* result = NULL;
7786 if (scope->containsOnlyDeclarations())
7787 {
7788 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7789 SgDeclarationStatementPtrList::iterator i=declList.begin();
7790 while (i!=declList.end())
7791 {
7792 Sg_File_Info * fileInfo = (*i)->get_file_info();
7793
7794 if ((fileInfo->isSameFile(scope->get_file_info()))||
7795 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7796 )
7797 {
7798 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7799 if (func)
7800 {
7801 if (func->get_definingDeclaration ()==func)
7802 {
7803 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7804 result=func;
7805 break;
7806 }
7807 }
7808 }
7809 i++;
7810 }//end while
7811 } else
7812 {
7813 SgStatementPtrList stmtList = scope->getStatementList();
7814 SgStatementPtrList::iterator i=stmtList.begin();
7815 while (i!=stmtList.end())
7816 {
7817 Sg_File_Info * fileInfo = (*i)->get_file_info();
7818 if ( (fileInfo->isSameFile(scope->get_file_info()))||
7819 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7820 )
7821 {
7822 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7823 if (func)
7824 {
7825 if (func->get_definingDeclaration ()==func)
7826 {
7827 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7828 result=func;
7829 break;
7830 }// if defining
7831 } // if func
7832 }// if fileInof
7833 i++;
7834 }//while
7835 } // end if
7836 return result;
7837 }
7838
7839
7841{
7842 bool result = false;
7843 // Liao 1/5/2010, handle Fortran main entry: SgProgramHeaderStatement
7845 if (isSgProgramHeaderStatement(n)) {
7846 result = true;
7847 }
7848 }
7849 else {
7850 if (isSgFunctionDeclaration(n) != nullptr) {
7851 bool either = false;
7853 either = true;
7854 }
7855 else {
7856 const SgStatement* stmnt = isSgStatement(n);
7857 ROSE_ASSERT(stmnt != nullptr);
7858 if (isSgGlobal(stmnt->get_scope())) {
7859 either = true;
7860 }
7861 }
7862 if (either) {
7863 const SgFunctionDeclaration* funcDefn = isSgFunctionDeclaration(n);
7864 ROSE_ASSERT(funcDefn != nullptr);
7865 if (funcDefn->get_name() == "main") {
7866 result = true;
7867 }
7868 }
7869 }
7870 }
7871 return result;
7872}
7873
7874// Originally from ompTranslator.C
7875// DQ (1/6/2007): The correct qualified name for "main" is "::main", at least in C++.
7876// however for C is should be "main". Our name qualification is not language specific,
7877// however, for C is makes no sense to as for the qualified name, so the name we
7878// want to search for could be language specific. The test code test2007_07.C
7879// demonstrates that the function "main" can exist in both classes (as member functions)
7880// and in namespaces (as more meaningfully qualified names). Because of this C++
7881// would have to qualify the global main function as "::main", I think.
7882
7883// Revised by Jeremiah,
7884// Added check to see if the scope is global: Liao
7886 if (!n) return 0;
7887 if (isMain(n))
7888 {
7889 return isSgFunctionDeclaration(n);
7890 }
7891 vector<SgNode*> children = n->get_traversalSuccessorContainer();
7892 for (vector<SgNode*>::const_iterator i = children.begin();
7893 i != children.end(); ++i) {
7894
7895 SgFunctionDeclaration* mainDecl = findMain(*i);
7896 if (mainDecl)
7897 if (mainDecl->get_definingDeclaration() == mainDecl) // skip non-defining main() declaration, Liao 8/27/2010
7898 return mainDecl;
7899 }
7900 return 0;
7901}
7902
7904// another declaration statement can be inserted.
7905// This is useful to find a safe place to insert a declaration statement with special requirements about where it can be inserted.
7906// e.g. a variable declaration statement should not be inserted before IMPLICIT none in Fortran
7907// If it returns NULL, a declaration statement should be able to be prepended to the scope
7909{
7910 SgStatement* rt = NULL;
7911 ROSE_ASSERT (scope != NULL);
7912
7913 SgStatementPtrList stmt_list = scope->generateStatementList ();
7914
7915 for (size_t i = 0; i<stmt_list.size(); i++)
7916 {
7917 SgStatement* cur_stmt = stmt_list[i];
7918 // We should exclude pragma decl. We don't want to insert things after pragmas.
7919 if (isSgDeclarationStatement(cur_stmt))
7920 {
7921 if (isSgPragmaDeclaration (cur_stmt))
7922 {
7923 if (includePragma)
7924 rt = cur_stmt;
7925 }
7926 else
7927 rt = cur_stmt;
7928 }
7929 //if (isSgImplicitStatement(cur_stmt)) || isSgFortranIncludeLine(cur_stmt) || isSgDeclarationStatement
7930 }
7931
7932 return rt;
7933}
7934
7936{
7937 SgNode* rt = NULL;
7938 SgTreeCopy g_treeCopy; // should use a copy object each time of usage!
7939 if (n!= NULL)
7940 {
7941 rt = n->copy (g_treeCopy);
7943 }
7944 // return n ? n->copy (g_treeCopy) : 0;
7945 return rt;
7946}
7947
7948// by Jeremiah
7949// Return bool for C++ code, and int for C code
7951 bool isC = TransformationSupport::getSourceFile(n)->get_outputLanguage() == SgFile::e_C_language;
7952 if (isC) {
7953 return SgTypeInt::createType();
7954 } else {
7955 return SgTypeBool::createType();
7956 }
7957}
7958
7959#if 1
7960// Change continue statements in a given block of code to gotos to a label
7962 {
7963#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
7964 std::vector<SgContinueStmt*> continues = SageInterface::findContinueStmts(stmt);
7965 for (std::vector<SgContinueStmt*>::iterator i = continues.begin(); i != continues.end(); ++i)
7966 {
7967 SgGotoStatement* gotoStatement = SageBuilder::buildGotoStatement(label);
7968 // printf ("Building gotoStatement #1 = %p \n",gotoStatement);
7969#ifndef _MSC_VER
7970 LowLevelRewrite::replace(*i, make_unit_list( gotoStatement ) );
7971#else
7972 ROSE_ABORT();
7973#endif
7974 }
7975#else
7976 printf ("Not supported in mode: ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT (LowLevelRewrite::replace() is unavailable)");
7977 ROSE_ABORT();
7978#endif
7979 }
7980
7981#define DEBUG_TEMPLATE_ARG_EQUIVALENCE 0
7982
7984 {
7985 if (arg1 == arg2)
7986 {
7987#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7988 printf ("In templateArgumentEquivalence(): same pointer to template argument: returning true \n");
7989#endif
7990 return true;
7991 }
7992
7993 if (arg1->get_argumentType() != arg2->get_argumentType())
7994 {
7995#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7996 printf ("In templateArgumentEquivalence(): different argumentType(): returning false \n");
7997#endif
7998 return false;
7999 }
8000
8001 switch (arg1->get_argumentType())
8002 {
8004 {
8005 ROSE_ASSERT(arg1->get_type() != NULL);
8006 ROSE_ASSERT(arg2->get_type() != NULL);
8007
8008#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8009 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: arg1->get_type() = %p = %s arg2->get_type() = %p = %s \n",
8010 arg1->get_type(),arg1->get_type()->class_name().c_str(),
8011 arg2->get_type(),arg2->get_type()->class_name().c_str());
8012#endif
8013 // DQ (5/19/2016): Rewrote to support debugging.
8014 // return arg1->get_type() == arg2->get_type();
8015 if (arg1->get_type() == arg2->get_type())
8016 {
8017#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8018 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: returning true \n");
8019#endif
8020 return true;
8021 }
8022 else
8023 {
8024 // ROSE_ASSERT(!"NIY: non-type template argument comparaison."); /// \todo
8025
8026 // DQ (5/19/2016): Use type equivalence mechanism to handle the case where
8027 // these are different pointers to what might still be the same type.
8028 // return false;
8029 bool typesAreEqual = isEquivalentType(arg1->get_type(),arg2->get_type());
8030
8031#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8032 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: pointers are different: returning typesAreEqual = %s \n",typesAreEqual ? "true" : "false");
8033#endif
8034 return typesAreEqual;
8035 }
8036 }
8037
8039 {
8040 SgExpression * expr1 = arg1->get_expression();
8041 SgExpression * expr2 = arg2->get_expression();
8042 if (expr1 == expr2) {
8043#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8044 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: checking for the same expression: returning true \n");
8045#endif
8046 return true;
8047 } else if (expr1->variantT() == expr2->variantT() ) {
8048#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8049 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: same variant of expression: %s\n", expr1->class_name().c_str());
8050#endif
8051 switch (expr1->variantT()) {
8052 case V_SgLongIntVal: {
8053 return ((SgLongIntVal *)expr1)->get_value() == ((SgLongIntVal *)expr2)->get_value();
8054 }
8055 default: {
8056 printf ("FATAL: In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: expression have the same variant %s but comparison is not NIY!\n", expr1->class_name().c_str());
8057 ROSE_ABORT();
8058 }
8059 }
8060 } else {
8061#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8062 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: different variant of expression: returning false \n");
8063#endif
8064 return false;
8065 }
8066 }
8067
8069 {
8070 if (arg1->get_templateDeclaration() == arg2->get_templateDeclaration())
8071 {
8072#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8073 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::template_template_argument: checking for the same templateDeclaration: returning true \n");
8074#endif
8075 return true;
8076 }
8077 else
8078 {
8079 ROSE_ASSERT(!"NIY: template template argument comparaison.");
8080 }
8081 }
8082
8084 {
8085 ROSE_ASSERT(!"Try to compare template arguments of unknown type...");
8086 }
8087
8088 // DQ (7/19/2015): Added missing case:
8090 {
8091 // Liao 6/24/2016. Handle the simplest case: both arguments are parameter pack.
8093 return true;
8094 ROSE_ASSERT(!"Try to compare template arguments of unknown type start_of_pack_expansion_argument");
8095 }
8096
8097 // DQ (7/19/2015): Added missing default case: we always want to ahve a default case to catch errors and missing cases.
8098 default:
8099 {
8100 printf ("Error: default case not handled! \n");
8101 ROSE_ABORT();
8102 }
8103 }
8104
8105 ROSE_ABORT(); // unreachable code
8106 }
8107
8108#define DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE 0
8109
8110bool SageInterface::templateArgumentListEquivalence(const SgTemplateArgumentPtrList & list1, const SgTemplateArgumentPtrList & list2)
8111 {
8112 if (list1.size() != list2.size())
8113 {
8114#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8115 printf ("In templateArgumentListEquivalence(): different list sizes: returning false \n");
8116 printf (" --- list1.size() = %zu \n",list1.size());
8117 printf (" --- list2.size() = %zu \n",list2.size());
8118#endif
8119 return false;
8120 }
8121
8122 if (list1 == list2)
8123 {
8124#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8125 printf ("In templateArgumentListEquivalence(): same list using STL equality operator: returning true \n");
8126#endif
8127 return true;
8128 }
8129
8130 // for (unsigned i = 0; i < list1.size(); i++)
8131 for (size_t i = 0; i < list1.size(); i++)
8132 {
8133#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8134 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu \n",i);
8135#endif
8136 // if (!templateArgumentEquivalence(list1[i], list2[i]))
8137 if (templateArgumentEquivalence(list1[i], list2[i]) == false)
8138 {
8139#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8140 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu --- returned false: returning false \n",i);
8141#endif
8142 return false;
8143 }
8144 }
8145
8146#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8147 printf ("In templateArgumentListEquivalence(): reached base of function: returning true \n");
8148#endif
8149
8150 return true;
8151 }
8152
8153// Add a step statement to the end of a loop body
8154// Add a new label to the end of the loop, with the step statement after
8155// it; then change all continue statements in the old loop body into
8156// jumps to the label
8157//
8158// For example:
8159// while (a < 5) {if (a < -3) continue;} (adding "a++" to end) becomes
8160// while (a < 5) {if (a < -3) goto label; label: a++;}
8162 using namespace SageBuilder;
8164 SgStatement* old_body = SageInterface::getLoopBody(loopStmt);
8165 SgBasicBlock* new_body = buildBasicBlock();
8166// printf ("Building IR node #13: new SgBasicBlock = %p \n",new_body);
8167 SgName labelname = "rose_label__";
8168 labelname << ++gensym_counter;
8169 SgLabelStatement* labelstmt = buildLabelStatement(labelname,
8170buildBasicBlock(), proc);
8171 changeContinuesToGotos(old_body, labelstmt);
8172 appendStatement(old_body, new_body);
8173 appendStatement(labelstmt, new_body);
8174 appendStatement(step, new_body);
8175 SageInterface::setLoopBody(loopStmt, new_body);
8176}
8177
8178
8180 if (isSgNullExpression(f->get_increment())) return;
8181 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(f->get_increment());
8182 f->get_increment()->set_parent(incrStmt);
8185 f->set_increment(ne);
8186 ne->set_parent(f);
8187}
8188
8189static
8190bool hasEmptyCondition(SgForStatement* f)
8191{
8192 ROSE_ASSERT(f);
8193
8194 SgStatement* condstmt = f->get_test();
8195 ROSE_ASSERT(condstmt);
8196
8197 if (isSgNullStatement(condstmt)) return true;
8198
8199 SgExprStatement* exprStmt = isSgExprStatement(condstmt);
8200
8201 return isSgNullExpression(exprStmt->get_expression());
8202}
8203
8208 SgStatementPtrList& bbStmts = bb->get_statements();
8209 SgStatementPtrList& initStmts = inits->get_init_stmt();
8210 bbStmts = initStmts;
8211 for (size_t i = 0; i < bbStmts.size(); ++i) {
8212 bbStmts[i]->set_parent(bb);
8213 }
8214
8215 const bool testIsNull = hasEmptyCondition(f);
8217 : f->get_test();
8219
8220 appendStatement(ws, bb);
8221 isSgStatement(f->get_parent())->replace_statement(f, bb);
8222}
8223
8225 Rose_STL_Container<SgNode*> fors = NodeQuery::querySubTree(top,
8226V_SgForStatement);
8227 for (size_t i = 0; i < fors.size(); ++i) {
8228 convertForToWhile(isSgForStatement(fors[i]));
8229 }
8230}
8231
8232 vector<SgGotoStatement*> SageInterface::findGotoStmts(SgStatement* scope, SgLabelStatement* l) {
8233 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8234 // But we still need the copy since the return type is IR node specific.
8235 Rose_STL_Container<SgNode*> allGotos = NodeQuery::querySubTree(scope, V_SgGotoStatement);
8236
8237 vector<SgGotoStatement*> result;
8238 for (Rose_STL_Container<SgNode*>::const_iterator i = allGotos.begin(); i != allGotos.end(); ++i) {
8239 if (isSgGotoStatement(*i)->get_label() == l) {
8240 result.push_back(isSgGotoStatement(*i));
8241 }
8242 }
8243 return result;
8244 }
8245
8246#if 0 // Liao 5/21/2010. This is a bad function in terms of performance
8247 // vectors are created/destroyed multiple times
8248 vector<SgReturnStmt*> SageInterface::findReturnStmts(SgStatement* scope) {
8249 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8250 // But we still need the copy since the return type is IR node specific.
8251 Rose_STL_Container<SgNode*> returns = NodeQuery::querySubTree(scope, V_SgReturnStmt);
8252
8253 vector<SgReturnStmt*> result;
8254 for (Rose_STL_Container<SgNode*>::const_iterator i = returns.begin(); i != returns.end(); ++i) {
8255 result.push_back(isSgReturnStmt(*i));
8256 }
8257 return result;
8258 }
8259
8260#endif
8261static void getSwitchCasesHelper(SgStatement* top, vector<SgStatement*>& result) {
8262 ROSE_ASSERT (top);
8263 if (isSgSwitchStatement(top)) return; // Don't descend into nested switches
8264 if (isSgCaseOptionStmt(top) || isSgDefaultOptionStmt(top)) {
8265 result.push_back(top);
8266 }
8267 vector<SgNode*> children = top->get_traversalSuccessorContainer();
8268 for (unsigned int i = 0; i < children.size(); ++i) {
8269 if (isSgStatement(children[i])) {
8270 getSwitchCasesHelper(isSgStatement(children[i]), result);
8271 }
8272 }
8273 }
8274
8276 vector<SgStatement*> result;
8277 getSwitchCasesHelper(sw->get_body(), result);
8278 return result;
8279 }
8280
8281
8282#endif
8283
8290SgScopeStatement* SageInterface::getEnclosingScope(SgNode* n, const bool includingSelf/* =false*/)
8291{
8292 SgScopeStatement* result = getScope (n);
8293 if (result == n)
8294 {
8295 if (!includingSelf)
8296 result = getScope(n->get_parent());
8297 }
8298 return result;
8299}
8300
8301// from transformationSupport.C
8304 {
8305
8306 // Case 1: directly call get_scope() for some types of nodes
8307 if (const SgSymbol* symbol = isSgSymbol(astNode))
8308 return symbol->get_scope();
8309 else if (const SgInitializedName* initName = isSgInitializedName(astNode))
8310 return initName->get_scope();
8311 else if (const SgTemplateArgument* tempArg = isSgTemplateArgument(astNode))
8312 return tempArg->get_scope();
8313 else if (const SgQualifiedName* qualifiedName = isSgQualifiedName(astNode))
8314 return qualifiedName->get_scope();
8315
8316 // DQ (6/9/2007): This function traverses through the parents to the first scope (used for name qualification support of template arguments)
8317 const SgNode* parentNode = astNode;
8318 while (!isSgScopeStatement(parentNode))
8319 {
8320 //George Vulov (11/29/2010)
8321 //Function parameter lists are siblings of SgFunctionDefinition, so just going up to parents
8322 //produces SgGlobal.
8323 if (isSgFunctionParameterList(parentNode) || isSgCtorInitializerList(parentNode))
8324 {
8325 const SgFunctionDeclaration* funcDeclaration = isSgFunctionDeclaration(parentNode->get_parent());
8326 ROSE_ASSERT(funcDeclaration != NULL);
8327 funcDeclaration = isSgFunctionDeclaration(funcDeclaration->get_definingDeclaration());
8328 if (funcDeclaration != NULL)
8329 {
8330 return funcDeclaration->get_definition();
8331 }
8332 }
8333
8334 parentNode = parentNode->get_parent();
8335 if (parentNode == NULL)
8336 {
8337 break;
8338 }
8339 }
8340
8341 // Check to see if we made it back to the root (current root is SgProject).
8342 // It is also OK to stop at a node for which get_parent() returns NULL (SgType and SgSymbol nodes).
8343 if ( isSgScopeStatement(parentNode) == NULL &&
8344 dynamic_cast<const SgType*>(parentNode) == NULL &&
8345 dynamic_cast<const SgSymbol*>(parentNode) == NULL )
8346 {
8347 printf ("Error: In SageInterface::getScope(): could not trace back to SgScopeStatement node \n");
8348 ROSE_ABORT();
8349 }
8350 else
8351 {
8352 if ( dynamic_cast<const SgType*>(parentNode) != NULL || dynamic_cast<const SgSymbol*>(parentNode) != NULL )
8353 {
8354 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());
8355 return NULL;
8356 }
8357 }
8358
8359 // Make sure we have a SgStatement node
8360 const SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8361 //SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8362 ROSE_ASSERT (scopeStatement != NULL);
8363
8364 // ensure the search is inclusive
8365 if (isSgScopeStatement(astNode))
8366 if (isSgScopeStatement(parentNode))
8367 {
8368 ROSE_ASSERT (astNode == parentNode);
8369 }
8370
8371 // return scopeStatement;
8372 return const_cast<SgScopeStatement*>(scopeStatement);
8373 }
8374
8375
8376// from outliner, ASTtools
8377// ------------------------------------------------
8378
8386static
8387const SgVariableSymbol *
8388getVarSymFromName_const (const SgInitializedName* name)
8389 {
8390 SgVariableSymbol* v_sym = NULL;
8391
8392 if (name != NULL)
8393 {
8394#if 0
8395 printf ("In getVarSymFromName(): name->get_name() = %s \n",name->get_name().str());
8396#endif
8397 SgScopeStatement* scope = name->get_scope();
8398 ROSE_ASSERT (scope != NULL);
8399#if 0
8400 printf ("In getVarSymFromName(): name->get_name() = %s scope = %p = %s \n",name->get_name().str(),scope,scope->class_name().c_str());
8401#endif
8402 v_sym = scope->lookup_var_symbol (name->get_name());
8403
8404 if (!v_sym) // E.g., might be part of an 'extern' declaration.
8405 {
8406 // Try the declaration's scope.
8407 SgDeclarationStatement* decl = name->get_declaration ();
8408 ROSE_ASSERT (decl);
8409
8410 SgScopeStatement* decl_scope = decl->get_scope ();
8411 if (decl_scope != NULL)
8412 v_sym = decl_scope->lookup_var_symbol (name->get_name());
8413
8414 if (!v_sym)
8415 cerr << "\t\t*** WARNING: Can't seem to find a symbol for '"
8416 << name->get_name ().str ()
8417 << "' ***" << endl;
8418 }
8419 }
8420
8421 return v_sym;
8422 }
8423
8424#if 0
8432static
8434getVarSymFromName (SgInitializedName* name)
8435{
8436 const SgVariableSymbol* v_sym = getVarSymFromName_const (name);
8437 return const_cast<SgVariableSymbol *> (v_sym);
8438}
8439#endif
8444static
8445const SgVariableSymbol *
8446getVarSym_const (const SgNode* n)
8447{
8448 const SgVariableSymbol* v_sym = 0;
8449 switch (n->variantT ())
8450 {
8451 case V_SgVarRefExp:
8452 v_sym = isSgVarRefExp (n)->get_symbol ();
8453 break;
8454 case V_SgInitializedName:
8455 v_sym = getVarSymFromName_const (isSgInitializedName (n));
8456 break;
8457 default:
8458 break;
8459 }
8460 return v_sym;
8461}
8462
8463#if 0
8468static
8470getVarSym (SgNode* n)
8471{
8472 const SgVariableSymbol* v_sym = getVarSym_const (n);
8473 return const_cast<SgVariableSymbol *> (v_sym);
8474}
8475#endif
8476
8477static
8478const SgVariableSymbol *
8479getFirstVarSym_const (const SgVariableDeclaration* decl)
8480{
8481 if (!decl) return 0;
8482 const SgInitializedNamePtrList& names = decl->get_variables ();
8483 if (names.begin () != names.end ())
8484 {
8485 const SgInitializedName* name = *(names.begin ());
8486 return getVarSym_const (name);
8487 }
8488 else
8489 return 0;
8490}
8491
8494{
8495 const SgVariableSymbol* sym = getFirstVarSym_const (decl);
8496 return const_cast<SgVariableSymbol *> (sym);
8497}
8498
8499
8502{
8503 ROSE_ASSERT(decl);
8504 SgInitializedNamePtrList& names = decl->get_variables ();
8505 if (names.begin () != names.end ())
8506 return *(names.begin ());
8507 else
8508 return NULL;
8509}
8510
8511
8512static void findBreakStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgBreakStmt*>& breakStmts) {
8513 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code) || isSgSwitchStatement(code)) {
8514 if (fortranLabel == "") {
8515 // Outermost loop only
8516 return;
8517 } else {
8518 // Set this for query on children
8519 inOutermostBody = false;
8520 }
8521 }
8522 if (isSgBreakStmt(code)) {
8523 SgBreakStmt* bs = isSgBreakStmt(code);
8524 bool breakMatchesThisConstruct = false;
8525 if (bs->get_do_string_label() == "") {
8526 // Break matches closest construct
8527 breakMatchesThisConstruct = inOutermostBody;
8528 } else {
8529 breakMatchesThisConstruct = (fortranLabel == bs->get_do_string_label());
8530 }
8531 if (breakMatchesThisConstruct) {
8532 breakStmts.push_back(bs);
8533 }
8534 return;
8535 }
8536 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8537 for (unsigned int i = 0; i < children.size(); ++i) {
8538 if (isSgStatement(children[i])) {
8539 findBreakStmtsHelper(isSgStatement(children[i]), fortranLabel, inOutermostBody, breakStmts);
8540 }
8541 }
8542}
8543
8544vector<SgBreakStmt*> SageInterface::findBreakStmts(SgStatement* code, const std::string& fortranLabel) {
8545 // Run this on the body of a loop or switch, because it stops at any
8546 // construct which defines a new scope for break statements
8547 vector<SgBreakStmt*> result;
8548 findBreakStmtsHelper(code, fortranLabel, true, result);
8549 return result;
8550}
8551
8552
8553static void findContinueStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgContinueStmt*>& continueStmts) {
8554 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code)) {
8555 if (fortranLabel == "") {
8556 // Outermost loop only
8557 return;
8558 } else {
8559 // Set this for query on children
8560 inOutermostBody = false;
8561 }
8562 }
8563 if (isSgContinueStmt(code)) {
8564 SgContinueStmt* cs = isSgContinueStmt(code);
8565 bool continueMatchesThisConstruct = false;
8566 if (cs->get_do_string_label() == "") {
8567 // Continue matches closest construct
8568 continueMatchesThisConstruct = inOutermostBody;
8569 } else {
8570 continueMatchesThisConstruct = (fortranLabel == cs->get_do_string_label());
8571 }
8572 if (continueMatchesThisConstruct) {
8573 continueStmts.push_back(cs);
8574 }
8575 return;
8576 }
8577 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8578 for (unsigned int i = 0; i < children.size(); ++i) {
8579 SgStatement* stmnt = isSgStatement(children[i]);
8580 if (stmnt != NULL) {
8581 findContinueStmtsHelper(stmnt, fortranLabel, inOutermostBody, continueStmts);
8582 }
8583 }
8584}
8585
8586vector<SgContinueStmt*> SageInterface::findContinueStmts(SgStatement* code, const std::string& fortranLabel) {
8587 // Run this on the body of a loop, because it stops at any construct which
8588 // defines a new scope for continue statements
8589 vector<SgContinueStmt*> result;
8590 findContinueStmtsHelper(code, fortranLabel, true, result);
8591 return result;
8592}
8593
8594
8595// Get the initializer containing an expression if it is within an
8596// initializer.
8597// from replaceExpressionWithStatement.C
8599 assert(n);
8600#if 0
8601 std::cout << "Starting getInitializerOfExpression on 0x" << std::hex << (int)n << ", which has type " << n->sage_class_name() << std::endl;
8602#endif
8603 while (!isSgInitializer(n)) {
8604 n = isSgExpression(n->get_parent());
8605#if 0
8606 std::cout << "Continuing getInitializerOfExpression on 0x" << std::hex << (int)n;
8607 if (n) std::cout << ", which has type " << n->sage_class_name();
8608 std::cout << std::endl;
8609#endif
8610 assert(n);
8611 }
8612 return isSgInitializer(n);
8613}
8614
8615#ifndef USE_ROSE
8616// Get all symbols used in a given expression
8618 class GetSymbolsUsedInExpressionVisitor: public AstSimpleProcessing {
8619 public:
8620 std::vector<SgVariableSymbol*> symbols;
8621
8622 virtual void visit(SgNode* n) {
8623 if (isSgVarRefExp(n))
8624 symbols.push_back(isSgVarRefExp(n)->get_symbol());
8625 }
8626 };
8627
8628 GetSymbolsUsedInExpressionVisitor vis;
8629 vis.traverse(expr, preorder);
8630 return vis.symbols;
8631}
8632#endif
8633
8636 return getEnclosingNode<SgSourceFile>(n, includingSelf);
8637}
8638
8639
8641{
8642 return findDeclarationStatement<SgFunctionDeclaration> (root, name, scope, isDefining);
8643}
8644
8645
8647{
8648 return getEnclosingFunctionDefinition(n,includingSelf);
8649}
8650
8653 return getEnclosingNode<SgFunctionDefinition>(n, includingSelf);
8654}
8655
8656
8659 return getEnclosingNode<SgFunctionDeclaration>(astNode, includingSelf);
8660}
8661
8662// #endif
8663
8664// #ifndef USE_ROSE
8665
8666SgGlobal*
8668 // should including itself in this case
8669 return getEnclosingNode<SgGlobal>(astNode, true /*includingSelf*/);
8670}
8671
8673SageInterface::getEnclosingClassDefinition(SgNode* astNode, const bool includingSelf/* =false*/) {
8674 return getEnclosingNode<SgClassDefinition>(astNode, includingSelf);
8675}
8676
8677
8680 // DQ (1/24/2019): This might have to get the SgClassDefinition and then the SgClassDeclaration from that.
8681 // I'm having trouble making this work for a member function declared outside of the class definition.
8682 return getEnclosingNode<SgClassDeclaration>(astNode, true);
8683}
8684
8686SageInterface::getEnclosingExprListExp(SgNode* astNode, const bool includingSelf/* =false*/) {
8687 return getEnclosingNode<SgExprListExp>(astNode, includingSelf);
8688}
8689
8690bool
8692 {
8693 bool returnValue = false;
8694
8695 struct Visitor: public AstSimpleProcessing
8696 {
8697 SgExpression* expression_target;
8698 bool in_subtree;
8699 virtual void visit(SgNode* n)
8700 {
8701 if (n == expression_target)
8702 {
8703 in_subtree = true;
8704 }
8705 }
8706
8707 Visitor(SgExpression* expr) : expression_target(expr), in_subtree(false) {}
8708 };
8709
8710 Visitor traversal(exp);
8711
8712 traversal.traverse(subtree, preorder);
8713
8714 returnValue = traversal.in_subtree;
8715
8716 return returnValue;
8717 }
8718
8719
8722 {
8723 // DQ (2/7/2019): Added more general function to support extraction of the associated function declaration.
8724 // The lower level functions are more robust on the SgFunctionRefExp and SgMemberFunctionRefExp than
8725 // when called on the SgFunctionCallExp for example.
8726
8727 // SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
8728 ROSE_ASSERT (functionCallExp != NULL);
8729
8730 SgExpression* expression = functionCallExp->get_function();
8731 ROSE_ASSERT (expression != NULL);
8732
8733 SgFunctionDeclaration* returnDeclaration = NULL;
8734
8735 SgDotExp* dotExp = isSgDotExp(expression);
8736 if (dotExp != NULL)
8737 {
8738 ROSE_ASSERT (dotExp != NULL);
8739
8740 SgExpression* rhsOperand = dotExp->get_rhs_operand();
8741 ROSE_ASSERT (rhsOperand != NULL);
8742
8743 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8744
8745 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8746 if (memberFunctionRefExp != NULL)
8747 {
8748 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8749 }
8750 }
8751
8752 SgFunctionRefExp* functionReferenceExp = isSgFunctionRefExp(expression);
8753 if (functionReferenceExp != NULL)
8754 {
8755 returnDeclaration = functionReferenceExp->getAssociatedFunctionDeclaration();
8756 }
8757
8758 SgArrowExp* arrowExp = isSgArrowExp(expression);
8759 if ( arrowExp != NULL)
8760 {
8761 ROSE_ASSERT (arrowExp != NULL);
8762
8763 SgExpression* rhsOperand = arrowExp->get_rhs_operand();
8764 ROSE_ASSERT (rhsOperand != NULL);
8765
8766 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8767
8768 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8769 if (memberFunctionRefExp != NULL)
8770 {
8771 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8772 }
8773 }
8774
8775 return returnDeclaration;
8776 }
8777
8778
8779
8780std::list<SgClassType*>
8782 {
8783 // DQ (2/16/2019): This version support for data member name qualification return type chains.
8784
8785#define DEBUG_DATA_MEMBER_TYPE_CHAIN 0
8786
8787 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
8788 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
8789 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
8790
8791 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
8792
8793 std::list<SgClassType*> returnTypeChain;
8794
8795 // Internal list used to filter the class chain generated from chained SgCastExp objects to identify the subset containing an ambiguity.
8796 std::list<SgClassType*> classChain;
8797
8798 // Make sure this is at least a reference to a data or member function member.
8799 // The requirements for these functions are different, however, if they were
8800 // virtual functions it might be a more attractive design.
8801 if (varRefExp != NULL)
8802 {
8803 ROSE_ASSERT(isDataMemberReference(varRefExp) == true);
8804 }
8805 else
8806 {
8807 ROSE_ASSERT(memberFunctionRefExp != NULL);
8808 ROSE_ASSERT(isMemberFunctionMemberReference(memberFunctionRefExp) == true);
8809 }
8810
8811 SgNode* parent = refExp->get_parent();
8812 ROSE_ASSERT(parent != NULL);
8813
8814#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8815 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): parent = %p = %s \n",parent,parent->class_name().c_str());
8816#endif
8817
8818 SgArrowExp* arrowExp = isSgArrowExp(parent);
8819 SgDotExp* dotExp = isSgDotExp(parent);
8820
8821 SgBinaryOp* binaryOperator = NULL;
8822
8823 if (arrowExp != NULL)
8824 {
8825#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8826 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an arrow expression \n");
8827#endif
8828 binaryOperator = arrowExp;
8829 }
8830
8831 if (dotExp != NULL)
8832 {
8833#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8834 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an dot expression \n");
8835#endif
8836 binaryOperator = dotExp;
8837 }
8838
8839 // ROSE_ASSERT(binaryOperator != NULL);
8840 if (binaryOperator != NULL)
8841 {
8842 SgExpression* lhs = binaryOperator->get_lhs_operand();
8843 ROSE_ASSERT(lhs != NULL);
8844
8845#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8846 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs = %p = %s \n",lhs,lhs->class_name().c_str());
8847#endif
8848
8849 // Looking for a chain of SgCastExp expressions.
8850 SgExpression* temp_lhs = lhs;
8851 SgCastExp* cast = NULL;
8852 while (isSgCastExp(temp_lhs) != NULL)
8853 {
8854 cast = isSgCastExp(temp_lhs);
8855 ROSE_ASSERT(cast != NULL);
8856 temp_lhs = cast->get_operand();
8857
8858#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8859 printf ("Top of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8860#endif
8861 ROSE_ASSERT(cast->get_type() != NULL);
8862 SgClassType* classType = isSgClassType(cast->get_type());
8863 if (classType == NULL)
8864 {
8865#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8866 printf (" --- looking for base type: In SageInterface::getClassTypeChainForDataMemberReference(): classType == NULL: cast->get_type() = %p = %s \n",
8867 cast->get_type(),cast->get_type()->class_name().c_str());
8868#endif
8869 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);
8870 ROSE_ASSERT(baseType != NULL);
8871
8872#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8873 printf (" --- baseType = %p = %s name = %s \n",baseType,baseType->class_name().c_str(),get_name(baseType).c_str());
8874#endif
8875 classType = isSgClassType(baseType);
8876 }
8877 // ROSE_ASSERT(classType != NULL);
8878
8879 ROSE_ASSERT(temp_lhs != NULL);
8880
8881#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8882 printf (" --- temp_lhs = %p = %s name = %s \n",temp_lhs,temp_lhs->class_name().c_str(),get_name(temp_lhs).c_str());
8883#endif
8884
8885#if 1
8886 // DQ (1/20/2020): This (original) code works fine.
8887 // returnTypeChain.push_front(classType);
8888 if (classType != NULL)
8889 {
8890 classChain.push_front(classType);
8891 }
8892#else
8893 // DQ (1/20/2020): This (new) code works for Cxx11_tests/test2020_61.C.
8894 if (classType != NULL)
8895 {
8896 // DQ (1/20/2020): We might want to fully resolve the class types associated with this cast here directly
8897 // (see Cxx11_tests/test2020_61.C). The point is that we need a qualified name that will reflect all of
8898 // the class declarations from the temp_lhs to the declarations associated with the classType.
8899 // The steps are:
8900 // 1) Get the target class definition for the type represented by the temp_lhs.
8901 // 2) Get the source class definition for the classType.
8902 // 3) Iterate from the source class definition to the target class definition, and save the associated
8903 // types associated with the class declarations associated with the scopes visited.
8904 SgType* target_type = temp_lhs->get_type();
8905 ROSE_ASSERT(target_type != NULL);
8906 SgClassType* target_classType = isSgClassType(target_type);
8907 // ROSE_ASSERT(target_classType != NULL);
8908 if (target_classType != NULL)
8909 {
8910 SgDeclarationStatement* target_declaration = target_classType->get_declaration();
8911 ROSE_ASSERT(target_declaration != NULL);
8912 SgClassDeclaration* target_classDeclaration = isSgClassDeclaration(target_declaration);
8913 ROSE_ASSERT(target_classDeclaration != NULL);
8914 SgClassDeclaration* target_definingClassDeclaration = isSgClassDeclaration(target_classDeclaration->get_definingDeclaration());
8915 ROSE_ASSERT(target_definingClassDeclaration != NULL);
8916 SgScopeStatement* target_scope = target_definingClassDeclaration->get_definition();
8917 ROSE_ASSERT(target_scope != NULL);
8918
8919#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8920 printf ("target_classDeclaration = %p = %s name = %s target_scope = %p = %s \n",
8921 target_classDeclaration,target_classDeclaration->class_name().c_str(),target_classDeclaration->get_name().str(),target_scope,target_scope->class_name().c_str());
8922#endif
8923 SgClassType* source_classType = classType;
8924 ROSE_ASSERT(source_classType != NULL);
8925 SgDeclarationStatement* source_declaration = source_classType->get_declaration();
8926 ROSE_ASSERT(source_declaration != NULL);
8927 SgClassDeclaration* source_classDeclaration = isSgClassDeclaration(source_declaration);
8928 ROSE_ASSERT(source_classDeclaration != NULL);
8929 SgClassDeclaration* source_definingClassDeclaration = isSgClassDeclaration(source_classDeclaration->get_definingDeclaration());
8930 ROSE_ASSERT(source_definingClassDeclaration != NULL);
8931 SgScopeStatement* source_scope = source_definingClassDeclaration->get_definition();
8932 ROSE_ASSERT(source_scope != NULL);
8933
8934#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8935 printf ("source_classDeclaration = %p = %s name = %s source_scope = %p = %s \n",
8936 source_classDeclaration,source_classDeclaration->class_name().c_str(),source_classDeclaration->get_name().str(),source_scope,source_scope->class_name().c_str());
8937#endif
8938 SgScopeStatement* tmp_scope = source_scope;
8939 while (tmp_scope != NULL && tmp_scope != target_scope)
8940 {
8941#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8942 printf ("tmp_scope = %p = %s \n",tmp_scope,tmp_scope->class_name().c_str());
8943#endif
8944 SgClassDefinition* tmp_classDefinition = isSgClassDefinition(tmp_scope);
8945 ROSE_ASSERT(tmp_classDefinition != NULL);
8946 SgClassDeclaration* tmp_classDeclaration = tmp_classDefinition->get_declaration();
8947 ROSE_ASSERT(tmp_classDeclaration != NULL);
8948
8949#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8950 SgName scope_name = tmp_classDeclaration->get_name();
8951 printf ("scope_name = %s \n",scope_name.str());
8952#endif
8953 SgClassType* tmp_classType = tmp_classDeclaration->get_type();
8954 ROSE_ASSERT(tmp_classType != NULL);
8955
8956 // classChain.push_front(tmp_classDefinition);
8957 classChain.push_front(tmp_classType);
8958
8959 tmp_scope = tmp_scope->get_scope();
8960
8961 if (isSgGlobal(tmp_scope) != NULL)
8962 {
8963 tmp_scope = NULL;
8964 }
8965 }
8966 }
8967 else
8968 {
8969#if 1
8970 printf ("In loop processing cast: target_type = %p = %s \n",target_type,target_type->class_name().c_str());
8971#endif
8972 }
8973 }
8974#endif
8975
8976#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8977 printf ("Bottom of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8978#endif
8979 }
8980
8981 // 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.
8982
8983 ROSE_ASSERT(temp_lhs != NULL);
8984
8985#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8986 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
8987#endif
8988
8989 SgVarRefExp* derivedClassVarRefExp = isSgVarRefExp(temp_lhs);
8990 if (derivedClassVarRefExp != NULL)
8991 {
8992 SgVariableSymbol* derivedClassVariableSymbol = derivedClassVarRefExp->get_symbol();
8993 ROSE_ASSERT(derivedClassVariableSymbol != NULL);
8994
8995 SgName derivedClassVariableName = derivedClassVariableSymbol->get_name();
8996
8997#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8998 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): derivedClassVariableName = %s \n",derivedClassVariableName.str());
8999#endif
9000 // SgType* type = cast->get_type();
9001 SgType* type = temp_lhs->get_type();
9002 ROSE_ASSERT(type != NULL);
9003
9004#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9005 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s \n",type,type->class_name().c_str());
9006#endif
9007
9008 // 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);
9009 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);
9010
9011#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9012 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type = %p = %s \n",stripped_type,stripped_type->class_name().c_str());
9013#endif
9014
9015 // SgClassType* classType = isSgClassType(type);
9016 SgClassType* classType = isSgClassType(stripped_type);
9017
9018 // ROSE_ASSERT(classType != NULL);
9019 if (classType != NULL)
9020 {
9021#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9022 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classType = %p = %s \n",classType,classType->class_name().c_str());
9023 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
9024 ROSE_ASSERT(classDeclaration != NULL);
9025 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classDeclaration = %p = %s name = %s \n",
9026 classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9027#endif
9028 // This is where we want the SgVarRefExp data member qualification to start.
9029 // returnType = classType;
9030 // returnTypeChain.push_front(classType);
9031 classChain.push_front(classType);
9032 }
9033 else
9034 {
9035#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9036 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type is not a SgClassType \n");
9037#endif
9038 }
9039 }
9040 else
9041 {
9042#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9043 printf ("Need to support alternative to SgVarRefExp: temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
9044#endif
9045 SgType* type = temp_lhs->get_type();
9046 ROSE_ASSERT(type != NULL);
9047
9048#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9049 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s name = %s \n",type,type->class_name().c_str(),get_name(type).c_str());
9050#endif
9051
9052 // DQ (1/3/2019): Need to strip the type to get to a possible SgClassType.
9053 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);
9054
9055#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9056 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());
9057#endif
9058 // SgClassType* classType = isSgClassType(type);
9059 SgClassType* classType = isSgClassType(stripped_type);
9060 // returnTypeChain.push_front(classType);
9061 if (classType != NULL)
9062 {
9063 classChain.push_front(classType);
9064 }
9065 }
9066
9067#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9068 printf ("classChain.size() = %zu \n",classChain.size());
9069 std::list<SgClassType*>::iterator iter = classChain.begin();
9070 while(iter != classChain.end())
9071 {
9072 printf (" --- *iter = %p = %s name = %s \n",*iter,(*iter)->class_name().c_str(),(*iter)->get_name().str());
9073
9074 iter++;
9075 }
9076#endif
9077
9078 // Test the first element in the list to see if there is an ambiguity in the associated classDefinition
9079 // for the input variable referenced SgVarRefExp).
9080
9081 // SgVariableSymbol* variableSymbol = varRefExp->get_symbol();
9082 // ROSE_ASSERT(variableSymbol != NULL);
9083 // SgName variableName = variableSymbol->get_name();
9084 SgSymbol* referenceSymbol = NULL;
9085 if (varRefExp != NULL)
9086 {
9087 ROSE_ASSERT(varRefExp != NULL);
9088 ROSE_ASSERT(memberFunctionRefExp == NULL);
9089
9090 referenceSymbol = varRefExp->get_symbol();
9091 }
9092 else
9093 {
9094 ROSE_ASSERT(varRefExp == NULL);
9095 ROSE_ASSERT(memberFunctionRefExp != NULL);
9096
9097 referenceSymbol = memberFunctionRefExp->get_symbol();
9098 }
9099 ROSE_ASSERT(referenceSymbol != NULL);
9100 SgName symbolName = referenceSymbol->get_name();
9101
9102#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9103 printf ("referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9104 printf ("symbolName = %s \n",symbolName.str());
9105#endif
9106
9107 // Generate the name without the template arguments.
9108 SgFunctionSymbol* functionSymbol = isSgFunctionSymbol(referenceSymbol);
9109 if (functionSymbol != NULL)
9110 {
9111 // 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.
9112 // SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(referenceSymbol->get_declaration());
9113 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(functionSymbol->get_declaration());
9114 if (templateInstantiationMemberFunctionDeclaration != NULL)
9115 {
9116#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9117 printf ("This is a template name, we want the name without template arguments \n");
9118 printf ("templateInstantiationMemberFunctionDeclaration = %p \n",templateInstantiationMemberFunctionDeclaration);
9119 printf ("templateInstantiationMemberFunctionDeclaration->get_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_name().str());
9120#endif
9121
9122 // DQ (2/24/2019): This is an error (calls base class function).
9123 // printf ("templateInstantiationMemberFunctionDeclaration->get_template_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_template_name().str());
9124
9125 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration =
9126 isSgTemplateMemberFunctionDeclaration(templateInstantiationMemberFunctionDeclaration->get_templateDeclaration());
9127 if (templateMemberFunctionDeclaration != NULL)
9128 {
9129#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9130 printf ("templateMemberFunctionDeclaration = %p \n",templateMemberFunctionDeclaration);
9131 printf ("templateMemberFunctionDeclaration->get_name() = %s \n",templateMemberFunctionDeclaration->get_name().str());
9132#endif
9133 // We need the template name without template arguments.
9134 symbolName = templateMemberFunctionDeclaration->get_name();
9135 }
9136 else
9137 {
9138#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9139 printf ("templateMemberFunctionDeclaration == NULL: template declaration not available from template instantiation (rare, I think) \n");
9140#endif
9141 }
9142#if 0
9143 printf ("Exiting as a test! \n");
9144 ROSE_ABORT();
9145#endif
9146 }
9147 else
9148 {
9149 // DQ (2/24/2019): This might indicate another case to handle: finding SgMemberFunctionDeclaration (but this is not a template).
9150 SgDeclarationStatement* declarationStatement = functionSymbol->get_declaration();
9151 ROSE_ASSERT(declarationStatement != NULL);
9152#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9153 printf ("functionSymbol != NULL: but declaration is not a member function: declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
9154#endif
9155 }
9156 }
9157 else
9158 {
9159 SgVariableSymbol* variableSymbol = isSgVariableSymbol(referenceSymbol);
9160 if (variableSymbol != NULL)
9161 {
9162 // Nothing to do in this case of a SgVariableSymbol.
9163 }
9164 else
9165 {
9166#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9167 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): NOTE: referenceSymbol is not a SgFunctionSymbol or SgVariableSymbol \n");
9168#endif
9169#if 1
9170 printf ("Exiting as a test! \n");
9171 ROSE_ABORT();
9172#endif
9173 }
9174
9175 }
9176
9177#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9178 printf ("symbolName = %s \n",symbolName.str());
9179#endif
9180
9181 // SgClassType* firstDetectedAmbiguity = NULL;
9182 // SgClassType* lastDetectedAmbiguity = NULL;
9183
9184 // bool nameQualificationRequired = false;
9185
9186 // std::list<SgClassType*> deleteList;
9187 std::list<SgClassType*> saveList;
9188
9189#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9190 printf ("classChain.size() = %zu \n",classChain.size());
9191#endif
9192
9193 std::list<SgClassType*>::iterator i = classChain.begin();
9194 std::list<SgClassType*>::iterator save_iter = i;
9195
9196 // 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.
9197 save_iter++;
9198
9199 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9200 bool ambiguityDetectedSoSaveWholeChain = false;
9201
9202 while(i != classChain.end())
9203 {
9204#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9205 printf ("******** TOP OF WHILE LOOP ******** \n");
9206 printf (" --- *i = %p = %s name = %s \n",*i,(*i)->class_name().c_str(),(*i)->get_name().str());
9207 printf (" --- --- referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9208#endif
9209 bool ambiguityDetected = false;
9210
9211 SgDeclarationStatement* declarationStatement = (*i)->get_declaration();
9212 ROSE_ASSERT(declarationStatement != NULL);
9213 SgDeclarationStatement* definingDeclarationStatement = declarationStatement->get_definingDeclaration();
9214 if (definingDeclarationStatement != NULL)
9215 {
9216 SgClassDeclaration* classDeclaration = isSgClassDeclaration(definingDeclarationStatement);
9217 ROSE_ASSERT(classDeclaration != NULL);
9218 SgClassDefinition* classDefinition = classDeclaration->get_definition();
9219
9220#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9221 printf (" --- classDeclaration = %p = %s name = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9222 printf (" --- classDefinition = %p = %s \n",classDefinition,classDefinition->class_name().c_str());
9223#endif
9224 // This works for any SgName and SgSymbol, so it need not be specific to variables.
9225 ambiguityDetected = classDefinition->hasAmbiguity(symbolName,referenceSymbol);
9226
9227#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9228 printf (" --- ambiguityDetected = %s \n",ambiguityDetected ? "true" : "false");
9229#endif
9230 }
9231
9232 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9233 if (ambiguityDetected == true || ambiguityDetectedSoSaveWholeChain == true)
9234 {
9235 ambiguityDetectedSoSaveWholeChain = true;
9236
9237 if (save_iter != classChain.end())
9238 {
9239#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9240 printf (" --- add to saveList: *save_iter = %p \n",*save_iter);
9241#endif
9242 saveList.push_back(*save_iter);
9243 }
9244 else
9245 {
9246#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9247 printf (" --- save_iter == classChain.end() \n");
9248#endif
9249 }
9250 }
9251
9252#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9253 printf ("******** BOTTOM OF WHILE LOOP ******** \n");
9254#endif
9255 i++;
9256
9257 // Also increment the save_iter.
9258 save_iter++;
9259 }
9260
9261 // Now build a list of class types to use in the name qualification from firstDetectedAmbiguity to lastDetectedAmbiguity (inclusive).
9262
9263#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9264 printf ("saveList.size() = %zu \n",saveList.size());
9265 std::list<SgClassType*>::iterator saveList_iterator = saveList.begin();
9266 while (saveList_iterator != saveList.end())
9267 {
9268 printf (" --- *saveList_iterator = %p = %s name = %s \n",*saveList_iterator,(*saveList_iterator)->class_name().c_str(),(*saveList_iterator)->get_name().str());
9269
9270 saveList_iterator++;
9271 }
9272#endif
9273
9274 returnTypeChain = saveList;
9275
9276 // End of branch for binaryOperator != NULL.
9277 }
9278
9279 return returnTypeChain;
9280 }
9281
9282
9283
9284bool
9286 {
9287 // DQ (2/17/2019): This may share a design in common with isDataMemberReference() below.
9288
9289#define DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE 0
9290
9291 ROSE_ASSERT(memberFunctionRefExp != NULL);
9292
9293 bool returnValue = false;
9294
9295 // 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;")
9296 SgNode* parent = memberFunctionRefExp->get_parent();
9297
9298 SgArrowExp* arrowExp = isSgArrowExp(parent);
9299 SgDotExp* dotExp = isSgDotExp(parent);
9300
9301 // I don't know that the SgAddressOfOp is as relevant for the case of SgMemberFunctionRefExp, but I think
9302 // it is because we would have to support membr pointeds to functions the same a member pointers to data.
9303 // I need some examples test codes to verify that name qualification is important in this case.
9304 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9305
9306 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9307 {
9308 // Use a SgFunctionSymbol instead of a SgMemberFunctionSymbol for generality (I hope this works).
9309 SgFunctionSymbol* symbol = memberFunctionRefExp->get_symbol();
9310 ROSE_ASSERT(symbol != NULL);
9311
9312 SgFunctionDeclaration* functionDeclaration = symbol->get_declaration();
9313 ROSE_ASSERT(functionDeclaration != NULL);
9314
9315 // Check if this is a statically declared variable.
9316 if (functionDeclaration != NULL)
9317 {
9318 bool isStatic = functionDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9319#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9320 printf ("isStatic = %s \n",isStatic ? "true" : "false");
9321#endif
9322 if (isStatic == false)
9323 {
9324 SgScopeStatement* scope = functionDeclaration->get_scope();
9325 ROSE_ASSERT(scope != NULL);
9326
9327 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9328 if (classDefinition != NULL)
9329 {
9330 returnValue = true;
9331 }
9332 }
9333 }
9334 else
9335 {
9336#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9337 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9338#endif
9339 }
9340 }
9341 else
9342 {
9343#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9344 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9345#endif
9346 }
9347
9348#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9349 printf ("Leaving SageInterface::isMemberFunctionMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9350#endif
9351
9352 return returnValue;
9353 }
9354
9355
9356
9357bool
9359 {
9360 // This function is used to support the name qualification of data member references seperate from name qualification
9361 // of variables that might be members (e.g. "X x; x.A::y;" instead of "A::y" (which is just simple name qualification)).
9362
9363 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9364
9365 // DQ (2/17/2019): I think we need to make sure this is not a static data member reference (since those are qualified
9366 // differently (not member data name qualification). Consider changing the name of this function to indicate non-static.
9367
9368#define DEBUG_IS_DATA_MEMBER_REFERENCE 0
9369
9370 ROSE_ASSERT(varRefExp != NULL);
9371
9372 bool returnValue = false;
9373
9374 // 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;")
9375 SgNode* parent = varRefExp->get_parent();
9376
9377 SgArrowExp* arrowExp = isSgArrowExp(parent);
9378 SgDotExp* dotExp = isSgDotExp(parent);
9379
9380 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9381
9382 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9383 {
9384 if (arrowExp != NULL)
9385 {
9386 // DQ (2/17/2019): Check if this is part of a sizeof operand for which is is_objectless_nonstatic_data_member_reference == true.
9387 SgNode* parentOfArrowExp = arrowExp->get_parent();
9388 ROSE_ASSERT(parentOfArrowExp != NULL);
9389 SgSizeOfOp* sizeOfOp = isSgSizeOfOp(parentOfArrowExp);
9390 if (sizeOfOp != NULL && sizeOfOp->get_is_objectless_nonstatic_data_member_reference() == true)
9391 {
9392 // This is not to be qualified using data member name qualification (it should use standard name qualification).
9393#if DEBUG_IS_DATA_MEMBER_REFERENCE
9394 printf ("In SageInterface::isDataMemberReference(): Found case of expression used in sizeof with objectless_nonstatic_data_member_reference \n");
9395#endif
9396 return false;
9397 }
9398 }
9399
9400 SgVariableSymbol* symbol = varRefExp->get_symbol();
9401 ROSE_ASSERT(symbol != NULL);
9402
9403 SgInitializedName* initializedName = symbol->get_declaration();
9404 ROSE_ASSERT(initializedName != NULL);
9405
9406 // Check if this is a statically declared variable.
9407 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(initializedName->get_parent());
9408 if (variableDeclaration != NULL)
9409 {
9410 bool isStatic = variableDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9411 if (isStatic == false)
9412 {
9413 SgScopeStatement* scope = initializedName->get_scope();
9414 ROSE_ASSERT(scope != NULL);
9415
9416 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9417 if (classDefinition != NULL)
9418 {
9419 returnValue = true;
9420 }
9421 }
9422 }
9423 else
9424 {
9425#if DEBUG_IS_DATA_MEMBER_REFERENCE
9426 printf ("In SageInterface::isDataMemberReference(): varRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9427#endif
9428 }
9429 }
9430 else
9431 {
9432#if DEBUG_IS_DATA_MEMBER_REFERENCE
9433 printf ("In SageInterface::isDataMemberReference(): varRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9434#endif
9435 }
9436
9437#if DEBUG_IS_DATA_MEMBER_REFERENCE
9438 printf ("Leaving SageInterface::isDataMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9439#endif
9440
9441 return returnValue;
9442 }
9443
9444
9445#if 0
9446bool
9448 {
9449 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9450 ROSE_ASSERT(varRefExp != NULL);
9451
9452 bool returnValue = false;
9453
9454 SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9455
9456 if (addressOfOp != NULL)
9457 {
9458 returnValue = true;
9459 }
9460
9461 return returnValue;
9462 }
9463#endif
9464
9465bool
9467 {
9468 // DQ (2/17/2019): Need to generalize this function to apply to member functions references as well.
9469
9470 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
9471 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
9472 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
9473
9474 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
9475
9476 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9477 // ROSE_ASSERT(varRefExp != NULL);
9478 ROSE_ASSERT(refExp != NULL);
9479
9480 bool returnValue = false;
9481
9482 // SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9483 SgAddressOfOp* addressOfOp = isSgAddressOfOp(refExp->get_parent());
9484
9485 if (addressOfOp != NULL)
9486 {
9487 returnValue = true;
9488 }
9489
9490 return returnValue;
9491 }
9492
9494 {
9495 // DQ (3/4/2014): This new version of this function supports both C/C++ and also Java.
9496 // If the SgJavaPackageDeclaration is noticed then the previous parent is a
9497 // SgClassDefinition and the previous previous parent is a SgClassDeclaration whose
9498 // name can be used to match the filename in the SgProject's list of files.
9499 // A better implementation usign an attribute (not in place until tomorrow) and
9500 // from the attribute the pointer to the associated file is directly available.
9501 // The later implementation is as fast as possible.
9502
9503 ROSE_ASSERT (astNode != NULL);
9504
9505 // Make sure this is not a project node (since the SgFile exists below
9506 // the project and could not be found by a traversal of the parent list)
9507 ROSE_ASSERT (isSgProject(astNode) == NULL);
9508
9509 SgNode* previous_parent = NULL;
9510 SgNode* previous_previous_parent = NULL;
9511
9512 SgNode* parent = astNode;
9513 // while ( (parent != NULL) && (isSgFile(parent) == NULL) )
9514 while ( (parent != NULL) && (isSgFile(parent) == NULL) && isSgJavaPackageDeclaration(parent) == NULL)
9515 {
9516#if 0
9517 printf ("In getEnclosingFileNode(): parent = %p = %s \n",parent,parent->class_name().c_str());
9518#endif
9519 previous_previous_parent = previous_parent;
9520 previous_parent = parent;
9521
9522 parent = parent->get_parent();
9523 }
9524
9525 if (previous_previous_parent != NULL && previous_parent != NULL && isSgJavaPackageDeclaration(parent) != NULL)
9526 {
9527 // This is for a Java program and is contained within a SgJavaPackageDeclaration
9528#if 0
9529 printf ("parent = %p = %s \n",parent,parent->class_name().c_str());
9530 printf ("previous_parent = %p = %s \n",previous_parent,previous_parent->class_name().c_str());
9531 printf ("previous_previous_parent = %p = %s \n",previous_previous_parent,previous_previous_parent->class_name().c_str());
9532#endif
9533 SgClassDeclaration* classDeclaration = isSgClassDeclaration(previous_previous_parent);
9534 if (classDeclaration != NULL)
9535 {
9536#if 0
9537 printf ("Class name = %p = %s = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9538#endif
9539 // Find the associated Java class file.
9540#if 0
9541 // DQ (3/4/2014): This is the code we want to use until we get Philippe's branch in place with the attribute.
9542 SgProject* project = TransformationSupport::getProject(parent);
9543 ROSE_ASSERT(project != NULL);
9544 SgFileList* fileList = project->get_fileList_ptr();
9545 ROSE_ASSERT(fileList != NULL);
9546 SgFilePtrList & vectorFile = fileList->get_listOfFiles();
9547#if 0
9548 printf ("Output list of files: \n");
9549#endif
9550 SgFilePtrList::iterator i = vectorFile.begin();
9551 while (i != vectorFile.end())
9552 {
9553 SgFile* file = *i;
9554 ROSE_ASSERT(file != NULL);
9555#if 0
9556 printf (" --- filename = %s \n",file->getFileName().c_str());
9557#endif
9558 string filename = file->getFileName();
9559 string filenameWithoutPath = file->get_sourceFileNameWithoutPath();
9560 string classname = classDeclaration->get_name();
9561 string matchingfilename = classname + ".java";
9562#if 0
9563 printf (" --- --- filename = %s \n",filename.c_str());
9564 printf (" --- --- filenameWithoutPath = %s \n",filenameWithoutPath.c_str());
9565 printf (" --- --- classname = %s \n",classname.c_str());
9566 printf (" --- --- matchingfilename = %s \n",matchingfilename.c_str());
9567#endif
9568 if (filenameWithoutPath == matchingfilename)
9569 {
9570#if 0
9571 printf (" return file = %p \n",file);
9572#endif
9573 return file;
9574 }
9575
9576 i++;
9577 }
9578#else
9579 // DQ (3/4/2014): This is the code we want to use when the attribute is in place (philippe's branch).
9580 AstSgNodeAttribute *attribute = (AstSgNodeAttribute *) classDeclaration->getAttribute("sourcefile");
9581
9582 // "This simpler and more efficent code requires the latest work in Java support (3/6/2014)"
9583
9584 if (attribute)
9585 {
9586 // true for all user-specified classes and false for all classes fom libraries
9587 SgSourceFile *sourcefile = isSgSourceFile(attribute->getNode());
9588 ROSE_ASSERT(sourcefile != NULL);
9589 return sourcefile;
9590 }
9591#endif
9592 }
9593 }
9594 else
9595 {
9596 // previous_parent was uninitialized to a non-null value or astNode is a SgJavaPackageDeclaration or SgFile.
9597 if (previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9598 {
9599 // The input was a SgJavaPackageDeclaration (so there is no associated SgFile).
9600 ROSE_ASSERT(isSgJavaPackageDeclaration(astNode) != NULL);
9601 return NULL;
9602 }
9603 else
9604 {
9605 if (previous_previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9606 {
9607 // The input was a SgClassDefinition (so there is no associated SgFile).
9608 ROSE_ASSERT(isSgClassDefinition(astNode) != NULL);
9609 return NULL;
9610 }
9611 else
9612 {
9613 // This could be a C/C++ file (handled below).
9614 }
9615 }
9616 }
9617
9618 // This is where we handle the C/C++ files.
9619 if (parent == nullptr)
9620 {
9621 return nullptr;
9622 }
9623 else
9624 {
9625 return isSgFile(parent);
9626 }
9627 }
9628
9630 struct FrontendSpecificTraversal : public ROSE_VisitTraversal {
9631 std::set<SgNode*> specific;
9632 std::set<SgNode*> non_specific;
9633
9634 static void recursive_collect( SgNode* node , std::set<SgNode *> & collection ) {
9635 // Stop on sinks and loops
9636 if (node == NULL || !collection.insert(node).second) return;
9637
9638 std::vector<std::pair<SgNode*, std::string> > data_members = node->returnDataMemberPointers();
9639 for (std::vector<std::pair<SgNode*, std::string> >::iterator i = data_members.begin(); i != data_members.end(); ++i) {
9640 recursive_collect(i->first, collection);
9641 }
9642 }
9643
9644 void visit (SgNode* n) {
9645 Sg_File_Info * fileInfo = n->get_file_info();
9646
9647 if (fileInfo != NULL) {
9648 if (fileInfo->isFrontendSpecific()) {
9649 specific.insert(n);
9650 recursive_collect(n, specific);
9651 } else {
9652 non_specific.insert(n);
9653 recursive_collect(n, non_specific);
9654 }
9655 } else {
9656 fileInfo = isSg_File_Info(n);
9657 if (fileInfo != NULL) {
9658 if (fileInfo->isFrontendSpecific()) {
9659 specific.insert(n);
9660 } else {
9661 non_specific.insert(n);
9662 }
9663 }
9664 }
9665 }
9666
9667 std::set<SgNode*> apply() {
9668 traverseMemoryPool();
9669
9670 std::set<SgNode*> result;
9671
9672 std::set_difference(
9673 specific.begin(), specific.end(),
9674 non_specific.begin(), non_specific.end(),
9675 std::insert_iterator<set<SgNode*> >(result, result.begin())
9676 );
9677
9678 return result;
9679 }
9680 };
9681
9682 FrontendSpecificTraversal fst;
9683 return fst.apply();
9684}
9685
9686void
9688 {
9689 // DQ (2/17/2019): Display the shared nodes in the AST for debugging.
9690
9691 class OutputSharedNodesTraversal : public SgSimpleProcessing
9692 {
9693 // This traversal collects the includes at the top of a file.
9694 public:
9695 void visit(SgNode *astNode)
9696 {
9697 ROSE_ASSERT(astNode != NULL);
9698 Sg_File_Info* file_info = astNode->get_file_info();
9699 if (file_info != NULL)
9700 {
9701 if (file_info->isShared() == true)
9702 {
9703 printf ("Found shared node: astNode = %p = %s \n",astNode,astNode->class_name().c_str());
9704 }
9705 }
9706 }
9707 };
9708
9709 OutputSharedNodesTraversal tt;
9710 tt.traverse(node,preorder);
9711 }
9712
9713
9714
9715
9716
9718 while (n && !isSgStatement(n)) n = n->get_parent();
9719 return isSgStatement(n);
9720}
9721
9722
9723
9724#if 1
9725// DQ (11/19/2020): We need to expand the use of this to cover deffered transformations of common SageInterface transformations (e.g. replaceStatement).
9726// So I need to move this out of being specific to the outliner and make it more generally data structure in the SageInterface.
9727
9728SageInterface::DeferredTransformation::DeferredTransformation()
9729 : deferredTransformationKind(e_default),
9730 statementToRemove(NULL),
9731 statementToAdd(NULL),
9732 class_definition(NULL),
9733 target_class_member(NULL),
9734 new_function_prototype(NULL),
9735 // DQ (2/28/2021): Added new data member to support deferred transformations.
9736 locationToOverwriteWithTransformation(NULL),
9737 transformationToOverwriteFirstStatementInInterval(NULL),
9738 blockOfStatementsToOutline(NULL)
9739 {
9740 // Default constructor (not particularly useful).
9741#if 0
9742 printf ("In SageInterface::DeferredTransformation default constructor called \n");
9743#endif
9744 }
9745
9746// DQ (2/28/2021): Added new data member to support deferred transformations.
9747// IntervalType statementInterval;
9748// SgStatement* locationToOverwriteWithTransformation;
9749
9750SageInterface::DeferredTransformation::DeferredTransformation(
9751 SgClassDefinition* input_class_definition,
9752 SgDeclarationStatement* input_target_class_member,
9753 SgDeclarationStatement* input_new_function_prototype)
9754 : deferredTransformationKind(e_outliner),
9755 statementToRemove(NULL),
9756 statementToAdd(NULL),
9757 class_definition(input_class_definition),
9758 target_class_member(input_target_class_member),
9759 new_function_prototype(input_new_function_prototype),
9760 // DQ (2/28/2021): Added new data member to support deferred transformations.
9761 locationToOverwriteWithTransformation(NULL),
9762 transformationToOverwriteFirstStatementInInterval(NULL),
9763 blockOfStatementsToOutline(NULL)
9764 {
9765 // This constructor is used by the outliner.
9766#if 0
9767 printf ("In SageInterface::DeferredTransformation constructor for outliner called \n");
9768#endif
9769 }
9770
9773 {
9774#if 0
9775 printf ("In SageInterface::DeferredTransformation constructor for replaceDefiningFunctionDeclarationWithFunctionPrototype called \n");
9776#endif
9777 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9778 // This constructor is used by tool_G and supports the use of the transformation represented
9779 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9781 X.deferredTransformationKind = e_replaceDefiningFunctionDeclarationWithFunctionPrototype;
9782 X.statementToRemove = functionDeclaration;
9783 X.statementToAdd = NULL;
9784 X.class_definition = NULL;
9785 X.target_class_member = NULL;
9786 X.new_function_prototype = NULL;
9787
9788 // DQ (2/28/2021): Added new data member to support deferred transformations.
9789 X.locationToOverwriteWithTransformation = NULL;
9790 X.transformationToOverwriteFirstStatementInInterval = NULL;
9791 X.blockOfStatementsToOutline = NULL;
9792
9793 return X;
9794 }
9795
9797SageInterface::DeferredTransformation::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool /*movePreprocessingInfo = false*/)
9798 {
9799#if 0
9800 printf ("In SageInterface::DeferredTransformation constructor for replaceStatement called \n");
9801#endif
9802 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9803 // This constructor is used by tool_G and supports the use of the transformation represented
9804 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9806 X.deferredTransformationKind = e_replaceStatement;
9807 X.statementToRemove = oldStmt;
9808 X.statementToAdd = newStmt;
9809 X.class_definition = NULL;
9810 X.target_class_member = NULL;
9811 X.new_function_prototype = NULL;
9812
9813 // DQ (2/28/2021): Added new data member to support deferred transformations.
9814 X.locationToOverwriteWithTransformation = NULL;
9815 X.transformationToOverwriteFirstStatementInInterval = NULL;
9816 X.blockOfStatementsToOutline = NULL;
9817
9818 return X;
9819 }
9820
9821SageInterface::DeferredTransformation::DeferredTransformation (const DeferredTransformation& X)
9822#if 0
9823 : deferredTransformationKind(X.deferredTransformationKind),
9824 statementToRemove(X.statementToRemove),
9825 statementToAdd(X.StatementToAdd),
9826 class_definition(X.class_definition),
9827 target_class_member(X.target_class_member),
9828 new_function_prototype(X.new_function_prototype),
9829 targetClasses(X.targetClasses),
9830 targetFriends(X.targetFriends)
9831 {
9832 }
9833#else
9834 {
9835#if 0
9836 printf ("In SageInterface::DeferredTransformation copy constructor called \n");
9837#endif
9838 // DQ (11/19/2020): Leverage the operator=() implementation to reduce complexity (one place to update).
9839 *this = X;
9840 }
9841#endif
9842
9844 {
9845#if 0
9846 printf ("Inside of SageInterface::DeferredTransformation::operator= (const DeferredTransformation& X) \n");
9847#endif
9848
9849#if 0
9850 // Original code.
9851 targetFriends = X.targetFriends;
9852 targetClasses = X.targetClasses;
9853#else
9854
9855 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9856 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9857 // definitions in the dynamic library file with function prototypes.
9858 transformationLabel = X.transformationLabel;
9859
9860 // New code added to support more general usage.
9861 deferredTransformationKind = X.deferredTransformationKind;
9862 statementToRemove = X.statementToRemove;
9863 statementToAdd = X.statementToAdd;
9864
9865 class_definition = X.class_definition;
9866 target_class_member = X.target_class_member;
9867 new_function_prototype = X.new_function_prototype;
9868 targetClasses = X.targetClasses;
9869 targetFriends = X.targetFriends;
9870
9871 // DQ (2/28/2021): Added new data member to support deferred transformations.
9872 statementInterval = X.statementInterval;
9873 locationToOverwriteWithTransformation = X.locationToOverwriteWithTransformation;
9874 transformationToOverwriteFirstStatementInInterval = X.transformationToOverwriteFirstStatementInInterval;
9875
9876 // DQ (3/1/2021): Added new data member to support deferred transformations.
9877 blockOfStatementsToOutline = X.blockOfStatementsToOutline;
9878#endif
9879
9880 return *this;
9881 }
9882
9887
9888std::string SageInterface::DeferredTransformation::outputDeferredTransformationKind(const TransformationKind & kind)
9889 {
9890 string returnValue = "uninitialized";
9891 switch (kind)
9892 {
9893 case e_error: returnValue = "e_error"; break;
9894 case e_default: returnValue = "e_default"; break;
9895 case e_outliner: returnValue = "e_outliner"; break;
9896 case e_replaceStatement: returnValue = "e_replaceStatement"; break;
9897 case e_removeStatement: returnValue = "e_removeStatement"; break;
9898 case e_replaceDefiningFunctionDeclarationWithFunctionPrototype: returnValue = "e_replaceDefiningFunctionDeclarationWithFunctionPrototype"; break;
9899 case e_last: returnValue = "e_last"; break;
9900 default:
9901 {
9902 printf ("Error: SageInterface::DeferredTransformation::get_deferredTransformationKind_string(): default reached \n");
9903 ROSE_ABORT();
9904 }
9905 }
9906
9907 return returnValue;
9908 }
9909
9910void SageInterface::DeferredTransformation::display ( std::string label ) const
9911 {
9912 printf ("SageInterface::DeferredTransformation::display(): label = %s \n",label.c_str());
9913
9914 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9915 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9916 // definitions in the dynamic library file with function prototypes.
9917 printf (" --- transformationLabel = %s \n",transformationLabel.c_str());
9918
9919 printf (" --- deferredTransformationKind = %s \n",outputDeferredTransformationKind(deferredTransformationKind).c_str());
9920 if (statementToRemove != NULL)
9921 {
9922 printf (" --- statementToRemove = %p = %s name = %s \n",statementToRemove,statementToRemove->class_name().c_str(),get_name(statementToRemove).c_str());
9923 }
9924 else
9925 {
9926 printf (" --- statementToRemove == NULL \n");
9927 }
9928
9929 if (statementToAdd != NULL)
9930 {
9931 printf (" --- statementToAdd = %p = %s name = %s \n",statementToAdd,statementToAdd->class_name().c_str(),get_name(statementToAdd).c_str());
9932 }
9933 else
9934 {
9935 printf (" --- statementToAdd == NULL \n");
9936 }
9937
9938 if (class_definition != NULL)
9939 {
9940 // printf (" --- class_definition = %p = %s name = %s \n",class_definition,class_definition->class_name().c_str(),get_name(class_definition).c_str());
9941 printf (" --- class_definition = %p \n",class_definition);
9942 }
9943
9944 if (target_class_member != NULL)
9945 {
9946 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());
9947 }
9948
9949 if (new_function_prototype != NULL)
9950 {
9951 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());
9952 }
9953
9954 // DQ (2/28/2021): Added new data member to support deferred transformations.
9955 if (locationToOverwriteWithTransformation != NULL)
9956 {
9957 // printf (" --- locationToOverwriteWithTransformation = %p = %s name = %s \n",locationToOverwriteWithTransformation,
9958 // locationToOverwriteWithTransformation->class_name().c_str(),get_name(locationToOverwriteWithTransformation).c_str());
9959 printf (" --- locationToOverwriteWithTransformation = %p \n",locationToOverwriteWithTransformation);
9960 }
9961
9962 // DQ (2/28/2021): Added new data member to support deferred transformations.
9963 if (transformationToOverwriteFirstStatementInInterval != NULL)
9964 {
9965 // printf (" --- transformationToOverwriteFirstStatementInInterval = %p = %s name = %s \n",transformationToOverwriteFirstStatementInInterval,
9966 // transformationToOverwriteFirstStatementInInterval->class_name().c_str(),get_name(transformationToOverwriteFirstStatementInInterval).c_str());
9967 printf (" --- transformationToOverwriteFirstStatementInInterval = %p \n",transformationToOverwriteFirstStatementInInterval);
9968 }
9969
9970 // DQ (3/1/2021): Added new data member to support deferred transformations.
9971 if (blockOfStatementsToOutline != NULL)
9972 {
9973 printf (" --- blockOfStatementsToOutline = %p \n",blockOfStatementsToOutline);
9974 }
9975
9976 printf ("targetClasses.size() = %zu \n",targetClasses.size());
9977 printf ("targetFriends.size() = %zu \n",targetFriends.size());
9978
9979 // DQ (2/28/2021): Added new data member to support deferred transformations.
9980 printf ("statementInterval.size() = %zu \n",statementInterval.size());
9981
9982 }
9983#endif
9984
9985
9986
9987
9988
9989// DQ (/20/2010): Control debugging output for SageInterface::removeStatement() function.
9990#define REMOVE_STATEMENT_DEBUG 0
9991
9993void SageInterface::removeStatement(SgStatement* targetStmt, bool autoRelocatePreprocessingInfo /*= true*/)
9994 {
9995#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
9996 // This function removes the input statement.
9997 // If there are comments and/or CPP directives then those comments and/or CPP directives will
9998 // be moved to a new SgStatement. The new SgStatement is selected using the findSurroundingStatementFromSameFile()
9999 // function and if there is not statement found then the SgGlobal IR node will be selected.
10000 // this work is tested by the tests/nonsmoke/functional/roseTests/astInterfaceTests/removeStatementCommentRelocation.C
10001 // translator and a number of input codes that represent a range of contexts which exercise different
10002 // cases in the code below.
10003
10004#ifndef _MSC_VER
10005 // This function only supports the removal of a whole statement (not an expression within a statement)
10006 ASSERT_not_null(targetStmt);
10007
10008 SgStatement * parentStatement = isSgStatement(targetStmt->get_parent());
10009
10010 // Can't assert this since SgFile is the parent of SgGlobal, and SgFile is not a statement.
10011 // Even so SgGlobal can't be removed from SgFile, but isRemovableStatement() takes a SgStatement.
10012 // ROSE_ASSERT (parentStatement != NULL);
10013
10014 bool isRemovable = (parentStatement != NULL) ? LowLevelRewrite::isRemovableStatement(targetStmt) : false;
10015
10016#if REMOVE_STATEMENT_DEBUG || 0
10017 printf ("In SageInterface::removeStatement(): parentStatement = %p = %s remove targetStatement = %p = %s (isRemovable = %s) \n",
10018 parentStatement,parentStatement->class_name().c_str(),targetStmt,targetStmt->class_name().c_str(),isRemovable ? "true" : "false");
10019#endif
10020
10021 if (isRemovable == true)
10022 {
10023 // DQ (9/19/2010): Disable this new (not completely working feature) so that I can checkin the latest UPC/UPC++ work.
10024#if 1
10025 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
10026 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
10027 // Liao 10/28/2010. Sometimes we want remove the statement with all its preprocessing information
10028 if (autoRelocatePreprocessingInfo == true)
10029 {
10030 // WE need to move up inner danglinge #endif or #if directives first.
10032 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
10033 // appear before the statment to be attached to the inserted statement (and marked
10034 // to appear before that statement).
10035 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
10036
10037
10038 if (comments != nullptr && isSgBasicBlock(targetStmt) == nullptr )
10039 {
10040 vector<int> captureList;
10041#if REMOVE_STATEMENT_DEBUG
10042 printf ("Found attached comments (removing %p = %s): comments->size() = %" PRIuPTR " \n",targetStmt,targetStmt->class_name().c_str(),comments->size());
10043#endif
10044
10045 // Liao 10/28/2010. relinking AST statements may be achieved by remove it and attach it to somewhere else.
10046 // In this case, preprocessing information sometimes should go with the statements and not be relocated to the original places.
10047 // Dan: Since this statement will be removed we have to relocate all the associated comments and CPP directives.
10048 int commentIndex = 0;
10049 AttachedPreprocessingInfoType::iterator i;
10050 for (i = comments->begin(); i != comments->end(); i++)
10051 {
10052 ROSE_ASSERT ( (*i) != NULL );
10053#if REMOVE_STATEMENT_DEBUG
10054 printf (" Attached Comment (relativePosition=%s): %s\n",
10055 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
10056 (*i)->getString().c_str());
10057 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
10058 (*i)->get_file_info()->display("comment/directive location debug");
10059#endif
10060 captureList.push_back(commentIndex);
10061 commentIndex++;
10062 }
10063
10064#if REMOVE_STATEMENT_DEBUG
10065 printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
10066#endif
10067
10068 if (captureList.empty() == false)
10069 {
10070 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
10071 // Find the surrounding statement by first looking up in the sequence of statements in this block, then down, we need another
10072 // statement from the same file. SgGlobal may be returned if nothing else is found.
10073 bool surroundingStatementPreceedsTargetStatement = false;
10074 SgStatement* surroundingStatement = findSurroundingStatementFromSameFile(targetStmt,surroundingStatementPreceedsTargetStatement);
10075
10076 if (surroundingStatement != nullptr)
10077 {
10078 // If we have identified a valid surrounding statemen, then move the comments and CPP directives to that statement.
10079#if REMOVE_STATEMENT_DEBUG
10080 printf ("In removeStatement(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10081 printf (" --- moving comments from targetStmt = %p = %s name = %s \n",targetStmt,targetStmt->class_name().c_str(),get_name(targetStmt).c_str());
10082 printf (" --- moving comments to surroundingStatement = %p = %s name = %s \n",surroundingStatement,surroundingStatement->class_name().c_str(),get_name(surroundingStatement).c_str());
10083#endif
10084 moveCommentsToNewStatement(targetStmt,captureList,surroundingStatement,surroundingStatementPreceedsTargetStatement);
10085 }
10086 }
10087 } // end if (comments)
10088 }// end if (autoRelocatePreprocessingInfo)
10089#endif // end #if 1
10090
10091 // DQ (12/1/2015): Adding support for fixup internal data struuctures that have references to statements (e.g. macro expansions).
10093
10094 parentStatement->remove_statement(targetStmt);
10095 }
10096#else
10097 printf ("Error: This is not supported within Microsoft Windows (I forget why). \n");
10098 ROSE_ABORT();
10099#endif
10100
10101#endif
10102 }
10103
10104
10105
10107void
10109 {
10110 // This function allows the modification of the input statement to trigger operations on internal
10111 // data structures that hold references to such statements. An example is the macroExpansion
10112 // data structures that have a reference to the statements that are associated with and macro expansion.
10113 // if a statement assocated with a macro expansion is removed, then the macroExpansion needs to be
10114 // updated to force all of the statements to be marked as transformed (so that the AST will be unparsed
10115 // instead of the tokens representing the macro or some partial representation of the transformed
10116 // statements and the macro call (worse).
10117
10118#if 0
10119 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10120#endif
10121
10122 SgSourceFile* sourceFile = getEnclosingSourceFile(sourceStatement);
10123
10124 // NOTE: if the statment has not yet been added to the AST then it will not return a valid pointer.
10125 // ROSE_ASSERT(sourceFile != NULL);
10126
10127#if 0
10128 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceFile = %p \n",sourceFile);
10129#endif
10130
10131 if (sourceFile != NULL)
10132 {
10133 std::map<SgStatement*,MacroExpansion*> & macroExpansionMap = sourceFile->get_macroExpansionMap();
10134
10135 if (macroExpansionMap.find(sourceStatement) != macroExpansionMap.end())
10136 {
10137 MacroExpansion* macroExpansion = macroExpansionMap[sourceStatement];
10138 ROSE_ASSERT(macroExpansion != NULL);
10139#if 0
10140 printf ("In resetInternalMapsForTargetStatement(): macroExpansion = %p = %s \n",macroExpansion,macroExpansion->macro_name.c_str());
10141#endif
10142 if (macroExpansion->isTransformed == false)
10143 {
10144 // Mark all of the statements in the macro expansion to be transformed.
10145 std::vector<SgStatement*> & associatedStatementVector = macroExpansion->associatedStatementVector;
10146
10147 for (size_t i = 0; i < associatedStatementVector.size(); i++)
10148 {
10149 // I am concerned that some of these statements might have been deleted.
10150 SgStatement* statement = associatedStatementVector[i];
10151#if 0
10152 printf ("Mark as transformation to be output: statement = %p = %s \n",statement,statement->class_name().c_str());
10153#endif
10154 // Note that any new statement might not yet have valid Sg_File_Info objects setup at this point.
10155 // Then again, now did it make it into the associatedStatementVector unless it was via memory
10156 // recycling through the mmory pool.
10157 if (statement->get_file_info() != NULL)
10158 {
10159 // Mark each of the statements as a transformation.
10160 statement->setTransformation();
10161
10162 // This is required, else the statement will not be output in the generated code.
10163 // To understand this, consider that statements in header files could be transformed,
10164 // but we would not want that to cause them to be unparse in the source file.
10165 statement->setOutputInCodeGeneration();
10166
10167 // Not clear if we should also remove the statement from the associatedStatementVector.
10168 // This would be important to do to avoid having the same location in the memory pool
10169 // be reused for another statement. Since we makr the macro expansion as transformed
10170 // we likely don't have to worry about this.
10171 }
10172 }
10173 }
10174
10175 // Mark this macro expansion as having been processed.
10176 macroExpansion->isTransformed = true;
10177 }
10178
10179 // Other data strucutes that may have to be updated include:
10180 // representativeWhitespaceStatementMap (should be required, but only effects whitespace details)
10181 // redundantlyMappedTokensToStatementMultimap (might not be required)
10182
10183 }
10184 }
10185
10186
10188void
10189SageInterface::moveCommentsToNewStatement(SgStatement* sourceStatement, const vector<int> & indexList, SgStatement* targetStatement , bool surroundingStatementPreceedsTargetStatement)
10190 {
10191 AttachedPreprocessingInfoType* comments = sourceStatement->getAttachedPreprocessingInfo();
10192
10193#if REMOVE_STATEMENT_DEBUG || 0
10194 printf ("In moveCommentsToNewStatement(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10195 printf (" --- sourceStatement = %p = %s name = %s \n",sourceStatement,sourceStatement->class_name().c_str(),get_name(sourceStatement).c_str());
10196 printf (" --- targetStatement = %p = %s name = %s \n",targetStatement,targetStatement->class_name().c_str(),get_name(targetStatement).c_str());
10197#endif
10198 // Liao 2024/1/24
10199 // 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.
10200 // A solution : pcounter++ whenever a leading #if #ifdef #ifndef is encountered.
10201 // pcounter -- if #endif is countered
10202 // Normally the final pcounter ==0, if pcounter>=1, a #endif is missing somewhere. We should patch it up.
10203
10204#if REMOVE_STATEMENT_DEBUG
10205 printf ("Output the comments attached to sourceStatement: \n");
10206 printOutComments(sourceStatement);
10207 printf ("Output the comments attached to targetStatement: \n");
10208 printOutComments(targetStatement);
10209#endif
10210
10211 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
10212 vector<int>::const_iterator j = indexList.begin();
10213 PreprocessingInfo* prevTargetAnchorComment = NULL;
10214 while (j != indexList.end())
10215 {
10216 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
10217 ROSE_ASSERT(targetStatement->get_file_info() != NULL);
10218#if REMOVE_STATEMENT_DEBUG || 0
10219 printf ("Attaching comments to targetStatement = %p = %s on file = %s line %d \n",
10220 targetStatement,targetStatement->class_name().c_str(),
10221 targetStatement->get_file_info()->get_filenameString().c_str(),
10222 targetStatement->get_file_info()->get_line());
10223
10224 printf ("(*comments)[*j]->getRelativePosition() = %s \n",PreprocessingInfo::relativePositionName((*comments)[*j]->getRelativePosition()).c_str());
10225#endif
10226
10227 // Liao 2024/3/27: special handling when surrounding statement is SgGlobal
10228 // It should not be treated as either before or after the source statement we want to move comments from
10229 // SgGlobal should be treated as the enclosing scope of the source statement
10230 // The comments of the source statements should be attached to inside position of SgGlobal.
10231 // This is a variant of the before position (SgGlobal vs. source statement).
10232 // We do not treate SgGlobal as the same as if sgGlobal is preceeding source
10233 // because the comments of source statement would be attached to ::after of SgGlobal and
10234 // all comments will show up in the end of the file.
10235 // The ::inside location relies on the unparser to properly handle them later.
10236 if (surroundingStatementPreceedsTargetStatement == true || isSgGlobal(targetStatement) != NULL )
10237 {
10238 // dest
10239 // src // comments to be moved up: all before positions become after position
10240 // // then append to dest's commments
10241 // adjust relative position one by one
10242 auto commentPosition = (*comments)[*j]->getRelativePosition();
10243 if (commentPosition == PreprocessingInfo::before)
10244 {
10245 // Mark comments that were before the preceeding statement to be after the preceeding statement
10246 (*comments)[*j]->setRelativePosition(PreprocessingInfo::after);
10247 }
10248 else if (commentPosition == PreprocessingInfo::after ||
10249 commentPosition == PreprocessingInfo::end_of)
10250 {
10251 // Leave position alone [Rasmussen 2023.01.09]
10252 }
10253 else
10254 {
10255 ROSE_ASSERT(false && "Comment relative position neither, before, after, nor end_of");
10256 }
10257
10258 // special handling of inside position
10259 if (isSgGlobal(targetStatement))
10260 (*comments)[*j]->setRelativePosition(PreprocessingInfo::inside);
10261
10262 targetStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10263
10264 }
10265 else // the target statement is after the source statment: we want to move comments from src to target
10266 {
10267 // src : comments : before or after (when moved to dest, it should become before)
10268 // all should be prepend to dest's first comment
10269 // dest: comments
10270 // adjust relative position one by one
10271 if ((*comments)[*j]->getRelativePosition() == PreprocessingInfo::before)
10272 {
10273 // Leave the comments marked as being before the removed statement
10274 // as before the following statement
10275 }
10276 else
10277 {
10278 // If is is not before, I hope it can only be after.
10279 ASSERT_require((*comments)[*j]->getRelativePosition() == PreprocessingInfo::after);
10280 (*comments)[*j]->setRelativePosition(PreprocessingInfo::before);
10281 }
10282 AttachedPreprocessingInfoType* targetInfoList = targetStatement->getAttachedPreprocessingInfo();
10283 // source stmt has a list of comments c1, c2, c3
10284 // we want to keep their order and prepend to target stmt's existing comments
10285 // The solution is to define an anchor comment in target stmt
10286 // first time anchor is NULL, we prepend c1 to before the target stmt's first comment
10287 // after that, we insert after the anchor comment (previous anchor)
10288 // all anchor comments must come from source statement
10289 if (targetInfoList==NULL)
10290 {
10291 // we can just use append to the end. the same effect.
10292 targetStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10293 }
10294 else
10295 {
10296 // target stmt has comments
10297 // first time to grab thing
10298 if( prevTargetAnchorComment==NULL)
10299 {
10300 PreprocessingInfo * origFirstTargetComment = *(targetInfoList->begin());
10301 // insert before this original first one
10302 targetStatement->insertToAttachedPreprocessingInfo((*comments)[*j],origFirstTargetComment,false);
10303 }
10304 else
10305 {
10306 // now we have non null prev comment from target statement. insert after it!
10307 targetStatement->insertToAttachedPreprocessingInfo((*comments)[*j],prevTargetAnchorComment ,true);
10308 }
10309 }
10310
10311 prevTargetAnchorComment = (*comments)[*j];
10312 }
10313
10314
10315 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
10316#if REMOVE_STATEMENT_DEBUG
10317 printf ("Marking entry from comments list as NULL on sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10318#endif
10319 (*comments)[*j] = nullptr;// Why do we need to make it NULL??
10320
10321 j++;
10322 }
10323
10324 // Now remove each NULL entries in the comments vector.
10325 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
10326 for (size_t n = 0; n < indexList.size(); n++)
10327 {
10328#if REMOVE_STATEMENT_DEBUG || 0
10329 printf ("Erase entry from comments list on comments->size() %" PRIuPTR " \n",comments->size());
10330#endif
10331 bool modifiedList = false;
10332 AttachedPreprocessingInfoType::iterator k = comments->begin();
10333 while (k != comments->end() && modifiedList == false)
10334 {
10335 // Only modify the list once per iteration over the captureList
10336 if (*k == nullptr)
10337 {
10338 k = comments->erase(k);
10339 modifiedList = true;
10340 continue;
10341 }
10342 else
10343 {
10344 k++;
10345 }
10346 }
10347 }
10348 }
10349
10350
10353SageInterface::findSurroundingStatementFromSameFile(SgStatement* targetStmt, bool & surroundingStatementPreceedsTargetStatement)
10354 {
10355 // Note that if the return value is SgGlobal (global scope), then surroundingStatementPreceedsTargetStatement is false, but meaningless.
10356 // This function can not return a NULL pointer.
10357
10358 ROSE_ASSERT(targetStmt != NULL);
10359
10360 SgStatement* surroundingStatement = targetStmt;
10361 int surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID; // No file id can have this value.
10362
10363#if REMOVE_STATEMENT_DEBUG || 0
10364 printf ("TOP of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10365#endif
10366
10367 std::set<SgStatement*> previousVisitedStatementSet;
10368
10369 // Only handle relocation for statements that exist in the file (at least for now while debugging).
10370 if (targetStmt->get_file_info()->get_file_id() >= 0)
10371 {
10372 surroundingStatementPreceedsTargetStatement = true;
10373
10374#if REMOVE_STATEMENT_DEBUG
10375 printf (" targetStmt->get_file_info()->get_file_id() = %d \n",targetStmt->get_file_info()->get_file_id());
10376#endif
10377#if REMOVE_STATEMENT_DEBUG
10378 printf ("Before loop: surroundingStatement = %p = %s name = %s surroundingStatement_fileId = %d \n",surroundingStatement,
10379 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str(),surroundingStatement_fileId);
10380#endif
10381 bool returningNullSurroundingStatement = false;
10382 // while (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id())
10383 while ((returningNullSurroundingStatement == false) && (surroundingStatement != NULL) && surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id())
10384 {
10385 // Start by going up in the source sequence.
10386 // This is a declaration from the wrong file so go to the next statement.
10387 // surroundingStatement = (insertBefore == true) ? getNextStatement(surroundingStatement) : getPreviousStatement(surroundingStatement);
10388 // surroundingStatement = (insertBefore == true) ? getPreviousStatement(surroundingStatement) : getNextStatement(surroundingStatement);
10389 surroundingStatement = getPreviousStatement(surroundingStatement);
10390
10391#if REMOVE_STATEMENT_DEBUG
10392 printf ("In loop: after getPreviousStatement(): surroundingStatement = %p = %s name = %s \n",surroundingStatement,
10393 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str());
10394#endif
10395
10396 if (surroundingStatement == NULL)
10397 {
10398 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10399#if REMOVE_STATEMENT_DEBUG
10400 printf (" surroundingStatement_fileId set to Sg_File_Info::BAD_FILE_ID \n");
10401#endif
10402 }
10403 else
10404 {
10405 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10406#if REMOVE_STATEMENT_DEBUG
10407 printf (" surroundingStatement = %p = %s surroundingStatement->get_file_info()->get_file_id() = %d \n",
10408 surroundingStatement,surroundingStatement->class_name().c_str(),surroundingStatement->get_file_info()->get_file_id());
10409#endif
10410 }
10411
10412#if REMOVE_STATEMENT_DEBUG
10413 if (surroundingStatement != NULL)
10414 {
10415 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",
10416 surroundingStatement,surroundingStatement->class_name().c_str(),
10417 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10418 surroundingStatement->get_file_info()->get_file_id(),
10419 surroundingStatement->get_file_info()->get_line());
10420 }
10421 else
10422 {
10423 printf ("surroundingStatement == NULL \n");
10424 }
10425#endif
10426
10427 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10428 if (previousVisitedStatementSet.find(surroundingStatement) != previousVisitedStatementSet.end())
10429 {
10430 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10431
10432 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10433
10434 surroundingStatement = NULL;
10435 // break;
10436 // return NULL;
10437 }
10438 else
10439 {
10440 previousVisitedStatementSet.insert(surroundingStatement);
10441 }
10442
10443 // As a last resort restart and go down in the statement sequence.
10444 if (surroundingStatement == NULL || isSgGlobal(surroundingStatement) != NULL)
10445 {
10446 // This is triggered by rose_inputloopUnrolling.C
10447#if REMOVE_STATEMENT_DEBUG
10448 printf ("We just ran off the start (top) of the file... targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
10449#endif
10450#if 0
10451 ROSE_ABORT();
10452#endif
10453 // A statement in the same file could not be identified, so this is false.
10454 surroundingStatementPreceedsTargetStatement = false;
10455
10456 // Restart by going the other direction (down in the source sequence)
10457 surroundingStatement = targetStmt;
10458 SgStatement* previousStatement = surroundingStatement;
10459 // surroundingStatement = getNextStatement(surroundingStatement);
10460 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10461
10462 std::set<SgStatement*> forwardVisitedStatementSet;
10463
10464 // while ( (surroundingStatement != NULL) && (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id()) )
10465 while ( (surroundingStatement != NULL) && (surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id()) )
10466 {
10467 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10468 if (forwardVisitedStatementSet.find(surroundingStatement) != forwardVisitedStatementSet.end())
10469 {
10470 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10471
10472 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10473
10474 surroundingStatement = NULL;
10475 break;
10476 // return NULL;
10477 }
10478 else
10479 {
10480 forwardVisitedStatementSet.insert(surroundingStatement);
10481 }
10482
10483 previousStatement = surroundingStatement;
10484 surroundingStatement = getNextStatement(surroundingStatement);
10485
10486 if (surroundingStatement == NULL)
10487 {
10488 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10489#if REMOVE_STATEMENT_DEBUG
10490 printf ("We just ran off the end (bottom) of the file... \n");
10491#endif
10492#if 0
10493 ROSE_ABORT();
10494#endif
10495 returningNullSurroundingStatement = true;
10496 }
10497 else
10498 {
10499 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10500#if REMOVE_STATEMENT_DEBUG
10501 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",
10502 surroundingStatement,surroundingStatement->class_name().c_str(),
10503 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10504 surroundingStatement->get_file_info()->get_file_id(),
10505 surroundingStatement->get_file_info()->get_line());
10506#endif
10507 }
10508 }
10509
10510 if (surroundingStatement == NULL)
10511 {
10512#if REMOVE_STATEMENT_DEBUG
10513 printf ("Resetting the surroundingStatement to the previousStatement = %p = %s \n",previousStatement,previousStatement->class_name().c_str());
10514#endif
10515 surroundingStatement = previousStatement;
10516
10517 // Check if this is the input statement we are removing (since the we have to attach comments to the global scope IR node.
10518 if (surroundingStatement == targetStmt)
10519 {
10520 // This can happen if there was only a single statement in a file and it was removed.
10521 // All associated comments would have to be relocated to the SgGlobal IR node.
10522#if REMOVE_STATEMENT_DEBUG
10523 printf ("Setting the surroundingStatement to be global scope \n");
10524#endif
10525 surroundingStatement = TransformationSupport::getGlobalScope(targetStmt);
10526 }
10527 }
10528 }
10529 }
10530
10531 ROSE_ASSERT(surroundingStatement != NULL);
10532 }
10533 else
10534 {
10535 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());
10536 surroundingStatement = NULL;
10537 }
10538
10539#if REMOVE_STATEMENT_DEBUG
10540 printf ("BOTTOM of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s surroundingStatement = %p \n",surroundingStatementPreceedsTargetStatement ? "true" : "false",surroundingStatement);
10541 if (surroundingStatement != NULL)
10542 {
10543 printf ("surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10544 }
10545#endif
10546
10547 // ROSE_ASSERT(surroundingStatement != NULL);
10548
10549 return surroundingStatement;
10550 }
10551
10552
10553#ifndef USE_ROSE
10556{
10557#if 0
10558 struct Visitor: public AstSimpleProcessing {
10559 virtual void visit(SgNode* n) {
10560 delete (n);
10561 }
10562 };
10563 Visitor().traverse(root, postorder);
10564#else
10565 deleteAST(root);
10566#endif
10567}
10568#endif
10569
10571void SageInterface::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool movePreprocessingInfoValue/* = false*/)
10572 {
10573 ROSE_ASSERT(oldStmt);
10574 ROSE_ASSERT(newStmt);
10575
10576 if (oldStmt == newStmt) return;
10577
10578 SgStatement * p = isSgStatement(oldStmt->get_parent());
10579 ROSE_ASSERT(p);
10580
10581#if 0
10582 // TODO handle replace the body of a C/Fortran function definition with a single statement?
10583 // Liao 2/1/2010, in some case, we want to replace the entire body (SgBasicBlock) for some parent nodes.
10584 // the built-in replace_statement() (insert_child() underneath) may not defined for them.
10585 if (SgFortranDo * f_do = isSgFortranDo (p))
10586 {
10587 ROSE_ASSERT (f_do->get_body() == oldStmt);
10588 if (!isSgBasicBlock(newStmt))
10589 newStmt = buildBasicBlock (newStmt);
10590 f_do->set_body(isSgBasicBlock(newStmt));
10591 newStmt->set_parent(f_do);
10592 }
10593 else
10594 {
10595 p->replace_statement(oldStmt,newStmt);
10596 }
10597#endif
10598 p->replace_statement(oldStmt,newStmt);
10599
10600#if 1
10601 // DQ (7/20/2021): Need to make the physical_file_ids match and the parents.
10602 // Acutally this may be too late in the case of a deferred transformation since
10603 // we run the AST consistancy tests as an intermediate step.
10604 int physical_file_id = oldStmt->get_startOfConstruct()->get_physical_file_id();
10605
10606#if 0
10607 printf ("In SageInterface::replaceStatement(): physical_file_id = %d \n",physical_file_id);
10608#endif
10609
10610 newStmt->get_startOfConstruct()->set_physical_file_id(physical_file_id);
10611 newStmt->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
10612
10613 // DQ (7/20/2021): Do we need this when we set the physical_file_id?
10614 newStmt->set_parent(oldStmt->get_parent());
10615#endif
10616
10617 // Some translators have their own handling for this (e.g. the outliner)
10618 if (movePreprocessingInfoValue)
10619 {
10620 // move inner dangling #endif, #if etc to newStmt's after position, otherwise they got lost
10621//A-B test here
10623#if 0
10624 printf ("In SageInterface::replaceStatement(): calling moveUpPreprocessingInfo() changed to movePreprocessingInfo() \n");
10625#endif
10626
10627 // DQ (12/28/2020): I think this should be movePreprocessingInfo instead of moveUpPreprocessingInfo
10628 // (which has a collection of defaults that are not appropriate).
10629 // moveUpPreprocessingInfo(newStmt, oldStmt);
10630#if 1
10631 // 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).
10632 moveUpPreprocessingInfo(newStmt, oldStmt);
10633#else
10634 // void SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
10635 // PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
10636 bool usePrepend = true;
10637 // movePreprocessingInfo ( newStmt, oldStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10638 movePreprocessingInfo ( oldStmt, newStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10639#endif
10640 }
10641 }
10642
10643void
10645 {
10646 // Relocate the declaration to be explicitly represented in its associated namespace (required for some backend compilers to process template instantiations).
10647
10648 // DQ (7/19/2015): This is required to support general unparsing of template instantations for the GNU g++
10649 // compiler which does not permit name qualification to be used to support the expression of the namespace
10650 // where a template instantiatoon would be places. Such name qualification would also sometimes require
10651 // global qualification which is also not allowed by the GNU g++ compiler. These issues appear to be
10652 // specific to the GNU compiler versions, at least versions 4.4 through 4.8.
10653
10654 // Find the previous statement in this scope so that we can close off the namepsace and start a new one.
10655 SgStatement* previousDeclarationStatement = getPreviousStatement(declarationStatement);
10656 SgStatement* nextDeclarationStatement = getNextStatement(declarationStatement);
10657
10658#if 0
10659 printf ("In SageInterface::moveDeclarationToAssociatedNamespace(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
10660 printf (" --- previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement != NULL ? previousDeclarationStatement->class_name().c_str() : "null");
10661 printf (" --- nextDeclarationStatement = %p \n",nextDeclarationStatement);
10662 printf (" --- nextDeclarationStatement = %p = %s \n",nextDeclarationStatement, nextDeclarationStatement != NULL ? nextDeclarationStatement->class_name().c_str() : "null");
10663#endif
10664
10665 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10666 if (previousDeclarationStatement != NULL)
10667 {
10668 // printf ("previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement->class_name().c_str());
10669 }
10670 else
10671 {
10672 printf ("There is no previous statement so there is no namespace to close off! \n");
10673
10674 // Handle this corner case after we have the most general case working!
10675 printf ("Exiting as a test! \n");
10676 ROSE_ABORT();
10677 }
10678
10679 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10680 if (nextDeclarationStatement != NULL)
10681 {
10682 // printf ("nextDeclarationStatement = %p = %s \n",nextDeclarationStatement,nextDeclarationStatement->class_name().c_str());
10683 }
10684 else
10685 {
10686#if 0
10687 printf ("There is no next statement so there is no namespace to reopen! \n");
10688#endif
10689#if 0
10690 // Handle this corner case after we have the most general case working!
10691 printf ("Exiting as a test! \n");
10692 ROSE_ABORT();
10693#endif
10694 }
10695
10696 if (previousDeclarationStatement != NULL && nextDeclarationStatement != NULL)
10697 {
10698 // DQ (7/19/2015): This is the most common case!
10699#if 0
10700 printf ("Identified the most common case... \n");
10701#endif
10702 // Identify the associated namespace
10703 //SgScopeStatement* declarationScope = declarationStatement->get_scope();
10704#if 0
10705 printf ("declarationScope = %p = %s \n",declarationScope,declarationScope->class_name().c_str());
10706#endif
10707#if 0
10708 // Handle this corner case after we have the most general case working!
10709 printf ("Exiting as a test! \n");
10710 ROSE_ABORT();
10711#endif
10712 }
10713 else
10714 {
10715 if (previousDeclarationStatement != NULL && nextDeclarationStatement == NULL)
10716 {
10717 // This is the case for the last template instantiaton in global scope (so it too is a common case)!
10718#if 0
10719 printf ("Found 2nd most common case: previousDeclarationStatement != NULL && nextDeclarationStatement == NULL \n");
10720#endif
10721#if 0
10722 // Handle this corner case after we have the most general case working!
10723 printf ("Exiting as a test! \n");
10724 ROSE_ABORT();
10725#endif
10726 }
10727 else
10728 {
10729 if (previousDeclarationStatement == NULL && nextDeclarationStatement == NULL)
10730 {
10731 printf ("This case should require no special handling, unless we are still in the wrong namespace \n");
10732
10733 // Handle this corner case after we have the most general case working!
10734 printf ("Exiting as a test! \n");
10735 ROSE_ABORT();
10736 }
10737 else
10738 {
10739 printf ("This case should have been caught above! \n");
10740
10741 // Handle this corner case after we have the most general case working!
10742 printf ("Exiting as a test! \n");
10743 ROSE_ABORT();
10744 }
10745 }
10746 }
10747
10748 SgScopeStatement* declarationParent = isSgScopeStatement(declarationStatement->get_parent());
10749 if (declarationParent == NULL)
10750 {
10751#if 0
10752 printf ("declarationStatement->get_parent() = %p = %s \n",declarationStatement->get_parent(), (declarationStatement->get_parent() != NULL) ? declarationStatement->get_parent()->class_name().c_str() : "null");
10753#endif
10754 }
10755 // This can be a SgTemplateInstantiationDirectiveStatement (bug we want to skip over this case for now).
10756 // ROSE_ASSERT(declarationParent != NULL);
10757
10758 if (declarationParent != NULL)
10759 {
10760 SgScopeStatement* declarationScope = declarationStatement->get_scope();
10761 ROSE_ASSERT(declarationScope != NULL);
10762
10763 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(declarationScope);
10764 if (namespaceDefinition != NULL)
10765 {
10766 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
10767 ROSE_ASSERT(namespaceDeclaration != NULL);
10768#if 0
10769 printf ("The declaration has been identified to be associuated with a valid namespace = %p = %s \n",namespaceDeclaration,namespaceDeclaration->get_name().str());
10770 printf (" --- declarationParent = %p = %s \n",declarationParent,declarationParent->class_name().c_str());
10771 printf (" --- Move declaration from scope = %p = %s to namespace = %p = %s \n",declarationParent,declarationParent->class_name().c_str(),namespaceDeclaration,namespaceDeclaration->get_name().str());
10772#endif
10773#if 0
10774 printf ("Exiting as a test! \n");
10775 ROSE_ABORT();
10776#endif
10777 }
10778 else
10779 {
10780#if 0
10781 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());
10782#endif
10783 }
10784 }
10785 else
10786 {
10787#if 0
10788 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");
10789#endif
10790 // ROSE_ASSERT(declarationParent != NULL);
10791 }
10792
10793 }
10794
10795
10796bool
10798 {
10799 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10800 if (isSgTemplateInstantiationDefn(node) != NULL)
10801 {
10802#if 0
10803 printf ("Note: In SageInterface::isTemplateInstantiationNode(): skipping SgTemplateInstantiationDefn \n");
10804#endif
10805 }
10806
10807 return isSgTemplateInstantiationDecl(node)
10808 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10809// || isSgTemplateInstantiationDefn(node)
10810 || isSgTemplateInstantiationDefn(node)
10811 || isSgTemplateInstantiationFunctionDecl(node)
10812 || isSgTemplateInstantiationMemberFunctionDecl(node)
10813 || isSgTemplateInstantiationTypedefDeclaration(node)
10814 || isSgTemplateInstantiationDirectiveStatement(node)
10815 ;
10816 }
10817
10818#if 0
10819// DQ (5/23/2021): Added (uncommented, and added to the header file) function to support test for template declaration.
10820// Commented back out, since this is not required for what I am debugging currently.
10821// DQ (6/27/2018): This will be the template declaration test version of the template instantiation test function above.
10822bool
10823SageInterface::isTemplateDeclarationNode(SgNode* node)
10824 {
10825 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10826 if (isSgTemplateDefinition(node) != NULL)
10827 {
10828#if 0
10829 printf ("Note: In SageInterface::isTemplateDeclarationNode(): skipping SgTemplateDefinition \n");
10830#endif
10831 }
10832
10833 return isSgTemplateInstantiationDecl(node)
10834 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10835 // || isSgTemplateInstantiationDefn(node)
10836 || isSgTemplateInstantiationDefn(node)
10837 || isSgTemplateInstantiationFunctionDecl(node)
10838 || isSgTemplateInstantiationMemberFunctionDecl(node)
10839 || isSgTemplateInstantiationTypedefDeclaration(node)
10840 || isSgTemplateInstantiationDirectiveStatement(node)
10841 ;
10842 }
10843#endif
10844
10845void
10847 {
10848 // DQ (8/18/2015): This function is called from the tests/nonsmoke/functional/testTemplates translator.
10849
10850 // DQ (7/19/2015): This function can't use an iterator since it will be
10851 // doing transformations on the AST and will cause iterator invalidation errors.
10852
10853 std::vector<SgDeclarationStatement*> templateInstantiationVector;
10854
10855 // DQ (9/24/2015): This feature is not available yet in CMake (Markus is adding the library support for this feature).
10856#ifndef USE_CMAKEx
10857 RoseAst ast(root);
10858
10859 for (RoseAst::iterator i= ast.begin(); i!= ast.end(); ++i)
10860 {
10862 {
10863 // markNodeToBeUnparsed(*i);
10864 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
10865 if (declaration != NULL)
10866 {
10867 templateInstantiationVector.push_back(declaration);
10868 }
10869 else
10870 {
10871 // I think it is OK that not all are a SgDeclarationStatement.
10872 }
10873 }
10874 }
10875#else
10876 std::cerr << "This feature for now is available with autotools only!" << std::endl;
10877 ROSE_ABORT();
10878#endif
10879
10880 std::vector<SgDeclarationStatement*>::iterator j = templateInstantiationVector.begin();
10881 while (j != templateInstantiationVector.end())
10882 {
10884 j++;
10885 }
10886 }
10887
10888
10889
10891// All SgVariantExpression in the pattern will be replaced with copies of the anchor node.
10893{
10894 SgExpression * anchor_exp = isSgExpression(anchor);
10895 SgExpression * pattern_exp = isSgExpression(new_pattern);
10896 ROSE_ASSERT (anchor_exp != NULL);
10897 ROSE_ASSERT (pattern_exp != NULL);
10898
10899 // we replace all SgExpression within the pattern with copies of anchor
10900 Rose_STL_Container<SgNode*> opaque_exp_list = NodeQuery::querySubTree(pattern_exp,V_SgExpression);
10901 for (size_t i = 0; i<opaque_exp_list.size(); i++)
10902 {
10903 SgExpression* opaque_exp = isSgExpression(opaque_exp_list[i]);
10904 ROSE_ASSERT (opaque_exp != NULL);
10905 if (opaque_exp->variantT() == V_SgVariantExpression)
10906 {
10907 SgExpression * anchor_exp_copy = deepCopy(anchor_exp);
10908 replaceExpression(opaque_exp, anchor_exp_copy);
10909 }
10910 }
10911
10912 // finally we replace anchor_exp with the pattern_exp
10913 replaceExpression(anchor_exp, pattern_exp, false);
10914 return new_pattern;
10915}
10919{
10920 //This implementation tends to generate numbers that are unnecessarily high.
10921 static int counter = 0;
10922
10923 string name;
10924 bool collision = false;
10925 do
10926 {
10927 name = "__" + baseName + boost::lexical_cast<string > (counter++) + "__";
10928
10929 // DQ (8/16/2013): Modified to reflect new API.
10930 // Look up the name in the parent scopes
10931 // SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope);
10932 SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope,NULL,NULL);
10933 collision = (nameSymbol != NULL);
10934
10935 //Look up the name in the children scopes
10936 Rose_STL_Container<SgNode*> childScopes = NodeQuery::querySubTree(scope, V_SgScopeStatement);
10937
10938 BOOST_FOREACH(SgNode* childScope, childScopes)
10939 {
10940 SgScopeStatement* childScopeStatement = isSgScopeStatement(childScope);
10941
10942 // DQ (8/16/2013): Modified to reflect new API.
10943 // nameSymbol = childScopeStatement->lookup_symbol(SgName(name));
10944 nameSymbol = childScopeStatement->lookup_symbol(SgName(name),NULL,NULL);
10945
10946 collision = collision || (nameSymbol != NULL);
10947 }
10948 } while (collision);
10949
10950 return name;
10951}
10952
10953
10954std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableForExpression
10955(SgExpression* expression, SgScopeStatement* scope, bool initializeInDeclaration, SgAssignOp** reEvaluate)
10956{
10957 SgType* expressionType = expression->get_type();
10958 SgType* variableType = expressionType;
10959
10960 //If the expression has a reference type, we need to use a pointer type for the temporary variable.
10961 //Else, re-assigning the variable is not possible
10962 bool isReferenceType = SageInterface::isReferenceType(expressionType);
10963 if (isReferenceType)
10964 {
10965 SgType* expressionBaseType = expressionType->stripType(SgType::STRIP_TYPEDEF_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE);
10966 variableType = SageBuilder::buildPointerType(expressionBaseType);
10967 }
10968
10969 //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.
10970 if (SgArrayType* arrayType=isSgArrayType(expressionType)) {
10971 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
10972 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
10973 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
10974 }
10975 }
10976
10977 // If the expression is a dereferenced pointer, use a reference to hold it.
10978 if (isSgPointerDerefExp(expression))
10979 variableType = SageBuilder::buildReferenceType(variableType);
10980
10981 //Generate a unique variable name
10982 string name = generateUniqueVariableName(scope);
10983
10984 //Initialize the temporary variable to an evaluation of the expression
10985 SgExpression* tempVarInitExpression = SageInterface::copyExpression(expression);
10986 ROSE_ASSERT(tempVarInitExpression != NULL);
10987 if (isReferenceType)
10988 {
10989 //FIXME: the next line is hiding a bug in ROSE. Remove this line and talk to Dan about the resulting assert
10990 tempVarInitExpression->set_lvalue(false);
10991
10992 tempVarInitExpression = SageBuilder::buildAddressOfOp(tempVarInitExpression);
10993 }
10994
10995 //Optionally initialize the variable in its declaration
10996 SgAssignInitializer* initializer = NULL;
10997 if (initializeInDeclaration)
10998 {
10999 SgExpression* initExpressionCopy = SageInterface::copyExpression(tempVarInitExpression);
11000 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11001 }
11002
11003 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11004 ROSE_ASSERT(tempVarDeclaration != NULL);
11005
11006 //Now create the assignment op for reevaluating the expression
11007 if (reEvaluate != NULL)
11008 {
11009 SgVarRefExp* tempVarReference = SageBuilder::buildVarRefExp(tempVarDeclaration);
11010 *reEvaluate = SageBuilder::buildAssignOp(tempVarReference, tempVarInitExpression);
11011 }
11012
11013 //Build the variable reference expression that can be used in place of the original expression
11014 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11015 if (isReferenceType)
11016 {
11017 //The temp variable is a pointer type, so dereference it before using it
11018 varRefExpression = SageBuilder::buildPointerDerefExp(varRefExpression);
11019 }
11020
11021 return std::make_pair(tempVarDeclaration, varRefExpression);
11022}
11023
11024// This function creates a temporary variable for a given expression in the given scope
11025// This is different from SageInterface::createTempVariableForExpression in that it does not
11026// try to be smart to create pointers to reference types and so on. The tempt is initialized to expression.
11027// The caller is responsible for setting the parent of SgVariableDeclaration since buildVariableDeclaration
11028// may not set_parent() when the scope stack is empty. See programTransformation/extractFunctionArgumentsNormalization/ExtractFunctionArguments.C for sample usage.
11029
11030std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableAndReferenceForExpression
11031(SgExpression* expression, SgScopeStatement* scope)
11032{
11033 SgType* expressionType = expression->get_type();
11034 SgType* variableType = expressionType;
11035
11036 //MS 10/24/2018: If the expression has array type, we need to use a pointer type for the temporary variable.
11037 if (SgArrayType* arrayType=isSgArrayType(expressionType))
11038 {
11039 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
11040 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
11041 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
11042 }
11043 }
11044
11045 //Generate a unique variable name
11046 string name = generateUniqueVariableName(scope);
11047
11048 //initialize the variable in its declaration
11049 SgAssignInitializer* initializer = NULL;
11050 SgExpression* initExpressionCopy = SageInterface::copyExpression(expression);
11051 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11052
11053 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11054 ROSE_ASSERT(tempVarDeclaration != NULL);
11055
11056 //Build the variable reference expression that can be used in place of the original expression
11057 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11058 return std::make_pair(tempVarDeclaration, varRefExpression);
11059}
11060
11061
11062namespace
11063{
11064 void
11065 replaceExpressionInSgExpressionPtrList(SgExpression* oldExp, SgExpression* newExp, SgExpressionPtrList& lst, bool replAll = false)
11066 {
11067 SgExpressionPtrList::iterator lim = lst.end();
11068 SgExpressionPtrList::iterator pos = lst.begin();
11069 bool chg = false;
11070
11071 do
11072 {
11073 pos = std::find(pos, lim, oldExp);
11074
11075 if (pos != lim) { *pos = newExp; ++pos; chg = true; }
11076 } while (replAll && (pos != lim));
11077
11078 ROSE_ASSERT(chg);
11079 }
11080}
11081
11082// This code is based on OpenMP translator's ASTtools::replaceVarRefExp() and astInling's replaceExpressionWithExpression()
11083// Motivation: It involves the parent node to replace a VarRefExp with a new node
11084// Used to replace shared variables with the dereference expression of their addresses
11085// e.g. to replace shared1 with (*__pp_shared1)
11086
11087void SageInterface::replaceExpression(SgExpression* oldExp, SgExpression* newExp, bool keepOldExp/*=false*/) {
11088 SgExpression* parentExp;
11089
11090 ROSE_ASSERT(oldExp);
11091 ROSE_ASSERT(newExp);
11092 if (oldExp==newExp) return;
11093
11094 if (isSgVarRefExp(newExp))
11095 newExp->set_need_paren(true); // enclosing new expression with () to be safe
11096
11097 SgNode* parent = oldExp->get_parent();
11098 ROSE_ASSERT(parent!=NULL);
11099 newExp->set_parent(parent);
11100
11101 // set lvalue when necessary
11102 if (oldExp->get_lvalue() == true) newExp->set_lvalue(true);
11103
11104 if (isSgExprStatement(parent)) {
11105 isSgExprStatement(parent)->set_expression(newExp);
11106 } else if (isSgForStatement(parent)) {
11107 ROSE_ASSERT (isSgForStatement(parent)->get_increment() == oldExp);
11108 isSgForStatement(parent)->set_increment(newExp);
11109 // TODO: any other cases here??
11110 } else if(SgMatlabForStatement *matlabFor = isSgMatlabForStatement(parent)) {
11111 if(matlabFor->get_index() == oldExp)
11112 matlabFor->set_index(newExp);
11113 else if(matlabFor->get_range() == oldExp)
11114 matlabFor->set_range(newExp);
11115 else
11116 ROSE_ASSERT(!"sub-expression not found");
11117 } else if(SgJovialForThenStatement *jovFor = isSgJovialForThenStatement(parent)) {
11118 if(jovFor->get_initialization() == oldExp)
11119 jovFor->set_initialization(newExp);
11120 else if(jovFor->get_while_expression() == oldExp)
11121 jovFor->set_while_expression(newExp);
11122 else if(jovFor->get_by_or_then_expression() == oldExp)
11123 jovFor->set_by_or_then_expression(newExp);
11124 else
11125 ROSE_ASSERT(!"sub-expression not found");
11126 } else if (SgRangeExp* rngexp = isSgRangeExp(parent)) {
11127 if (rngexp->get_start() == oldExp)
11128 rngexp->set_start(newExp);
11129 else if (rngexp->get_end() == oldExp)
11130 rngexp->set_end(newExp);
11131 else if (rngexp->get_stride() == oldExp)
11132 rngexp->set_stride(newExp);
11133 else
11134 ROSE_ASSERT(!"sub-expression not found");
11135 } else if (isSgReturnStmt(parent)) {
11136 isSgReturnStmt(parent)->set_expression(newExp);
11137 } else if (isSgBinaryOp(parent)!=NULL) {
11138 if (oldExp==isSgBinaryOp(parent)->get_lhs_operand()) {
11139 isSgBinaryOp(parent)->set_lhs_operand(newExp);
11140 } else if (oldExp==isSgBinaryOp(parent)->get_rhs_operand()) {
11141 isSgBinaryOp(parent)->set_rhs_operand(newExp);
11142 } else {
11143 ROSE_ABORT();
11144 }
11145 } else if (isSgUnaryOp(parent)!=NULL){
11146 if (oldExp==isSgUnaryOp(parent)->get_operand_i())
11147 isSgUnaryOp(parent)->set_operand_i(newExp);
11148 else
11149 ROSE_ABORT();
11150 } else if (isSgConditionalExp(parent) != NULL) {
11151 SgConditionalExp* expparent = isSgConditionalExp(parent); //get explicity type parent
11152 if (oldExp==expparent->get_conditional_exp())
11153 expparent->set_conditional_exp(newExp);
11154 else if (oldExp==expparent->get_true_exp())
11155 expparent->set_true_exp(newExp);
11156 else if (oldExp==expparent->get_false_exp())
11157 expparent->set_false_exp(newExp);
11158 else
11159 ROSE_ABORT();
11160 } else if (isSgExprListExp(parent) != NULL) {
11161 SgExpressionPtrList& explist = isSgExprListExp(parent)->get_expressions();
11162 for (Rose_STL_Container<SgExpression*>::iterator i=explist.begin();i!=explist.end();i++) {
11163 if (isSgExpression(*i)==oldExp) {
11164 SgExprListExp* parentExpListExp = isSgExprListExp(parent);
11165 parentExpListExp->replace_expression(oldExp,newExp);
11166 // break; //replace the first occurrence only??
11167 }
11168 }
11169 } else if (isSgValueExp(parent)) {
11170 // For compiler generated code, this could happen.
11171 // We can just ignore this function call since it will not appear in the final AST.
11172 return;
11173 } else if (SgActualArgumentExpression* actexp = isSgActualArgumentExpression(parent)) {
11174 ROSE_ASSERT(oldExp == actexp->get_expression());
11175 actexp->set_expression(newExp);
11176 } else if (SgAdaAttributeExp* attrexp = isSgAdaAttributeExp(parent)) {
11177 if (oldExp == attrexp->get_object()) {
11178 attrexp->set_object(newExp);
11179 } else if (oldExp == attrexp->get_args()) {
11180 SgExprListExp* newLst = isSgExprListExp(newExp);
11181 ASSERT_not_null(newLst);
11182
11183 attrexp->set_args(newLst);
11184 } else {
11185 ROSE_ABORT();
11186 }
11187 /**** ALL expressions must be handled before the next line *****/
11188 } else if ((parentExp=isSgExpression(parent)) != NULL) {
11189 int worked = parentExp->replace_expression(oldExp, newExp);
11190 // ROSE_DEPRECATED_FUNCTION
11191 ROSE_ASSERT (worked);
11192 } else if (isSgInitializedName(parent)) {
11193 SgInitializedName* initializedNameParent = isSgInitializedName(parent);
11194 if (oldExp == initializedNameParent->get_initializer()) {
11195 //We can only replace an initializer expression with another initializer expression
11196 ROSE_ASSERT(isSgInitializer(newExp));
11197 initializedNameParent->set_initializer(isSgInitializer(newExp));
11198 } else {
11199 //What other expressions can be children of an SgInitializedname?
11200 ROSE_ABORT();
11201 }
11202 } else if (isSgCaseOptionStmt(parent)) {
11203 SgCaseOptionStmt * case_stmt = isSgCaseOptionStmt(parent);
11204 if (oldExp == case_stmt->get_key()) {
11205 case_stmt->set_key(newExp);
11206 } else if(oldExp == case_stmt->get_key_range_end()) {
11207 case_stmt->set_key_range_end(newExp);
11208 } else {
11209 ROSE_ABORT();
11210 }
11211 } else if (isSgProcessControlStatement(parent)) {
11213 if (oldExp == ctrl_stmt->get_quiet()) {
11214 ctrl_stmt->set_quiet(newExp);
11215 } else if (oldExp == ctrl_stmt->get_code()) {
11216 ctrl_stmt->set_code(newExp);
11217 } else {
11218 ROSE_ABORT();
11219 }
11220 } else if (isSgFortranDo(parent)) {
11221 SgFortranDo* fortranDo = isSgFortranDo(parent);
11222 if (oldExp == fortranDo->get_initialization()) {
11223 fortranDo->set_initialization(newExp);
11224 } else if(oldExp == fortranDo->get_bound()) {
11225 fortranDo->set_bound(newExp);
11226 } else if (oldExp == fortranDo->get_increment()) {
11227 fortranDo->set_increment(newExp);
11228 } else {
11229 ROSE_ABORT();
11230 }
11231 }
11232 else if (SgAdaExitStmt* stm = isSgAdaExitStmt(parent)) {
11233 ROSE_ASSERT(oldExp == stm->get_condition());
11234 stm->set_condition(newExp);
11235 }
11236 else if (SgAdaModularType* ptype = isSgAdaModularType(parent)) {
11237 ROSE_ASSERT(oldExp == ptype->get_modexpr());
11238 ptype->set_modexpr(newExp);
11239 }
11240 else if (SgAdaDelayStmt* stm = isSgAdaDelayStmt(parent)) {
11241 ROSE_ASSERT(oldExp == stm->get_time());
11242 stm->set_time(newExp);
11243 } else if (SgAdaAttributeClause* clause = isSgAdaAttributeClause(parent)) {
11244 ROSE_ASSERT(oldExp == clause->get_size());
11245 clause->set_size(newExp);
11246 } else if (SgAdaRenamingDecl* dcl = isSgAdaRenamingDecl(parent)) {
11247 ROSE_ASSERT(oldExp == dcl->get_renamed());
11248 dcl->set_renamed(newExp);
11249 } else if (SgAdaEntryDecl* dcl = isSgAdaEntryDecl(parent)) {
11250 ROSE_ASSERT(oldExp == dcl->get_entryBarrier());
11251 dcl->set_entryBarrier(newExp);
11252 } else if (SgAdaSelectAlternativeStmt* stm = isSgAdaSelectAlternativeStmt(parent)) {
11253 ROSE_ASSERT(oldExp == stm->get_guard());
11254 stm->set_guard(newExp);
11255 } else if (SgAdaDeltaConstraint* delc = isSgAdaDeltaConstraint(parent)) {
11256 ROSE_ASSERT(oldExp == delc->get_delta());
11257 delc->set_delta(newExp);
11258 } else if (SgAdaDigitsConstraint* digc = isSgAdaDigitsConstraint(parent)) {
11259 ROSE_ASSERT(oldExp == digc->get_digits());
11260 digc->set_digits(newExp);
11261 } else if (SgAdaDiscriminantConstraint* disc = isSgAdaDiscriminantConstraint(parent)) {
11262 replaceExpressionInSgExpressionPtrList(oldExp, newExp, disc->get_discriminants());
11263 } else if (SgAdaRangeConstraint* rngc = isSgAdaRangeConstraint(parent)) {
11264 ROSE_ASSERT(oldExp == rngc->get_range());
11265 rngc->set_range(newExp);
11266 } else if (SgAdaIndexConstraint* idxc = isSgAdaIndexConstraint(parent)) {
11267 replaceExpressionInSgExpressionPtrList(oldExp, newExp, idxc->get_indexRanges());
11268 } else if (SgAdaVariantDecl* vtdcl = isSgAdaVariantDecl(parent)) {
11269 ROSE_ASSERT(oldExp == vtdcl->get_discriminant());
11270 vtdcl->set_discriminant(newExp);
11271 } else if (SgAdaRepresentationClause* clause = isSgAdaRepresentationClause(parent)) {
11272 ROSE_ASSERT(oldExp == clause->get_alignment());
11273 clause->set_alignment(newExp);
11274 } else if (SgAdaVariantWhenStmt* vtwhen = isSgAdaVariantWhenStmt(parent)) {
11275 ROSE_ASSERT(oldExp == vtwhen->get_choices());
11276 SgExprListExp* newLst = isSgExprListExp(newExp);
11277 ROSE_ASSERT(newLst);
11278 vtwhen->set_choices(newLst);
11279 } else if (SgAdaComponentClause* clause = isSgAdaComponentClause(parent)) {
11280 if (oldExp == clause->get_offset())
11281 clause->set_offset(newExp);
11282 else if (oldExp == clause->get_range() && isSgRangeExp(newExp))
11283 clause->set_range(isSgRangeExp(newExp));
11284 else if (oldExp == clause->get_component() && isSgVarRefExp(newExp))
11285 clause->set_component(isSgVarRefExp(newExp));
11286 else
11287 ROSE_ABORT();
11288 } else {
11289 cerr<<"SageInterface::replaceExpression(). Unhandled parent expression type of SageIII enum value: " <<parent->class_name()<<endl;
11290 ROSE_ABORT();
11291 }
11292
11293 if (!keepOldExp) {
11294 deepDelete(oldExp); // avoid dangling node in memory pool
11295 } else {
11296 oldExp->set_parent(NULL);
11297 }
11298
11299} //replaceExpression()
11300
11302 {
11303 // reuse the implementation in ROSE namespace from src/roseSupport/utility_functions.C
11304 return Rose::getNextStatement(currentStmt);
11305 }
11306
11307SgStatement* SageInterface::getPreviousStatement(SgStatement * currentStmt, bool climbOutScope /*= true*/)
11308 {
11309 return Rose::getPreviousStatement(currentStmt, climbOutScope);
11310 }
11311
11313 return isSgIntVal(e) && isSgIntVal(e)->get_value() == value;
11314 }
11315
11317 {
11318 ROSE_ASSERT(func1&& func2);
11319 bool result = false;
11320 if (func1 == func2)
11321 result = true;
11322 else
11323 {
11325 {
11326 if (func1->get_name() == func2->get_name())
11327 result = true;
11328 }
11329 else if (is_Cxx_language() || is_Java_language())
11330 {
11331 if (func1->get_qualified_name().getString() +
11332 func1->get_mangled_name().getString() ==
11333 func2->get_qualified_name().getString() +
11334 func2->get_mangled_name().getString()
11335 )
11336 result = true;
11337 }
11338 else if (is_Fortran_language())
11339 {
11340 if (func1->get_name() == func2->get_name())
11341 result = true;
11342 }
11343 else
11344 {
11345 cout<<"Error: SageInterface::isSameFunction(): unhandled language"<<endl;
11346 ROSE_ABORT();
11347 }
11348
11349 } // not identical
11350 return result;
11351 } // isSameFunction()
11352
11355{
11356 bool result =false;
11357 ROSE_ASSERT(stmt != NULL);
11358 SgScopeStatement* p_scope = stmt->get_scope();
11359 ROSE_ASSERT(p_scope != NULL);
11360#if 0
11361 if (p_scope->containsOnlyDeclarations())
11362 {
11363 SgDeclarationStatementPtrList stmtlist= p_scope->getDeclarationList ()
11364 if (stmtlist[stmtlist.size()-1] == stmt)
11365 result = true;
11366 }
11367 else
11368 {
11369 SgStatementPtrList stmtlist= p_scope->getStatementList ();
11370 if (stmtlist[stmtlist.size()-1] == stmt)
11371 result = true;
11372 }
11373#endif
11374 SgStatementPtrList stmtlist= p_scope->generateStatementList ();
11375 if (stmtlist[stmtlist.size()-1] == stmt)
11376 result = true;
11377
11378 return result;
11379}
11380
11381#ifndef USE_ROSE
11382//-----------------------------------------------
11383// Remove original expression trees from expressions, so you can change
11384// the value and have it unparsed correctly.
11386 struct Visitor: public AstSimpleProcessing {
11387 virtual void visit(SgNode* n) {
11388 SgValueExp* valueExp = isSgValueExp(n);
11389 if (valueExp != NULL) {
11390 valueExp->set_originalExpressionTree(NULL);
11391 }
11392 else {
11393 SgCastExp* cast_exp = isSgCastExp(n);
11394 if (cast_exp != NULL) {
11395 cast_exp->set_originalExpressionTree(NULL);
11396 }
11397 }
11398 }
11399 };
11400 Visitor().traverse(top, preorder);
11401}
11402#endif
11403
11405 while (s && !isSgSwitchStatement(s)) {
11406 s = isSgStatement(s->get_parent());
11407 }
11408 ROSE_ASSERT (s);
11409 return isSgSwitchStatement(s);
11410}
11411
11414 while (s && !isSgOmpClauseBodyStatement(s)) {
11415 s = isSgStatement(s->get_parent());
11416 }
11417 // ROSE_ASSERT (s); // s is allowed to be NULL.
11418 if (s==NULL)
11419 return NULL;
11420 return isSgOmpClauseBodyStatement(s);
11421}
11422
11423
11424SgScopeStatement* SageInterface::findEnclosingLoop(SgStatement* s, const std::string& label, bool stopOnSwitches) {
11425 /* label can represent a fortran label or a java label provided as a label in a continue/break statement */
11426 for (; s; s = isSgStatement(s->get_parent())) {
11427 SgScopeStatement* sc = isSgScopeStatement(s);
11428 // Need to check for empty label as for java we must detect the
11429 // innermost labeled statement and skip everything in between
11430 switch (s->variantT()) {
11431 case V_SgDoWhileStmt: {
11432 if (label.empty()) {
11433 return sc;
11434 }
11435 break;
11436 }
11437 case V_SgForStatement: {
11438 if (label.empty()) {
11439 return sc;
11440 }
11441 break;
11442 }
11443 case V_SgFortranDo:
11444 case V_SgFortranNonblockedDo: {
11445 if (label.empty() ||
11446 label == isSgFortranDo(sc)->get_string_label()) {
11447 return sc;
11448 }
11449 break;
11450 }
11451 case V_SgWhileStmt: {
11452 if (label.empty() ||
11453 label == isSgWhileStmt(sc)->get_string_label()) {
11454 return sc;
11455 }
11456 break;
11457 }
11458 case V_SgSwitchStatement: {
11459 if (stopOnSwitches) return sc;
11460 break;
11461 }
11462 case V_SgJavaForEachStatement: {
11463 if (label.empty()) {
11464 return sc;
11465 }
11466 break;
11467 }
11468 case V_SgJavaLabelStatement: {
11469 if (label.empty() ||
11470 label == isSgJavaLabelStatement(sc)->get_label().getString()) {
11471 return sc;
11472 }
11473 break;
11474 }
11475 default: continue;
11476 }
11477 }
11478 return NULL;
11479}
11480
11481#ifndef USE_ROSE
11483{
11484 class RemoveJumpsToNextStatementVisitor: public AstSimpleProcessing {
11485 public:
11486 virtual void visit(SgNode* n) {
11487 if (isSgBasicBlock(n)) {
11488 SgBasicBlock* bb = isSgBasicBlock(n);
11489 bool changes = true;
11490 while (changes) {
11491 changes = false;
11492 for (SgStatementPtrList::iterator i = bb->get_statements().begin();
11493 i != bb->get_statements().end(); ++i) {
11494 if (isSgGotoStatement(*i)) {
11495 SgGotoStatement* gs = isSgGotoStatement(*i);
11496 SgStatementPtrList::iterator inext = i;
11497 ++inext;
11498 if (inext == bb->get_statements().end())
11499 continue;
11500 if (!isSgLabelStatement(*inext))
11501 continue;
11502 SgLabelStatement* ls = isSgLabelStatement(*inext);
11503 if (gs->get_label() == ls) {
11504 changes = true;
11505 bb->get_statements().erase(i);
11506 break;
11507 }
11508 }
11509 }
11510 }
11511 }
11512 }
11513 };
11514
11515 RemoveJumpsToNextStatementVisitor().traverse(top, postorder);
11516
11517}
11518#endif
11519
11520// special purpose remove for AST transformation/optimization from astInliner, don't use it otherwise.
11522 // assert (LowLevelRewrite::isRemovableStatement(*i));
11523 SgStatement* parent = isSgStatement(stmt->get_parent());
11524 ROSE_ASSERT (parent);
11525 SgBasicBlock* bb = isSgBasicBlock(parent);
11526 SgForInitStatement* fis = isSgForInitStatement(parent);
11527 if (bb || fis) {
11528 ROSE_ASSERT (bb || fis);
11529 SgStatementPtrList& siblings =
11530 (bb ? bb->get_statements() : fis->get_init_stmt());
11531 SgStatementPtrList::iterator j =
11532 std::find(siblings.begin(), siblings.end(), stmt);
11533 ROSE_ASSERT (j != siblings.end());
11534 siblings.erase(j);
11535 // LowLevelRewrite::remove(*i);
11536 } else {
11537 parent->replace_statement(stmt, new SgNullStatement(TRANS_FILE));
11538 }
11539}
11540
11541
11542#ifndef USE_ROSE
11543std::set<SgLabelStatement*> SageInterface::findUnusedLabels (SgNode* top)
11544{
11545 class FindUsedAndAllLabelsVisitor: public AstSimpleProcessing {
11546 SgLabelStatementPtrSet& used;
11547 SgLabelStatementPtrSet& all;
11548
11549 public:
11550 FindUsedAndAllLabelsVisitor(SgLabelStatementPtrSet& used,
11551 SgLabelStatementPtrSet& all):
11552 used(used), all(all) {}
11553
11554 virtual void visit(SgNode* n) {
11555 if (isSgGotoStatement(n)) {
11556 used.insert(isSgGotoStatement(n)->get_label());
11557 }
11558 if (isSgLabelStatement(n)) {
11559 all.insert(isSgLabelStatement(n));
11560 }
11561 }
11562 };
11563
11564 SgLabelStatementPtrSet used;
11565 SgLabelStatementPtrSet unused;
11566 FindUsedAndAllLabelsVisitor(used, unused).traverse(top, preorder);
11567
11568 for (SgLabelStatementPtrSet::iterator i = used.begin();
11569 i != used.end(); ++i) {
11570 assert (unused.find(*i) != unused.end());
11571 // std::cout << "Keeping used label " << (*i)->get_label().str() << std::endl;
11572 unused.erase(*i);
11573 }
11574
11575 return unused;
11576}
11577
11578// Remove all unused labels in a section of code.
11579void SageInterface::removeUnusedLabels(SgNode* top, bool keepChild/* =false */) {
11580
11581 SgLabelStatementPtrSet unused = findUnusedLabels(top);
11582
11583 for (SgLabelStatementPtrSet::iterator i = unused.begin();
11584 i != unused.end(); ++i) {
11585
11586 SgLabelStatement* l_stmt = *i;
11587 // std::cout << "Removing unused label " << (*i)->get_label().str() << std::endl;
11588 if (keepChild)
11589 {
11590 SgStatement* child= l_stmt->get_statement();
11591// l_stmt->set_parent(NULL);
11592 l_stmt->set_statement(NULL);
11593 replaceStatement (l_stmt, child);
11594 }
11595 else
11597 }
11598}
11599#endif
11600
11602 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_body();
11603 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_loop_body();
11604 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_body();
11605
11606 ROSE_ASSERT (!"Bad loop kind");
11607 return NULL;
11608 }
11609
11611 if (isSgWhileStmt(loopStmt)) {
11612 isSgWhileStmt(loopStmt)->set_body(body);
11613 } else if (isSgForStatement(loopStmt)) {
11614 isSgForStatement(loopStmt)->set_loop_body(body);
11615 } else if (isSgDoWhileStmt(loopStmt)) {
11616 isSgDoWhileStmt(loopStmt)->set_body(body);
11617 } else {
11618 ROSE_ASSERT (!"Bad loop kind");
11619 }
11620 body->set_parent(loopStmt);
11621 }
11622
11624 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_condition();
11625 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_test();
11626 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_condition();
11627
11628 ROSE_ASSERT (!"Bad loop kind");
11629 return NULL;
11630 }
11631
11633 if (isSgWhileStmt(loopStmt)) {
11634 isSgWhileStmt(loopStmt)->set_condition(cond);
11635 } else if (isSgForStatement(loopStmt)) {
11636 isSgForStatement(loopStmt)->set_test(cond);
11637 } else if (isSgDoWhileStmt(loopStmt)) {
11638 isSgDoWhileStmt(loopStmt)->set_condition(cond);
11639 } else {
11640 ROSE_ASSERT (!"Bad loop kind");
11641 }
11642 cond->set_parent(loopStmt);
11643 }
11644
11646// usually useful when compare two expressions to see if they actually refer to the same variable
11647static SgExpression* SkipCasting (SgExpression* exp)
11648{
11649 SgCastExp* cast_exp = isSgCastExp(exp);
11650 if (cast_exp != NULL)
11651 {
11652 SgExpression* operand = cast_exp->get_operand();
11653 assert(operand != 0);
11654 return SkipCasting(operand);
11655 }
11656 else
11657 return exp;
11658}
11659
11662{
11663 ROSE_ASSERT(loop!=NULL);
11664
11665 SgStatementPtrList &init = loop ->get_init_stmt();
11666 if (init.size() !=1) // We only handle one statement case
11667 return false;
11668
11669 SgStatement* init1 = init.front();
11670 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
11671 if (decl == NULL) // we only handle for (int i=0; ...)
11672 return true; // the return value is ambiguous: if not int i=0; it is already normalized
11673
11674 SgVariableSymbol* osymbol = getFirstVarSym(decl);
11675 SgInitializedName* ivarname = decl->get_variables().front();
11676 SgExpression* lbast = NULL; // the lower bound, initial state
11677 ROSE_ASSERT(ivarname != NULL);
11678 SgInitializer * initor = ivarname->get_initializer();
11679 if (isSgAssignInitializer(initor))
11680 {
11681 lbast = isSgAssignInitializer(initor)->get_operand();
11682 }
11683 else
11684 { //SgConstructorInitializer etc.
11685 // other complex declaration statements, such as Decomposition::Iterator ditr(&decomp) should be skipped
11686 // they cause a loop to be non-canonical.
11687 return false;
11688 }
11689
11690 // add a new statement like int i; and insert it to the enclosing function
11691 // There are multiple choices about where to insert this statement:
11692 // global scope: max name pollution,
11693 // right before the loop: mess up perfectly nested loops
11694 // So we prepend the statement to the enclosing function's body
11696 ROSE_ASSERT(funcDef!=NULL);
11697 SgBasicBlock* funcBody = funcDef->get_body();
11698 ROSE_ASSERT(funcBody!=NULL);
11699 //TODO a better name
11700 std::ostringstream os;
11701 os<<ivarname->get_name().getString();
11702
11703 // keep the original variable name if possible
11704 SgSymbol * visibleSym = NULL;
11705 visibleSym = lookupVariableSymbolInParentScopes(ivarname->get_name(), funcBody);
11706 if (visibleSym != NULL) // if there is a name collision, add suffix to the variable name
11707 {
11708 os<<"_nom_";
11709 os<<++gensym_counter;
11710 }
11711
11712 SgVariableDeclaration* ndecl = buildVariableDeclaration(os.str(),ivarname->get_type(), NULL, funcBody);
11713 prependStatement(ndecl, funcBody);
11714 SgVariableSymbol* nsymbol = getFirstVarSym(ndecl);
11715
11716 // replace variable ref to the new symbol
11717 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11718 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11719 {
11720 SgVarRefExp *vRef = isSgVarRefExp((*i));
11721 if (vRef->get_symbol()==osymbol)
11722 vRef->set_symbol(nsymbol);
11723 }
11724 // replace for (int i=0;) with for (i=0;)
11726 removeStatement(decl); //any side effect to the symbol? put after symbol replacement anyway
11727 init.push_back(ninit);
11728 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11729 // ninit->set_parent(loop);
11730 ninit->set_parent(loop->get_for_init_stmt ());
11731
11732 // keep record of this normalization
11733 // We may undo it later on.
11734 trans_records.forLoopInitNormalizationTable[loop] = true;
11735 trans_records.forLoopInitNormalizationRecord[loop] = make_pair (decl, ndecl) ;
11736
11737 return true;
11738}
11739
11740/*
11741 int i_norm_1;
11742 for (i_norm_1=0; i_norm_1<upper; i_norm_1 ++ );
11743Becomes:
11744 for (int i=0; i< upper; i++) ;
11745 * */
11747{
11748 ROSE_ASSERT (loop != NULL);
11749 //If not previously normalized, nothing to do and return false.
11750 if (!trans_records.forLoopInitNormalizationTable[loop])
11751 return false;
11752 // retrieve original and new declaration of the previous normalization
11753 SgVariableDeclaration* decl = trans_records.forLoopInitNormalizationRecord[loop].first;
11754 SgVariableDeclaration* ndecl = trans_records.forLoopInitNormalizationRecord[loop].second;
11755 ROSE_ASSERT (decl!= NULL);
11756 ROSE_ASSERT (ndecl!= NULL);
11757
11758
11759 // Sanity check
11760 SgStatementPtrList &init = loop ->get_init_stmt();
11761 ROSE_ASSERT(init.size() ==1); // We only handle one statement case
11762
11763 // remove the current init_stmt
11764 SgStatement* init1 = init.front();
11765 SgExprStatement* exp_stmt = isSgExprStatement(init1);
11766 ROSE_ASSERT (exp_stmt != NULL);
11767 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
11768 ROSE_ASSERT (assign_op != NULL);
11769
11770 // remove the new declaration and the current i_norm=1;
11771 removeStatement(ndecl);
11772 removeStatement (exp_stmt);
11773
11774 // restore the original declaration
11775 init.push_back(decl);
11776 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11777 // ninit->set_parent(loop);
11778 decl->set_parent(loop->get_for_init_stmt ());
11779
11780 // replace variable references
11781 // current symbol in the AST
11782 SgVariableSymbol* osymbol = getFirstVarSym(ndecl);
11783 // new symbol we want to have: the original decl
11784 SgVariableSymbol* nsymbol = getFirstVarSym(decl);
11785 // replace variable ref to the new symbol
11786 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11787 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11788 {
11789 SgVarRefExp *vRef = isSgVarRefExp((*i));
11790 if (vRef->get_symbol()==osymbol)
11791 vRef->set_symbol(nsymbol);
11792 }
11793
11794 // clear record: now the loop is not normalized any more
11795 trans_records.forLoopInitNormalizationTable[loop] = false;
11796 return true;
11797}
11798
11800{
11801 ROSE_ASSERT(loop != NULL);
11802
11803 // Normalized the test expressions
11804 // -------------------------------------
11805#if 0 // this is undecided
11806 // skip for (;;) case
11807 SgStatement* test_stmt = loop->get_test();
11808 if (test_stmt!=NULL)
11809 {
11810 if (isSgNullStatement(test_stmt))
11811 return false;
11812 }
11813#endif
11814 SgExpression* test = loop->get_test_expr();
11815 SgExpression* testlhs=NULL, * testrhs=NULL;
11816 if (isSgBinaryOp(test))
11817 {
11818 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11819 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11820 ROSE_ASSERT(testlhs && testrhs);
11821 }
11822 else
11823 return false;
11824 // keep the variable since test will be removed later on
11825 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11826 if (testlhs_var == NULL )
11827 return false;
11828 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11829 if (var_symbol==NULL)
11830 return false;
11831
11832 switch (test->variantT()) {
11833 case V_SgLessThanOp: // i<x is normalized to i<= (x-1)
11835 buildSubtractOp(deepCopy(testrhs), buildIntVal(1))));
11836 // deepDelete(test);// replaceExpression() does this already by default.
11837 break;
11838 case V_SgGreaterThanOp: // i>x is normalized to i>= (x+1)
11840 buildAddOp(deepCopy(testrhs), buildIntVal(1))));
11841 break;
11842 case V_SgLessOrEqualOp:
11843 case V_SgGreaterOrEqualOp:
11844 case V_SgNotEqualOp: //TODO Do we want to allow this?
11845 break;
11846 default:
11847 return false;
11848 }
11849 return true;
11850}
11852{
11853 ROSE_ASSERT(loop != NULL);
11854
11855 SgExpression* test = loop->get_test_expr();
11856 SgExpression* testlhs=NULL, * testrhs=NULL;
11857 if (isSgBinaryOp(test))
11858 {
11859 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11860 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11861 ROSE_ASSERT(testlhs && testrhs);
11862 }
11863 else
11864 return false;
11865 // keep the variable since test will be removed later on
11866 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11867 if (testlhs_var == NULL )
11868 return false;
11869 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11870 if (var_symbol==NULL)
11871 return false;
11872
11873
11874 // -------------------------------------
11875 SgExpression* incr = loop->get_increment();
11876 ROSE_ASSERT(incr != NULL);
11877 switch (incr->variantT()) {
11878 case V_SgPlusPlusOp: //i++ is normalized to i+=1
11879 {
11880 // check if the variables match
11881 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgPlusPlusOp(incr)->get_operand()));
11882 if (incr_var == NULL) return false;
11883 if ( incr_var->get_symbol() != var_symbol)
11884 return false;
11885 replaceExpression(incr,
11886 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)),buildIntVal(1)));
11887 break;
11888 }
11889 case V_SgMinusMinusOp: //i-- is normalized to i+=-1
11890 {
11891 // check if the variables match
11892 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusMinusOp(incr)->get_operand()));
11893 if (incr_var == NULL) return false;
11894 if ( incr_var->get_symbol() != var_symbol)
11895 return false;
11896 replaceExpression(incr,
11897 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildIntVal(-1)));
11898 break;
11899 }
11900 case V_SgMinusAssignOp: // i-= s is normalized to i+= -s
11901 {
11902 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusAssignOp(incr)->get_lhs_operand()));
11903 SgExpression* rhs = isSgMinusAssignOp(incr)->get_rhs_operand();
11904 ROSE_ASSERT (rhs != NULL);
11905 if (incr_var == NULL) return false;
11906 if ( incr_var->get_symbol() != var_symbol)
11907 return false;
11908 replaceExpression(incr,
11909 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildMultiplyOp(buildIntVal(-1), copyExpression(rhs))));
11910 break;
11911 }
11912 case V_SgAssignOp:
11913 case V_SgPlusAssignOp:
11914 break;
11915 default:
11916 return false;
11917 }
11918
11919 return true;
11920}
11922// Her loop translation does not pass AST consistency tests so we rewrite some of them here
11923// NormalizeCPP.C NormalizeLoopTraverse::ProcessLoop()
11924bool SageInterface::forLoopNormalization(SgForStatement* loop, bool foldConstant /*= true*/)
11925{
11926 ROSE_ASSERT(loop != NULL);
11927 // Normalize initialization statement of the for loop
11928 // -------------------------------------
11929 // for (int i=0;... ) becomes int i; for (i=0;..)
11930 // Only roughly check here, isCanonicalForLoop() should be called to have a stricter check
11932 return false;
11933
11934 // Normalized the test expressions
11935 if (!normalizeForLoopTest(loop))
11936 return false;
11937
11938 // Normalize the increment expression
11939 if (!normalizeForLoopIncrement(loop))
11940 return false;
11941
11942 // Normalize the loop body: ensure there is a basic block
11944 ROSE_ASSERT(body!=NULL);
11945 // Liao, 9/22/2009
11946 // folding entire loop may cause decreased accuracy for floating point operations
11947 // we only want to fold the loop controlling expressions
11948 if (foldConstant)
11949 {
11950 //constantFolding(loop->get_parent());
11951 constantFolding(loop->get_test());
11952 constantFolding(loop->get_increment());
11953 }
11954
11955 return true;
11956}
11957
11960{
11961 // TODO, normalize continue to enddo ?
11962 ROSE_ASSERT (loop != NULL);
11963 SgExpression* e_3 = loop->get_increment();
11964 if (isSgNullExpression(e_3))
11965 {
11966 SgIntVal* iv = buildIntVal(1);
11967 loop->set_increment(iv);
11968 iv->set_parent(loop);
11969 delete (e_3);
11970 }
11971 return true;
11972}
11973
11974#if 0
11975bool SageInterface::loopUnrolling(SgForStatement* loop, size_t unrolling_factor)
11976{
11977 // normalize the loop first
11978 if (!forLoopNormalization(loop))
11979 return false; // input loop cannot be normalized to a canonical form
11980 // prepare Loop transformation environment
11982 ROSE_ASSERT(func!=NULL);
11983 AstInterfaceImpl faImpl(func->get_definition()->get_body());
11984 AstInterface fa(&faImpl);
11985 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
11986 ArrayInterface array_interface (*annot);
11987 array_interface.initialize(fa, AstNodePtrImpl(func->get_definition()));
11988 array_interface.observe(fa);
11989 LoopTransformInterface :: set_astInterface(fa);
11990 LoopTransformInterface :: set_arrayInterface(&array_interface);
11991
11992 // invoke the unrolling defined in Qing's code
11993 // the traversal will skip the input node ptr, so we pass loop's parent ptr instead
11994 AstNodePtr result = AstNodePtrImpl(loop->get_parent()) ;
11995
11996 LoopUnrolling lu(unrolling_factor);
11997 //LoopUnrolling lu(unrolling_factor,LoopUnrolling::COND_LEFTOVER);//works but not a good choice
11998 //if (lu.cmdline_configure()) // this will cause unrolling to be skipped if no -unroll is used in command line
11999 result = lu(lpTrans, result);
12000 return true;
12001}
12002#else
12003
12004// a brand new serious implementation for loop unrolling, Liao, 6/25/2009
12005/* Handle left-over iterations if iteration_count%unrolling_factor != 0
12006 * Handle stride (step) >1
12007 * Assuming loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
12008 *
12009 * iteration_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1
12010 * fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step;
12011 * fringe ==0 if no leftover iterations
12012 * otherwise adjust ub so the leftover iterations will put into the last fringe loop
12013 * unrolled loop's header: for (i=lb;i<=ub - fringe; i+= step*unroll_factor)
12014 * loop body: copy body n times from 0 to factor -1
12015 * stmt(i+ 0*step); ...; stmt (i+ (factor-1)*step);
12016 * fringe loop: the same as the original loop, except for no init statement
12017 *
12018 * e.g:
12019 * // unrolling 3 times for the following loop with stride !=1
12020 * for (i=0; i<=9; i+=3)
12021 * {
12022 * a[i]=i;
12023 * }
12024 * // it becomes
12025 * // iteration count = 10%3=1 -> 10/3+1 = 4
12026 * // fringe = 4%3 =1 --> 3*3
12027 * // ub-fringe = 9-3*3
12028 * for (i=0; i<=9-3*3; i+=3*3)
12029 * {
12030 * a[i+3*0]=i;
12031 * a[i+3*1]=i;
12032 * a[i+3*2]=i;
12033 * }
12034 * // i=9 is the leftover iteration
12035 * for (; i<=9; i+=3)
12036 * {
12037 * a[i]=i;
12038 * }
12039 *
12040 */
12041bool SageInterface::loopUnrolling(SgForStatement* target_loop, size_t unrolling_factor)
12042{
12043#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
12044 //Handle 0 and 1, which means no unrolling at all
12045 if (unrolling_factor <= 1)
12046 return true;
12047
12048 // normalize the target loop first
12049
12050 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12051 if (!forLoopNormalization(target_loop))
12052 {
12053 // the return value is not reliable
12054 // cerr<<"Error in SageInterface::loopUnrolling(): target loop cannot be normalized."<<endl;
12055 // dumpInfo(target_loop);
12056 // return false;
12057 }
12058 // grab the target loop's essential header information
12059 SgInitializedName* ivar = NULL;
12060 SgExpression* lb = NULL;
12061 SgExpression* ub = NULL;
12062 SgExpression* step = NULL;
12063 SgStatement* orig_body = NULL;
12064 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, &orig_body))
12065 {
12066 cerr<<"Error in SageInterface::loopUnrolling(): target loop is not canonical."<<endl;
12067 dumpInfo(target_loop);
12068 return false;
12069 }
12070 ROSE_ASSERT(ivar&& lb && ub && step);
12071 ROSE_ASSERT(isSgBasicBlock(orig_body));
12072
12073 // generate the fringe loop
12074 bool needFringe = true;
12075 SgForStatement* fringe_loop = deepCopy<SgForStatement>(target_loop);
12076 insertStatementAfter(target_loop,fringe_loop);
12077 removeStatement(fringe_loop->get_for_init_stmt());
12078 fringe_loop->set_for_init_stmt(NULL);
12079
12080 // _lu_iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;
12082 copyExpression(lb));
12083 raw_range_exp->set_need_paren(true);
12084 SgExpression* range_d_step_exp = buildDivideOp(raw_range_exp,copyExpression(step));//(ub-lb+1)/step
12085 SgExpression* condition_1 = buildEqualityOp(buildModOp(copyExpression(raw_range_exp),copyExpression(step)),buildIntVal(0)); //(ub-lb+1)%step ==0
12086
12087 SgExpression* iter_count_exp = buildConditionalExp(condition_1,range_d_step_exp, buildAddOp(copyExpression(range_d_step_exp),buildIntVal(1)));
12088 // fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step
12089 SgExpression* condition_2 = buildEqualityOp(buildModOp(iter_count_exp, buildIntVal(unrolling_factor)), buildIntVal(0));
12090 SgExpression* initor = buildConditionalExp(condition_2, buildIntVal(0), buildMultiplyOp(buildIntVal(unrolling_factor),copyExpression(step)));
12091
12092 SgScopeStatement* scope = target_loop->get_scope();
12093 ROSE_ASSERT(scope != NULL);
12094 string fringe_name = "_lu_fringe_"+ StringUtility::numberToString(++gensym_counter);
12095 SgVariableDeclaration* fringe_decl = buildVariableDeclaration(fringe_name, buildIntType(),buildAssignInitializer(initor), scope);
12096 insertStatementBefore(target_loop, fringe_decl);
12097 attachComment(fringe_decl, "iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;");
12098 attachComment(fringe_decl, "fringe = iter_count%unroll_factor==0 ? 0:unroll_factor*step");
12099
12100 // compile-time evaluate to see if index is a constant of value 0
12101 // if so, the iteration count can be divided even by the unrolling factor
12102 // and no fringe loop is needed
12103 // WE have to fold on its parent node to get a possible constant since
12104 // constant folding only folds children nodes, not the current node to a constant
12105 ConstantFolding::constantFoldingOptimization(fringe_decl,false);
12106 SgInitializedName * ivarname = fringe_decl->get_variables().front();
12107 ROSE_ASSERT(ivarname != NULL);
12108 // points to a new address if constant folding happens
12109 SgAssignInitializer * init1 = isSgAssignInitializer(ivarname->get_initializer());
12110 if (init1)
12111 if (isSgIntVal(init1->get_operand_i()))
12112 if (isSgIntVal(init1->get_operand_i())->get_value() == 0)
12113 needFringe = false;
12114
12115 // rewrite loop header ub --> ub -fringe; step --> step *unrolling_factor
12116 SgBinaryOp* ub_bin_op = isSgBinaryOp(ub->get_parent());
12117 ROSE_ASSERT(ub_bin_op);
12118 if (needFringe)
12119 ub_bin_op->set_rhs_operand(buildSubtractOp(copyExpression(ub),buildVarRefExp(fringe_name,scope)));
12120 else
12121 {
12122 ub_bin_op->set_rhs_operand(copyExpression(ub));
12123 removeStatement(fringe_decl);
12124 }
12125
12126 SgBinaryOp* step_bin_op = isSgBinaryOp(step->get_parent());
12127 ROSE_ASSERT(step_bin_op != NULL);
12128 step_bin_op->set_rhs_operand(buildMultiplyOp(copyExpression(step),buildIntVal(unrolling_factor)));
12129
12130 bool isPlus = false;
12131 if (isSgPlusAssignOp(step_bin_op))
12132 isPlus = true;
12133 else if (isSgMinusAssignOp(step_bin_op))
12134 isPlus = false;
12135 else
12136 {
12137 cerr<<"Error in SageInterface::loopUnrolling(): illegal incremental exp of a canonical loop"<<endl;
12138 dumpInfo(step_bin_op);
12139 ROSE_ABORT();
12140 }
12141
12142 // copy loop body factor -1 times, and replace reference to ivar with ivar +/- step*[1 to factor-1]
12143 for (size_t i =1; i<unrolling_factor; i++)
12144 {
12145 SgBasicBlock* body = isSgBasicBlock(deepCopy(fringe_loop->get_loop_body())); // normalized loop has a BB body
12146 ROSE_ASSERT(body);
12147 std::vector<SgVarRefExp*> refs = querySubTree<SgVarRefExp> (body, V_SgVarRefExp);
12148 for (std::vector<SgVarRefExp*>::iterator iter = refs.begin(); iter !=refs.end(); iter++)
12149 {
12150 SgVarRefExp* refexp = *iter;
12151 if (refexp->get_symbol()==ivar->get_symbol_from_symbol_table())
12152 {
12153 // replace reference to ivar with ivar +/- step*i
12154 SgExpression* new_exp = NULL;
12155 //build replacement expression for every appearance
12156 if (isPlus) //ivar +/- step * i
12157 new_exp = buildAddOp(buildVarRefExp(ivar,scope),buildMultiplyOp(copyExpression(step),buildIntVal(i)));
12158 else
12160
12161 // replace it with the right one
12162 replaceExpression(refexp, new_exp);
12163 }
12164 }
12165 // copy body to loop body, this should be a better choice
12166 // to avoid redefinition of variables after unrolling (new scope is introduced to avoid this)
12167 appendStatement(body,isSgBasicBlock(orig_body));
12168 // moveStatementsBetweenBlocks(body,isSgBasicBlock(orig_body));
12169 }
12170
12171 // remove the fringe loop if not needed finally
12172 // it is used to buffering the original loop body before in either cases
12173 if (!needFringe)
12174 removeStatement(fringe_loop);
12175
12176 // constant folding for the transformed AST
12177 ConstantFolding::constantFoldingOptimization(scope,false);
12178 //ConstantFolding::constantFoldingOptimization(getProject(),false);
12179
12180#endif
12181
12182 return true;
12183}
12184#endif
12185
12186// Liao, 6/15/2009
12189static size_t myfactorial (size_t n)
12190{
12191 size_t result=1;
12192 for (size_t i=2; i<=n; i++)
12193 result*=i;
12194 return result;
12195}
12196
12197#endif
12198
12199#ifndef USE_ROSE
12200
12203std::vector<size_t> getPermutationOrder( size_t n, size_t lexicoOrder)
12204{
12205 size_t k = lexicoOrder;
12206 std::vector<size_t> s(n);
12207 // initialize the permutation vector
12208 for (size_t i=0; i<n; i++)
12209 s[i]=i;
12210
12211 //compute (n- 1)!
12212 size_t factorial = myfactorial(n-1);
12213 //check if the number is not in the range of [0, n! - 1]
12214 if (k/n>=factorial)
12215 {
12216 printf("Error: in getPermutationOrder(), lexicoOrder is larger than n!-1\n");
12217 ROSE_ABORT();
12218 }
12219 // Algorithm:
12220 //check each element of the array, excluding the right most one.
12221 //the goal is to find the right element for each s[j] from 0 to n-2
12222 // method: each position is associated a factorial number
12223 // s[0] -> (n-1)!
12224 // s[1] -> (n-2)! ...
12225 // the input number k is divided by the factorial at each position (6, 3, 2, 1 for size =4)
12226 // so only big enough k can have non-zero value after division
12227 // 0 value means no change to the position for the current iteration
12228 // The non-zero value is further modular by the number of the right hand elements of the current element.
12229 // (mode on 4, 3, 2 to get offset 1-2-3, 1-2, 1 from the current position 0, 1, 2)
12230 // choose one of them to be moved to the current position,
12231 // shift elements between the current and the moved element to the right direction for one position
12232 for (size_t j=0; j<n-1; j++)
12233 {
12234 //calculates the next cell from the cells left
12235 //(the cells in the range [j, s.length - 1])
12236 int tempj = (k/factorial) % (n - j);
12237 //Temporarily saves the value of the cell needed
12238 // to add to the permutation this time
12239 int temps = s[j+tempj];
12240 //shift all elements to "cover" the "missing" cell
12241 //shift them to the right
12242 for (size_t i=j+tempj; i>j; i--)
12243 {
12244 s[i] = s[i-1]; //shift the chain right
12245 }
12246 // put the chosen cell in the correct spot
12247 s[j]= temps;
12248 // updates the factorial
12249 factorial = factorial /(n-(j+1));
12250 }
12251#if 0
12252 for (size_t i = 0; i<n; i++)
12253 cout<<" "<<s[i];
12254 cout<<endl;
12255#endif
12256 return s;
12257}
12258
12260/* Translation
12261 Before:
12262 for (i = 0; i < 100; i++)
12263 for (j = 0; j < 100; j++)
12264 for (k = 0; k < 100; k++)
12265 c[i][j]= c[i][j]+a[i][k]*b[k][j];
12266
12267 After tiling i loop nest's level 3 (k-loop) with size 5, it becomes
12268
12269// added a new controlling loop at the outer most level
12270 int _lt_var_k;
12271 for (_lt_var_k = 0; _lt_var_k <= 99; _lt_var_k += 1 * 5) {
12272 for (i = 0; i < 100; i++)
12273 for (j = 0; j < 100; j++)
12274 // rewritten loop header , normalized also
12275 for (k = _lt_var_k; k <= (99 < (_lt_var_k + 5 - 1))?99 : (_lt_var_k + 5 - 1); k += 1) {
12276 c[i][j] = c[i][j] + a[i][k] * b[k][j];
12277 }
12278 }
12279// finally run constant folding
12280
12281 */
12282bool SageInterface::loopTiling(SgForStatement* loopNest, size_t targetLevel, size_t tileSize)
12283{
12284 ROSE_ASSERT(loopNest != NULL);
12285 ROSE_ASSERT(targetLevel >0);
12286 // ROSE_ASSERT(tileSize>0);// 1 is allowed
12287 // skip tiling if tiling size is 0 (no tiling), we allow 0 to get a reference value for the original code being tuned
12288 // 1 (no need to tile)
12289 if (tileSize<=1)
12290 return true;
12291 // Locate the target loop at level n
12292 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(loopNest,V_SgForStatement);
12293 ROSE_ASSERT(loops.size()>=targetLevel);
12294 SgForStatement* target_loop = loops[targetLevel -1]; // adjust to numbering starting from 0
12295
12296 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12297 // normalize the target loop first
12298 if (!forLoopNormalization(target_loop))
12299 {// the return value is not reliable
12300// cerr<<"Error in SageInterface::loopTiling(): target loop cannot be normalized."<<endl;
12301// dumpInfo(target_loop);
12302// return false;
12303 }
12304 // grab the target loop's essential header information
12305 SgInitializedName* ivar = NULL;
12306 SgExpression* lb = NULL;
12307 SgExpression* ub = NULL;
12308 SgExpression* step = NULL;
12309 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, NULL))
12310 {
12311 cerr<<"Error in SageInterface::loopTiling(): target loop is not canonical."<<endl;
12312 dumpInfo(target_loop);
12313 return false;
12314 }
12315 ROSE_ASSERT(ivar&& lb && ub && step);
12316
12317 // Add a controlling loop around the top loop nest
12318 // Ensure the parent can hold more than one children
12319 SgLocatedNode* parent = NULL; //SageInterface::ensureBasicBlockAsParent(loopNest)
12320 if (isBodyStatement(loopNest)) // if it is a single body statement (Already a for statement, not a basic block)
12321 parent = makeSingleStatementBodyToBlock (loopNest);
12322 else
12323 parent = isSgLocatedNode(loopNest ->get_parent());
12324
12325 ROSE_ASSERT(parent!= NULL);
12326 // Now we can prepend a controlling loop index variable: __lt_var_originalIndex
12327 string ivar2_name = "_lt_var_"+ivar->get_name().getString();
12328 SgScopeStatement* scope = loopNest->get_scope();
12330 (ivar2_name, buildIntType(),NULL, scope);
12331 insertStatementBefore(loopNest, loop_index_decl);
12332 // init statement of the loop header, copy the lower bound
12333 SgStatement* init_stmt = buildAssignStatement(buildVarRefExp(ivar2_name,scope), copyExpression(lb));
12334 //two cases <= or >= for a normalized loop
12335 SgExprStatement* cond_stmt = NULL;
12336 SgExpression* orig_test = target_loop->get_test_expr();
12337 if (isSgBinaryOp(orig_test))
12338 {
12339 if (isSgLessOrEqualOp(orig_test))
12340 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12341 else if (isSgGreaterOrEqualOp(orig_test))
12342 {
12343 cond_stmt = buildExprStatement(buildGreaterOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12344 }
12345 else
12346 {
12347 cerr<<"Error: illegal condition operator for a canonical loop"<<endl;
12348 dumpInfo(orig_test);
12349 ROSE_ABORT();
12350 }
12351 }
12352 else
12353 {
12354 cerr<<"Error: illegal condition expression for a canonical loop"<<endl;
12355 dumpInfo(orig_test);
12356 ROSE_ABORT();
12357 }
12358 ROSE_ASSERT(cond_stmt != NULL);
12359
12360 // build loop incremental I
12361 // expression var+=up*tilesize or var-=upper * tilesize
12362 SgExpression* incr_exp = NULL;
12363 SgExpression* orig_incr_exp = target_loop->get_increment();
12364 if( isSgPlusAssignOp(orig_incr_exp))
12365 {
12366 incr_exp = buildPlusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12367 }
12368 else if (isSgMinusAssignOp(orig_incr_exp))
12369 {
12370 incr_exp = buildMinusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12371 }
12372 else
12373 {
12374 cerr<<"Error: illegal increment expression for a canonical loop"<<endl;
12375 dumpInfo(orig_incr_exp);
12376 ROSE_ABORT();
12377 }
12378 SgForStatement* control_loop = buildForStatement(init_stmt, cond_stmt,incr_exp, buildBasicBlock());
12379 insertStatementBefore(loopNest, control_loop);
12380 // move loopNest into the control loop
12381 removeStatement(loopNest);
12382 appendStatement(loopNest,isSgBasicBlock(control_loop->get_loop_body()));
12383
12384 // rewrite the lower (i=lb), upper bounds (i<=/>= ub) of the target loop
12385 SgAssignOp* assign_op = isSgAssignOp(lb->get_parent());
12386 ROSE_ASSERT(assign_op);
12387 assign_op->set_rhs_operand(buildVarRefExp(ivar2_name,scope));
12388 // ub< var_i+tileSize-1? ub:var_i+tileSize-1
12389 SgBinaryOp* bin_op = isSgBinaryOp(ub->get_parent());
12390 ROSE_ASSERT(bin_op);
12391 SgExpression* ub2 = buildSubtractOp(buildAddOp(buildVarRefExp(ivar2_name,scope), buildIntVal(tileSize)), buildIntVal(1));
12392 SgExpression* test_exp = buildLessThanOp(copyExpression(ub),ub2);
12393 test_exp->set_need_paren(true);
12394 ub->set_need_paren(true);
12395 ub2->set_need_paren(true);
12396 SgConditionalExp * triple_exp = buildConditionalExp(test_exp,copyExpression(ub), copyExpression(ub2));
12397 bin_op->set_rhs_operand(triple_exp);
12398 // constant folding
12399 // folding entire loop may decrease the accuracy of floating point calculation
12400 // we fold loop control expressions only
12401 //constantFolding(control_loop->get_scope());
12402 constantFolding(control_loop->get_test());
12403 constantFolding(control_loop->get_increment());
12404 return true;
12405}
12406
12408bool SageInterface::loopInterchange(SgForStatement* loop, size_t depth, size_t lexicoOrder)
12409{
12410 if (lexicoOrder == 0) // allow 0 to mean no interchange at all
12411 return true;
12412 // parameter verification
12413 ROSE_ASSERT(loop != NULL);
12414 //must have at least two levels
12415 ROSE_ASSERT (depth >1);
12416 ROSE_ASSERT(lexicoOrder<myfactorial(depth));
12417 //TODO need to verify the input loop has n perfectly-nested children loops inside
12418 // save the loop nest's headers: init, test, and increment
12419 std::vector<SgForStatement* > loopNest = SageInterface::querySubTree<SgForStatement>(loop,V_SgForStatement);
12420 ROSE_ASSERT(loopNest.size()>=depth);
12421 std::vector<std::vector<SgNode*> > loopHeads;
12422 for (std::vector<SgForStatement* > ::iterator i = loopNest.begin(); i!= loopNest.end(); i++)
12423 {
12424 SgForStatement* cur_loop = *i;
12425 std::vector<SgNode*> head;
12426 head.push_back(cur_loop->get_for_init_stmt());
12427 head.push_back(cur_loop->get_test());
12428 head.push_back(cur_loop->get_increment());
12429 loopHeads.push_back(head);
12430 }
12431
12432 // convert the lexicographical number to a permutation order array permutation[depth]
12433 std::vector<size_t> changedOrder = getPermutationOrder (depth, lexicoOrder);
12434 // rewrite the loop nest to reflect the permutation
12435 // set the header to the new header based on the permutation array
12436 for (size_t i=0; i<depth; i++)
12437 {
12438 // only rewrite if necessary
12439 if (i != changedOrder[i])
12440 {
12441 SgForStatement* cur_loop = loopNest[i];
12442 std::vector<SgNode*> newhead = loopHeads[changedOrder[i]];
12443
12444 SgForInitStatement* init = isSgForInitStatement(newhead[0]);
12445 //ROSE_ASSERT(init != NULL) // could be NULL?
12446 ROSE_ASSERT(init != cur_loop->get_for_init_stmt());
12447 cur_loop->set_for_init_stmt(init);
12448 if (init)
12449 {
12450 init->set_parent(cur_loop);
12452 }
12453
12454 SgStatement* test = isSgStatement(newhead[1]);
12455 cur_loop->set_test(test);
12456 if (test)
12457 {
12458 test->set_parent(cur_loop);
12460 }
12461
12462 SgExpression* incr = isSgExpression(newhead[2]);
12463 cur_loop->set_increment(incr);
12464 if (incr)
12465 {
12466 incr->set_parent(cur_loop);
12468 }
12469 }
12470 }
12471 return true;
12472}
12473
12476{
12477 ROSE_ASSERT(loop != NULL);
12478 SgInitializedName* ivarname=NULL;
12479
12480 // Fortran case ------------------
12481 if (SgFortranDo * do_loop = isSgFortranDo(loop))
12482 {
12483 SgAssignOp* assign_op = isSgAssignOp (do_loop->get_initialization());
12484 ROSE_ASSERT (assign_op != NULL);
12485 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12486 ROSE_ASSERT (var != NULL);
12487 ivarname = var->get_symbol()->get_declaration();
12488 ROSE_ASSERT (ivarname != NULL);
12489 return ivarname;
12490 }
12491 // C/C++ case ------------------------------
12492 SgForStatement* fs = isSgForStatement(loop);
12493 if (fs == NULL)
12494 {
12495 return NULL;
12496 }
12497 // we only handle C/C++ for loops and Fortran Do loops.
12498 // Any other kinds of loops (while, do-while,etc.) are skipped and return NULL;
12499 // ROSE_ASSERT (fs != NULL);
12500
12501 //Check initialization statement is something like i=xx;
12502 SgStatementPtrList & init = fs->get_init_stmt();
12503 if (init.size() !=1)
12504 {
12505 cerr<<"SageInterface::getLoopIndexVariable(), no or more than one initialization statements are encountered. Not supported yet "<<endl;
12506 //ROSE_ASSERT(false);
12507 return NULL;
12508 }
12509 SgStatement* init1 = init.front();
12510 SgExpression* ivarast=NULL;
12511
12512 // DQ (3/20/2016): Note that GNU compiler reports these variables are set but not used.
12513 //bool isCase1=false, isCase2=false;
12514
12515 //consider C99 style: for (int i=0;...)
12516 if (isSgVariableDeclaration(init1))
12517 {
12518 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12519 ivarname = decl->get_variables().front();
12520 ROSE_ASSERT(ivarname != NULL);
12521 //SgInitializer * initor = ivarname->get_initializer();
12522 // if (isSgAssignInitializer(initor))
12523 // isCase1 = true;
12524 }// other regular case: for (i=0;..)
12525 else if (isAssignmentStatement(init1, &ivarast))
12526 {
12527 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12528 if (var)
12529 {
12530 ivarname = var->get_symbol()->get_declaration();
12531 //isCase2 = true;
12532 }
12533 }
12534 else if (SgExprStatement* exp_stmt = isSgExprStatement(init1))
12535 { //case like: for (i = 1, len1 = 0, len2=0; i <= n; i++)
12536 // AST is: SgCommaOpExp -> SgAssignOp -> SgVarRefExp
12537 if (SgCommaOpExp* comma_exp = isSgCommaOpExp(exp_stmt->get_expression()))
12538 {
12539 SgCommaOpExp* leaf_exp = comma_exp;
12540 while (isSgCommaOpExp(leaf_exp->get_lhs_operand()))
12541 leaf_exp = isSgCommaOpExp(leaf_exp->get_lhs_operand());
12542 if (SgAssignOp* assign_op = isSgAssignOp(leaf_exp->get_lhs_operand()))
12543 {
12544 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12545 if (var)
12546 {
12547 ivarname = var->get_symbol()->get_declaration();
12548 }
12549 }
12550 }
12551 }
12552 else
12553 {
12554
12555 mlog[Sawyer::Message::Common::WARN] <<"Warning: SageInterface::getLoopIndexVariable(). Unhandled init_stmt type of SgForStatement"<<endl;
12556 mlog[Sawyer::Message::Common::WARN] <<"Init statement is :"<<init1->class_name() <<" " <<init1->unparseToString()<<endl;
12557 init1->get_file_info()->display("Debug");
12558
12559 return NULL;
12560 //ROSE_ASSERT (false);
12561 }
12562 // Cannot be both true
12563 // ROSE_ASSERT(!(isCase1&&isCase2));
12564
12565 //Check loop index's type
12566 //ROSE_ASSERT(isStrictIntegerType(ivarname->get_type()));
12567 return ivarname;
12568}
12569
12573{
12574 ROSE_ASSERT (ivar != NULL);
12575 ROSE_ASSERT (subtree_root != NULL);
12576 bool result = false;
12577 SgScopeStatement * cur_loop = findEnclosingLoop (getEnclosingStatement(subtree_root));
12578 while (cur_loop)
12579 {
12580 SgInitializedName * i_index = getLoopIndexVariable (cur_loop);
12581 if (i_index == ivar)
12582 {
12583 result = true;
12584 break;
12585 }
12586 else
12587 { // findEnclosingLoop() is inclusive.
12588 cur_loop = findEnclosingLoop (getEnclosingStatement(cur_loop->get_parent()));
12589 }
12590 }
12591 return result;
12592}
12593
12595
12600{
12601 ROSE_ASSERT (loop !=NULL);
12602 SgStatementPtrList& stmt_list = loop->get_init_stmt();
12603 if (stmt_list.size() >1) return true; // two var decl statements
12604 if (stmt_list.size() == 0) return false;
12605
12606// generateDOTforMultipleFile(*getProject());
12607 //single variable declaration statement, like int i;
12608 SgVariableDeclaration* decl_stmt = isSgVariableDeclaration(stmt_list[0]);
12609 if (decl_stmt != NULL)
12610 return false;
12611
12612 // single statement, but with comma expression (i=0, j=0)
12613 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
12614 ROSE_ASSERT (exp_stmt != NULL);
12615 if (isSgCommaOpExp (exp_stmt->get_expression()) )
12616 {
12617 return true;
12618 }
12619
12620 return false;
12621}
12623bool 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*/)
12624{
12625 ROSE_ASSERT(loop != NULL);
12626 SgFortranDo* fs = isSgFortranDo(loop);
12627 if (fs == NULL)
12628 return false;
12629 // 1. Check initialization statement is something like i=xx;
12630 SgExpression * init = fs->get_initialization();
12631 if (init == NULL)
12632 return false;
12633 SgAssignOp* init_assign = isSgAssignOp (init);
12634 SgExpression *lbast=NULL, *ubast=NULL;
12635 // SgExpression* ivarast=NULL, *stepast=NULL;
12636 SgInitializedName* ivarname=NULL;
12637
12638 bool isCase1=false;
12639 if (init_assign)
12640 {
12641 SgVarRefExp* var = isSgVarRefExp(init_assign->get_lhs_operand());
12642 if (var)
12643 ivarname = var->get_symbol()->get_declaration();
12644 lbast = init_assign->get_rhs_operand();
12645 if (ivarname && lbast )
12646 isCase1 = true;
12647 }
12648 // if not i=1
12649 if (!isCase1)
12650 return false;
12651
12652 //Check loop index's type
12653 if (!SageInterface::isStrictIntegerType(ivarname->get_type()))
12654 return false;
12655#if 0
12656 //2. Check test expression i [<=, >=, <, > ,!=] bound
12657 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12658 if (test == NULL)
12659 return false;
12660 switch (test->variantT()) {
12661 case V_SgLessOrEqualOp:
12662 if (isInclusiveUpperBound != NULL)
12663 *isInclusiveUpperBound = true;
12664 if (hasIncrementalIterationSpace != NULL)
12665 *hasIncrementalIterationSpace = true;
12666 break;
12667 case V_SgLessThanOp:
12668 if (isInclusiveUpperBound != NULL)
12669 *isInclusiveUpperBound = false;
12670 if (hasIncrementalIterationSpace != NULL)
12671 *hasIncrementalIterationSpace = true;
12672 break;
12673 case V_SgGreaterOrEqualOp:
12674 if (isInclusiveUpperBound != NULL)
12675 *isInclusiveUpperBound = true;
12676 if (hasIncrementalIterationSpace != NULL)
12677 *hasIncrementalIterationSpace = false;
12678 break;
12679 case V_SgGreaterThanOp:
12680 if (isInclusiveUpperBound != NULL)
12681 *isInclusiveUpperBound = false;
12682 if (hasIncrementalIterationSpace != NULL)
12683 *hasIncrementalIterationSpace = false;
12684 break;
12685// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12686 break;
12687 default:
12688 return false;
12689 }
12690 // check the tested variable is the same as the loop index
12691 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12692 if (testvar == NULL)
12693 return false;
12694 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12695 return false;
12696#endif
12697 //grab the upper bound
12698 ubast = loop->get_bound();
12699 // Fortran Do loops always have inclusive upper bound
12700 if (isInclusiveUpperBound != NULL)
12701 *isInclusiveUpperBound = true;
12702 //3. Check the increment expression
12703 SgExpression* incr = fs->get_increment();
12704 ROSE_ASSERT (incr != NULL);
12705 if (isSgNullExpression(incr))
12706 {
12707 cerr<<"Error:isCanonicalDoLoop() found NULL increment expression. Please call doLoopNormalization() first!"<<endl;
12708 ROSE_ASSERT (false);
12709 }
12710 if (hasIncrementalIterationSpace != NULL)
12711 {
12712 *hasIncrementalIterationSpace = true;
12713 // We can only tell a few cases
12714 if (SgIntVal* i_v = isSgIntVal(incr))
12715 {
12716 if (i_v->get_value()<0)
12717 *hasIncrementalIterationSpace = false;
12718 }
12719 }
12720#if 0
12721 SgVarRefExp* incr_var = NULL;
12722 switch (incr->variantT()) {
12723 case V_SgPlusAssignOp: //+=
12724 case V_SgMinusAssignOp://-=
12725 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12726 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12727 break;
12728 case V_SgPlusPlusOp: //++
12729 case V_SgMinusMinusOp: //--
12730 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12731 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12732 break;
12733 default:
12734 return false;
12735 }
12736 if (incr_var == NULL)
12737 return false;
12738 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12739 return false;
12740#endif
12741 // return loop information if requested
12742 if (ivar != NULL)
12743 *ivar = ivarname;
12744 if (lb != NULL)
12745 *lb = lbast;
12746 if (ub != NULL)
12747 *ub = ubast;
12748 if (step != NULL)
12749 *step = incr;
12750 if (body != NULL) {
12751 *body = fs->get_body();
12752 }
12753 return true;
12754}
12755//TODO: expose it to the namespace once it matures.
12757// with a single entry at the top and a single exit at the bottom, or an OpenMP construct.
12758/*
12759From OpenMP 4.5 Specification
12760
127611.2.2 OpenMP Language Terminology
12762
12763For C/C++, an executable statement, possibly compound, with a single entry at the
12764top and a single exit at the bottom, or an OpenMP construct.
12765
12766For Fortran, a block of executable statements with a single entry at the top and a
12767single exit at the bottom, or an OpenMP construct.
12768
12769COMMENTS:
12770
12771For all base languages:
12772* Access to the structured block must not be the result of a branch; and
12773* The point of exit cannot be a branch out of the structured block.
12774
12775 For C/C++:
12776* The point of entry must not be a call to setjmp();
12777* longjmp() and throw() must not violate the entry/exit criteria;
12778* Calls to exit() are allowed in a structured block; and
12779* 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.
12780
12781For Fortran:
12782* STOP statements are allowed in a structured block.
12783
12784*/
12785bool isStructuredBlock(SgStatement* s)
12786{
12787 bool rt = true;
12788 ROSE_ASSERT (s != NULL);
12789
12790 // contain break;
12791 std::set<SgNode*> bset = SgNodeHelper::loopRelevantBreakStmtNodes (s);
12792 if (bset.size()!=0 )
12793 rt = false;
12794 //TODO: contain goto statement, jumping to outside targets
12795 // longjump(), throw(),
12796 // calls to exit() are allowed.
12797
12798 return rt;
12799
12800}
12801
12803//TODO check the loop index is not being written in the loop body
12804bool 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*/)
12805{
12806 ROSE_ASSERT(loop != NULL);
12807 SgForStatement* fs = isSgForStatement(loop);
12808 //SgFortranDo* fs2 = isSgFortranDo(loop);
12809 if (fs == NULL)
12810 {
12811 // if (fs2)
12812 // return isCanonicalDoLoop (fs2, ivar, lb, ub, step, body, hasIncrementalIterationSpace, isInclusiveUpperBound);
12813 // else
12814 return false;
12815 }
12816 // 1. Check initialization statement is something like i=xx;
12817 SgStatementPtrList & init = fs->get_init_stmt();
12818 if (init.size() !=1)
12819 return false;
12820 SgStatement* init1 = init.front();
12821 SgExpression* ivarast=NULL, *lbast=NULL, *ubast=NULL, *stepast=NULL;
12822 SgInitializedName* ivarname=NULL;
12823
12824 bool isCase1=false, isCase2=false;
12825 //consider C99 style: for (int i=0;...)
12826 if (isSgVariableDeclaration(init1))
12827 {
12828 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12829 ivarname = decl->get_variables().front();
12830 ROSE_ASSERT(ivarname != NULL);
12831 SgInitializer * initor = ivarname->get_initializer();
12832 if (isSgAssignInitializer(initor))
12833 {
12834 lbast = isSgAssignInitializer(initor)->get_operand();
12835 isCase1 = true;
12836 }
12837 }// other regular case: for (i=0;..)
12838 else if (isAssignmentStatement(init1, &ivarast, &lbast))
12839 {
12840 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12841 if (var)
12842 {
12843 ivarname = var->get_symbol()->get_declaration();
12844 isCase2 = true;
12845 }
12846 }
12847 // Cannot be both true
12848 ROSE_ASSERT(!(isCase1&&isCase2));
12849 // if not either case is true
12850 if (!(isCase1||isCase2))
12851 return false;
12852
12853 //Check loop index's type
12854 if (!isStrictIntegerType(ivarname->get_type()))
12855 return false;
12856
12857 //2. Check test expression i [<=, >=, <, > ,!=] bound
12858 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12859 if (test == NULL)
12860 return false;
12861 switch (test->variantT()) {
12862 case V_SgLessOrEqualOp:
12863 if (isInclusiveUpperBound != NULL)
12864 *isInclusiveUpperBound = true;
12865 if (hasIncrementalIterationSpace != NULL)
12866 *hasIncrementalIterationSpace = true;
12867 break;
12868 case V_SgLessThanOp:
12869 if (isInclusiveUpperBound != NULL)
12870 *isInclusiveUpperBound = false;
12871 if (hasIncrementalIterationSpace != NULL)
12872 *hasIncrementalIterationSpace = true;
12873 break;
12874 case V_SgGreaterOrEqualOp:
12875 if (isInclusiveUpperBound != NULL)
12876 *isInclusiveUpperBound = true;
12877 if (hasIncrementalIterationSpace != NULL)
12878 *hasIncrementalIterationSpace = false;
12879 break;
12880 case V_SgGreaterThanOp:
12881 if (isInclusiveUpperBound != NULL)
12882 *isInclusiveUpperBound = false;
12883 if (hasIncrementalIterationSpace != NULL)
12884 *hasIncrementalIterationSpace = false;
12885 break;
12886// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12887 break;
12888 default:
12889 return false;
12890 }
12891 // check the tested variable is the same as the loop index
12892 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12893 if (testvar == NULL)
12894 return false;
12895 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12896 return false;
12897 //grab the upper bound
12898 ubast = test->get_rhs_operand();
12899
12900 //3. Check the increment expression
12901 /* Allowed forms
12902 ++var
12903 var++
12904 --var
12905 var--
12906
12907 var += incr
12908 var -= incr
12909
12910 var = var + incr
12911 var = incr + var
12912 var = var - incr
12913 */
12914 SgExpression* incr = fs->get_increment();
12915 SgVarRefExp* incr_var = NULL;
12916 switch (incr->variantT()) {
12917 case V_SgPlusAssignOp: //+=
12918 case V_SgMinusAssignOp://-=
12919 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12920 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12921 break;
12922 case V_SgPlusPlusOp: //++
12923 case V_SgMinusMinusOp: //--
12924 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12925 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12926 break;
12927 case V_SgAssignOp: { // cases : var + incr, var - incr, incr + var (not allowed: incr-var)
12928 incr_var=isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12929 if(incr_var == NULL)
12930 return false;
12931 SgAddOp* addOp=isSgAddOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
12932 SgSubtractOp* subtractOp=isSgSubtractOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
12933 SgBinaryOp* arithOp=0;
12934 if(addOp)
12935 arithOp=addOp;
12936 else if(subtractOp)
12937 arithOp=subtractOp;
12938 else
12939 return false;
12940 ROSE_ASSERT(arithOp!=0);
12941 if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_lhs_operand()))) {
12942 // cases : var + incr, var - incr
12943 incr_var=varRefExp;
12944 stepast=isSgBinaryOp(arithOp)->get_rhs_operand();
12945 } else if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_rhs_operand()))) {
12946 if(isSgAddOp(arithOp)) {
12947 // case : incr + var (not allowed: incr-var)
12948 incr_var=varRefExp;
12949 stepast=isSgBinaryOp(arithOp)->get_lhs_operand();
12950 }
12951 }
12952 break;
12953 } // end of V_AssignOp
12954 default:
12955 return false;
12956 }
12957
12958 if (incr_var == NULL)
12959 return false;
12960 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12961 return false;
12962
12963
12964 // single entry and single exit?
12965 // only for C for loop for now
12966 // TODO: Fortran support later
12967 if (fs && !isStructuredBlock(fs->get_loop_body()) )
12968 return false;
12969
12970 // return loop information if requested
12971 if (ivar != NULL)
12972 *ivar = ivarname;
12973 if (lb != NULL)
12974 *lb = lbast;
12975 if (ub != NULL)
12976 *ub = ubast;
12977 if (step != NULL)
12978 *step = stepast;
12979 if (body != NULL) {
12980 *body = fs->get_loop_body();
12981 }
12982 return true;
12983}
12984
12987{
12988 ROSE_ASSERT(loop != NULL);
12989 ROSE_ASSERT(lb != NULL);
12990 SgForStatement* forstmt = isSgForStatement(loop);
12991 SgFortranDo* dostmt = isSgFortranDo(loop);
12992 // ROSE_ASSERT(forstmt!= NULL);
12993
12994 if (forstmt != NULL)
12995 {
12996 // two cases: init_stmt is
12997 // SgExprStatement (assignment) like i=0;
12998 // SgVariableDeclaration int i =0 or
12999 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignOp);
13000 if (testList.size()>0) // assignment statement
13001 {
13002 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13003 SgAssignOp * assignop = isSgAssignOp((*testList.begin()));
13004 ROSE_ASSERT(assignop);
13005 if( assignop->get_rhs_operand()->get_lvalue())
13006 lb->set_lvalue(true);
13007 assignop->set_rhs_operand(lb);
13008 lb->set_parent(assignop);
13009 //TODO what happens to the original rhs operand?
13010 }
13011 else // variable declaration case
13012 {
13013 // SgVariableDeclaration
13014 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignInitializer );
13015 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13016 SgAssignInitializer* init = isSgAssignInitializer((*testList.begin()));
13017 ROSE_ASSERT(init != NULL);
13018 init->set_operand(lb);
13019 lb->set_parent(init);
13020 //TODO what happens to the original rhs operand?
13021 }
13022 }
13023 else if (dostmt != NULL)
13024 {
13025 SgExpression* init = dostmt->get_initialization();
13026 ROSE_ASSERT (init != NULL);
13027 SgAssignOp * a_op = isSgAssignOp (init);
13028 ROSE_ASSERT (a_op!=NULL);
13029 a_op->set_rhs_operand(lb);
13030 lb->set_parent(a_op);
13031 //TODO delete the previous operand?
13032 }
13033 else
13034 {
13035 cerr<<"Error. SageInterface::setLoopLowerBound(), illegal loop type:"<< loop->class_name()<<endl;
13036 ROSE_ASSERT (false);
13037 }
13038}
13039
13042{
13043 ROSE_ASSERT(loop != NULL);
13044 ROSE_ASSERT(ub != NULL);
13045 SgForStatement* forstmt = isSgForStatement(loop);
13046 // ROSE_ASSERT(forstmt!= NULL);
13047 SgFortranDo* dostmt = isSgFortranDo(loop);
13048 if (forstmt != NULL)
13049 {
13050 // set upper bound expression
13051 SgBinaryOp * binop= isSgBinaryOp(isSgExprStatement(forstmt->get_test())->get_expression());
13052 ROSE_ASSERT(binop != NULL);
13053 binop->set_rhs_operand(ub);
13054 ub->set_parent(binop);
13055 }
13056 else if (dostmt != NULL)
13057 {
13058 dostmt->set_bound(ub);
13059 ub->set_parent(dostmt);
13060 //TODO delete the original bound expression
13061 }
13062 else
13063 {
13064 cerr<<"Error. SageInterface::setLoopUpperBound(), illegal loop type:"<< loop->class_name()<<endl;
13065 ROSE_ASSERT (false);
13066 }
13067
13068}
13069
13072{
13073 ROSE_ASSERT(loop != NULL);
13074 ROSE_ASSERT(stride != NULL);
13075 SgForStatement* forstmt = isSgForStatement(loop);
13076 SgFortranDo * dostmt = isSgFortranDo (loop);
13077 // ROSE_ASSERT(forstmt!= NULL);
13078 if (dostmt != NULL)
13079 {
13080 dostmt->set_increment(stride);
13081 stride->set_parent(dostmt);
13082 //TODO delete original increment expression
13083 }
13084 else if (forstmt != NULL)
13085 {
13086 // set stride expression
13087 // case 1: i++ change to i+=stride
13088 Rose_STL_Container<SgNode*> testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusPlusOp);
13089 if (testList.size()>0)
13090 {
13091 ROSE_ASSERT(testList.size() == 1); // should have only one
13092 SgVarRefExp *loopvarexp = isSgVarRefExp(SageInterface::deepCopy
13093 (isSgPlusPlusOp( *testList.begin())->get_operand()));
13094 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13095 forstmt->set_increment(plusassignop);
13096 }
13097
13098 // case 1.5: i-- also changed to i+=stride
13099 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusMinusOp);
13100 if (testList.size()>0)
13101 {
13102 ROSE_ASSERT(testList.size()==1);// should have only one
13103 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13104 (isSgMinusMinusOp(*testList.begin())->get_operand()));
13105 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13106 forstmt->set_increment(plusassignop);
13107 }
13108
13109 // case 2: i+=X
13110 testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusAssignOp);
13111 if (testList.size()>0)
13112 {
13113 ROSE_ASSERT(testList.size()==1);// should have only one
13114 SgPlusAssignOp * assignop = isSgPlusAssignOp(*(testList.begin()));
13115 ROSE_ASSERT(assignop!=NULL);
13116 assignop->set_rhs_operand(stride);
13117 }
13118
13119 // case 2.5: i-=X changed to i+=stride
13120 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusAssignOp);
13121 if (testList.size()>0)
13122 {
13123 ROSE_ASSERT(testList.size()==1);// should have only one
13124 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13125 (isSgMinusAssignOp(*testList.begin())->get_lhs_operand()));
13126 SgExprStatement* exprstmt = isSgExprStatement((*testList.begin())->get_parent());
13127 ROSE_ASSERT(exprstmt !=NULL);
13128 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13129 exprstmt->set_expression(plusassignop);
13130 }
13131
13132#if 0 // [Robb Matzke 2021-03-17]
13133 // DQ (1/3/2007): I think this is a meaningless statement.
13134 testList.empty();
13135#endif
13136 // case 3: i=i + X or i =X +i i
13137 // TODO; what if users use i*=,etc ??
13138 // send out a warning: not canonical FOR/DO loop
13139 // or do this in the real frontend. MUST conform to canonical form
13140 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgAddOp);
13141 if (testList.size()>0)
13142 {
13143 ROSE_ASSERT(testList.size()==1);// should have only one ??
13144 // consider only the top first one
13145 SgAddOp * addop = isSgAddOp(*(testList.begin()));
13146 ROSE_ASSERT(addop!=NULL);
13147 string loopvar= (isSgVarRefExp(isSgAssignOp(addop->get_parent())->get_lhs_operand())->get_symbol()->get_name()).getString();
13148 if (isSgVarRefExp(addop->get_rhs_operand())!=NULL)
13149 {
13150 if ((isSgVarRefExp(addop->get_rhs_operand())->get_symbol()->get_name()).getString() ==loopvar)
13151 addop->set_lhs_operand(stride);
13152 else
13153 addop->set_rhs_operand(stride);
13154 }
13155 else
13156 addop->set_rhs_operand(stride);
13157 }
13158
13159 // case 3.5: i=i - X
13160 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgSubtractOp);
13161 if (testList.size()>0)
13162 {
13163 ROSE_ASSERT(testList.size()==1);// should have only one ??
13164 // consider only the top first one
13165 SgSubtractOp * subtractop = isSgSubtractOp(*(testList.begin()));
13166 ROSE_ASSERT(subtractop!=NULL);
13167 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13168 (isSgSubtractOp(*testList.begin())->get_lhs_operand()));
13169 SgAssignOp *assignop = isSgAssignOp((*testList.begin())->get_parent());
13170 ROSE_ASSERT(assignop !=NULL);
13171 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13172 assignop->set_rhs_operand(plusassignop);
13173 }
13174 }
13175 else
13176 {
13177 cerr<<"Error. SageInterface::setLoopStride(), illegal loop type:"<< loop->class_name()<<endl;
13178 ROSE_ASSERT (false);
13179
13180 }
13181}
13182
13186bool SageInterface::isAssignmentStatement(SgNode* s, SgExpression** lhs/*=NULL*/, SgExpression** rhs/*=NULL*/, bool* readlhs/*=NULL*/)
13187{
13188 SgExprStatement *n = isSgExprStatement(s);
13189 SgExpression *exp = (n != 0)? n->get_expression() : isSgExpression(s);
13190 if (exp != 0) {
13191 switch (exp->variantT()) {
13192 case V_SgPlusAssignOp:
13193 case V_SgMinusAssignOp:
13194 case V_SgAndAssignOp:
13195 case V_SgIorAssignOp:
13196 case V_SgMultAssignOp:
13197 case V_SgDivAssignOp:
13198 case V_SgModAssignOp:
13199 case V_SgXorAssignOp:
13200 case V_SgAssignOp:
13201 {
13202 SgBinaryOp* s2 = isSgBinaryOp(exp);
13203 if (lhs != 0)
13204 *lhs = s2->get_lhs_operand();
13205 if (rhs != 0) {
13206 SgExpression* init = s2->get_rhs_operand();
13207 if ( init->variantT() == V_SgAssignInitializer)
13208 init = isSgAssignInitializer(init)->get_operand();
13209 *rhs = init;
13210 }
13211 if (readlhs != 0)
13212 *readlhs = (exp->variantT() != V_SgAssignOp);
13213 return true;
13214 }
13215 default:
13216 return false;
13217 }
13218 }
13219 return false;
13220}
13221
13222
13223void
13225 {
13226 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,V_SgGotoStatement);
13227 for (size_t i = 0; i < gotos.size(); ++i)
13228 {
13229 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13230 SgLabelStatement* ls = gs->get_label();
13231 SgBasicBlock* lsParent = isSgBasicBlock(ls->get_parent());
13232 if (!lsParent) continue;
13233 SgStatementPtrList& bbStatements = lsParent->get_statements();
13234
13235 size_t j = std::find(bbStatements.begin(), bbStatements.end(), ls) - bbStatements.begin();
13236
13237 ROSE_ASSERT (j != bbStatements.size());
13238
13239 while (j < bbStatements.size() - 1 && isSgLabelStatement(bbStatements[j + 1]))
13240 {
13241 ++j;
13242 }
13243 gs->set_label(isSgLabelStatement(bbStatements[j]));
13244 }
13245 }
13246
13247bool SageInterface::mergeDeclarationAndAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt, bool removeAssignStmt /*= true*/)
13248{
13249 return mergeAssignmentWithDeclaration (assign_stmt, decl, removeAssignStmt);
13250}
13252
13256bool SageInterface::mergeAssignmentWithDeclaration(SgExprStatement* assign_stmt, SgVariableDeclaration* decl, bool removeAssignStmt /*= true*/)
13257{
13258 bool rt= true;
13259 ROSE_ASSERT(decl != NULL);
13260 ROSE_ASSERT(assign_stmt != NULL);
13261
13262 // Sanity check of assign statement: must be a form of var = xxx;
13263 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13264 if (assign_op == NULL)
13265 return false;
13266 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13267 if (assign_op_var == NULL) return false;
13268
13269 // Sanity check of the variable declaration: it should not have an existing initializer
13271 if (decl_var->get_initptr()!= NULL ) return false;
13272
13273 // check if two variables match
13274 // In translation, it is possible the declaration has not yet been inserted into its scope.
13275 // finding its symbol can return NULL.
13276 // But we still want to do the merge.
13277 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13278 if (decl_var_symbol!=NULL)
13279 {
13280 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13281 if (assign_op_var->get_symbol() != decl_var_symbol) return false;
13282 }
13283 else
13284 { // fallback to comparing variable names instead
13285 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13286 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name()) return false;
13287 }
13288
13289 // Everything looks fine now. Do the merge.
13291
13292 // Must preserve the proprecessing information of the original assign_stmt
13293 // use appending (not prepending) so the order of decl's comments and assign_stmt's comments can be preserved
13294 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13295
13296 // removeStatement() does not support removing a statement which is not inside a container.
13297 // But sometimes we do need to remove such a statement and replace it with a new one.
13298 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13299 // TODO: improve removeStatement() which uses low level rewritting.
13300 if (removeAssignStmt)
13301 SageInterface::removeStatement (assign_stmt);
13302// SageInterface::deepDelete (assign_stmt);
13304 decl_var->set_initptr(initor);
13305 initor->set_parent(decl_var);
13306
13307 return rt;
13308}
13309
13311{
13312 bool rt= true;
13313
13314 // Sanity check of assign statement: must be a form of var = xxx;
13315 ROSE_ASSERT(assign_stmt != NULL);
13316 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13317 if (assign_op == NULL)
13318 return false;
13319 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13320 if (assign_op_var == NULL)
13321 return false;
13322
13323 // Sanity check of the variable declaration: it should not have an existing initializer
13324 ROSE_ASSERT(decl != NULL);
13326 if (decl_var->get_initptr()!= NULL)
13327 return false;
13328
13329 // check if two variables match
13330 // In translation, it is possible the declaration has not yet been inserted into its scope.
13331 // finding its symbol can return NULL.
13332 // But we still want to do the merge.
13333 ROSE_ASSERT(decl_var != NULL);
13334 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13335 if (decl_var_symbol != NULL) {
13336 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13337 if (assign_op_var->get_symbol() != decl_var_symbol)
13338 return false;
13339 }
13340 else
13341 { // fallback to comparing variable names instead
13342 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13343 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name())
13344 return false;
13345 }
13346
13347 // Everything looks fine now. Do the merge.
13348 // It is implemented by
13349 // 1. copy rhs to the decl's rhs,
13350 // 2. then move the decl to the place of the assignment,
13351 // 3. then remove the assignment
13352 //
13353 // Copy rhs to be initializer
13356 decl_var->set_initptr(initor);
13357 initor->set_parent(decl_var);
13358
13359 // move proprocessing info. attached before decl to its next statement's front, using prepending to preserve the original order
13360 SgStatement* next_stmt = SageInterface::getNextStatement (decl);
13361 SageInterface::movePreprocessingInfo(decl, next_stmt, PreprocessingInfo::before, PreprocessingInfo::before, true);
13362
13363 // removeStatement() does not support removing a statement which is not inside a container.
13364 // But sometimes we do need to remove such a statement and replace it with a new one.
13365 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13366 // TODO: improve removeStatement() which uses low level rewritting.
13367
13368 // Now move the declaration to a new position, right before the assignment statement
13370 SageInterface::insertStatementBefore(assign_stmt, decl, false);
13371
13372 // preserve preprocessing info. attached to assign_stmt before removing it , using append (last false)
13373 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13374
13375 // Original assignment statement should be removed
13376 SageInterface::removeStatement (assign_stmt);
13377 // SageInterface::deepDelete (decl);
13378
13379 return rt;
13380}
13381// Split a variable declaration with an rhs assignment into two statements: a declaration and an assignment.
13382// Return the generated assignment statement, if any
13384{
13385 SgExprStatement* rt = NULL;
13386 ROSE_ASSERT (decl != NULL);
13387
13389 SgInitializer* initor = decl_var ->get_initptr();
13390 if (initor == NULL)
13391 rt = NULL;
13392 else
13393 {
13394 // Liao, 2021/10/21, we have to support all sorts of initializers, including aggregate initializer
13395 SgExpression * rhs=NULL;
13396 if (SgAssignInitializer * ainitor = isSgAssignInitializer (initor))
13397 rhs = ainitor->get_operand();
13398 else
13399 rhs = initor;
13400
13401 // we deep copy the rhs operand
13402 rt = buildAssignStatement (buildVarRefExp(decl_var) , deepCopy(rhs));
13403 decl_var->set_initptr(NULL);
13404 //TODO clean up initor
13405 insertStatementAfter ( decl, rt );
13406 }
13407 return rt;
13408}
13410ROSE_DLL_API int SageInterface::splitVariableDeclaration (SgScopeStatement* scope, bool topLevelOnly /* = true */)
13411{
13412 int count = 0;
13413 if (!topLevelOnly)
13414 {
13415 cerr<<"SageInterface::splitVariableDeclaration() topLevelOnly == false is not yet implemented."<<endl;
13416 ROSE_ASSERT (false);
13417 }
13418
13419 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVariableDeclaration);
13420 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13421 {
13422 SgVariableDeclaration *decl= isSgVariableDeclaration(*i);
13423 if (topLevelOnly)
13424 {
13425 ROSE_ASSERT(decl != NULL);
13426 if (decl->get_scope() == scope)
13427 {
13429 count ++;
13430 }
13431 }
13432 }
13433 return count;
13434}
13435
13436void SageInterface::collectVarRefs(SgLocatedNode* root, std::vector<SgVarRefExp* > & result)
13437{
13438 ROSE_ASSERT (root != NULL);
13439// std::vector<SgVarRefExp* > result;
13440
13441 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgVarRefExp);
13442 // AST query won't find variables used in types
13444
13445 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13446 {
13447 SgVarRefExp *vRef = isSgVarRefExp(*i);
13448 ROSE_ASSERT (vRef != NULL);
13449 result.push_back(vRef);
13450 }
13451}
13452
13453int SageInterface::collectVariableReferencesInArrayTypes(SgLocatedNode* root, Rose_STL_Container<SgNode*> & currentVarRefList)
13454{
13455 int rt = 0;
13456 ROSE_ASSERT (root != NULL);
13457 Rose_STL_Container<SgNode*> constructorList= NodeQuery::querySubTree(root, V_SgConstructorInitializer);
13458 for (size_t i =0; i< constructorList.size(); i++)
13459 {
13460 SgConstructorInitializer * c_init = isSgConstructorInitializer (constructorList[i]);
13461 if (SgArrayType* a_type = isSgArrayType(c_init->get_expression_type()))
13462 {
13463 Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree (a_type->get_index(),V_SgVarRefExp);
13464 for (size_t j =0 ; j< varList.size(); j++)
13465 {
13466 SgVarRefExp* var_exp = isSgVarRefExp(varList[j]) ;
13467 currentVarRefList.push_back(var_exp);
13468//TODO: these variable references do have special scopes, how to communicate to users?
13469// specialVarRefScopeExp[var_exp] = c_init ;
13470 rt ++;
13471 }
13472 }
13473 }
13474 return rt;
13475}
13476
13477namespace SageInterface { // A few internal helper classes
13478
13480 {
13481 SgAndOp* op;
13482
13483 public:
13484 AndOpGenerator(SgAndOp* op): op(op) {}
13485
13486 virtual SgStatement* generate(SgExpression* lhs)
13487 {
13488 if (lhs==NULL)
13489 return NULL;
13490 SgTreeCopy treeCopy;
13491 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13492 ROSE_ASSERT (lhsCopy);
13493 SgIfStmt* tree =
13500 return tree;
13501 }
13502 };
13503
13505 {
13506 SgOrOp* op;
13507
13508 public:
13509 OrOpGenerator(SgOrOp* op): op(op) {}
13510
13511 virtual SgStatement* generate(SgExpression* lhs)
13512 {
13513 if (lhs==NULL)
13514 return NULL;
13515 SgTreeCopy treeCopy;
13516 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13517 ROSE_ASSERT (lhsCopy);
13518 SgIfStmt* tree =
13525 return tree;
13526 }
13527 };
13528
13530 {
13531 SgConditionalExp* op;
13532
13533 public:
13535
13536 virtual SgStatement* generate(SgExpression* lhs)
13537 {
13538 if (lhs==NULL)
13539 return NULL;
13540 SgTreeCopy treeCopy;
13541 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13542 ROSE_ASSERT (lhsCopy);
13543 SgIfStmt* tree =
13550 return tree;
13551 }
13552 };
13553
13554} // end of namespace for the helper classes
13555
13558{
13559 ROSE_ASSERT(from != NULL);
13560
13561#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
13562#if 0 // This is not accurate for template class specializations. We disable this assertion for now. The worst case is compilation error later.
13564 std::cerr << "Type " << from->get_type()->unparseToString() << " of expression " << from->unparseToString() << " is not copy constructible" << std::endl;
13565 ROSE_ASSERT (false);
13566 }
13567
13568 assert (SageInterface::isCopyConstructible(from->get_type())); // How do we report errors?
13569#endif
13570 SgStatement* stmt = getStatementOfExpression(from);
13571 assert (stmt);
13572 if (!isSgForInitStatement(stmt->get_parent())) {
13573 //SageInterface::ensureBasicBlockAsParent(stmt);
13574 // no return value is accepted. Only the optional transformation matters
13575 if (isBodyStatement(stmt) && !isSgBasicBlock(stmt))
13577 }
13578
13579 SgScopeStatement* parent = isSgScopeStatement(stmt->get_parent());
13580 // cout << "parent is a " << (parent ? parent->sage_class_name() : "NULL") << endl;
13581 if (!parent && isSgForInitStatement(stmt->get_parent()))
13582 parent = isSgScopeStatement(stmt->get_parent()->get_parent()->get_parent());
13583 assert (parent);
13584 // cout << "parent is a " << parent->sage_class_name() << endl;
13585 // cout << "parent is " << parent->unparseToString() << endl;
13586 // cout << "stmt is " << stmt->unparseToString() << endl;
13587 SgName varname = "rose_temp__";
13588 if (newName == "") {
13589 varname << ++SageInterface::gensym_counter;
13590 } else {
13591 varname = newName;
13592 }
13593
13594 SgType* vartype = from->get_type();
13595 SgNode* fromparent = from->get_parent();
13596 vector<SgExpression*> ancestors;
13597 for (SgExpression *expr = from, *anc = isSgExpression(fromparent); anc != 0;
13598 expr = anc, anc = isSgExpression(anc->get_parent()))
13599 {
13600 if ((isSgAndOp(anc) && expr != isSgAndOp(anc)->get_lhs_operand()) ||
13601 (isSgOrOp(anc) && expr != isSgOrOp(anc)->get_lhs_operand()) ||
13602 (isSgConditionalExp(anc) && expr != isSgConditionalExp(anc)->get_conditional_exp()))
13603 ancestors.push_back(anc); // Closest first
13604 }
13605 // cout << "This expression to split has " << ancestors.size() << " ancestor(s)" << endl;
13606 for (vector<SgExpression*>::reverse_iterator ai = ancestors.rbegin(); ai != ancestors.rend(); ++ai)
13607 {
13608 StatementGenerator* gen;
13609 switch ((*ai)->variantT()) {
13610 case V_SgAndOp:
13611 gen = new AndOpGenerator(isSgAndOp(*ai)); break;
13612 case V_SgOrOp:
13613 gen = new OrOpGenerator(isSgOrOp(*ai)); break;
13614 case V_SgConditionalExp:
13615 gen = new ConditionalExpGenerator(isSgConditionalExp(*ai)); break;
13616 default: assert (!"Should not happen"); abort();
13617 }
13619 delete gen;
13620 } // for
13621 if (ancestors.size() != 0) {
13622 return splitExpression(from);
13623 // Need to recompute everything if there were ancestors
13624 }
13625 SgVariableDeclaration* vardecl = SageBuilder::buildVariableDeclaration(varname, vartype, NULL, parent);
13627 ROSE_ASSERT (sym);
13628 SgInitializedName* initname = sym->get_declaration();
13629 ROSE_ASSERT (initname);
13631 replaceExpressionWithExpression(from, varref);
13632 // std::cout << "Unparsed 3: " << fromparent->sage_class_name() << " --- " << fromparent->unparseToString() << endl;
13633 // cout << "From is a " << from->sage_class_name() << endl;
13635 initname->set_initializer(ai);
13636 ai->set_parent(initname);
13637 myStatementInsert(stmt, vardecl, true);
13638 // vardecl->set_parent(stmt->get_parent());
13639 // FixSgTree(vardecl);
13640 // FixSgTree(parent);
13641 return ai;
13642
13643#else
13644 return NULL;
13645#endif
13646
13647} //splitExpression()
13648
13651 struct SplitStatementGenerator: public StatementGenerator {
13652 SgExpression* expr;
13653 virtual SgStatement* generate(SgExpression* answer) {
13654 using namespace SageBuilder;
13655 return buildBasicBlock(buildAssignStatement(answer, expr));
13656 }
13657 };
13658 SplitStatementGenerator gen;
13659 gen.expr = expr;
13661 }
13662
13664 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,
13665 V_SgGotoStatement);
13666 map<SgLabelStatement*, SgLabelStatement*> labelsToReplace; for
13667 (size_t i = 0; i < gotos.size(); ++i) {
13668 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13669 SgBasicBlock* gsParent = isSgBasicBlock(gs->get_parent());
13670 if (!gsParent) continue;
13671 SgStatementPtrList& bbStatements = gsParent->get_statements();
13672 size_t j = std::find(bbStatements.begin(), bbStatements.end(), gs)
13673 - bbStatements.begin();
13674 ROSE_ASSERT (j != bbStatements.size());
13675 if (j == 0) continue;
13676 if (isSgLabelStatement(bbStatements[j - 1])) {
13677 labelsToReplace[isSgLabelStatement(bbStatements[j - 1])] =
13678 gs->get_label();
13679 }
13680 }
13681 for (size_t i = 0; i < gotos.size(); ++i) {
13682 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13683 SgLabelStatement* oldLabel = gs->get_label();
13684 while (labelsToReplace.find(oldLabel) != labelsToReplace.end()) {
13685 oldLabel = labelsToReplace[oldLabel];
13686 }
13687 gs->set_label(oldLabel);
13688 }
13689 }
13690
13692 switch (e->variantT()) {
13693#ifdef _MSC_VER
13694 // DQ (11/28/2009): This fixes a warning in MSVC (likely p_value should be a "bool" instead of an "int").
13695 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() != 0);
13696#else
13697 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() == true);
13698#endif
13699 case V_SgIntVal: return isSgIntVal(e)->get_value() != 0;
13700 case V_SgCastExp: return isConstantTrue(isSgCastExp(e)->get_operand());
13701 case V_SgNotOp: return isConstantFalse(isSgNotOp(e)->get_operand());
13702 case V_SgAddressOfOp: return true;
13703 default: return false;
13704 }
13705 }
13706
13708 switch (e->variantT()) {
13709 case V_SgBoolValExp: return isSgBoolValExp(e)->get_value() == false;
13710 case V_SgIntVal: return isSgIntVal(e)->get_value() == 0;
13711 case V_SgCastExp: return
13712 isConstantFalse(isSgCastExp(e)->get_operand());
13713 case V_SgNotOp: return isConstantTrue(isSgNotOp(e)->get_operand());
13714 default: return false;
13715 }
13716 }
13717
13719 SgExpression* e) {
13720 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13721 if (!fc) return false;
13722 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13723 if (fr == NULL) return false;
13724 return fr->get_symbol()->get_declaration() == decl;
13725 }
13726
13727 bool SageInterface::isCallToParticularFunction(const std::string& qualifiedName, size_t
13728 arity, SgExpression* e) {
13729 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13730 if (!fc) return false;
13731 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13732 if (fr == NULL) return false;
13733 string name =
13734 fr->get_symbol()->get_declaration()->get_qualified_name().getString();
13735 return (name == qualifiedName &&
13736 fc->get_args()->get_expressions().size() == arity);
13737 }
13738
13740 {
13741 ROSE_ASSERT( e != NULL);
13742 // We enforce that the source expression is fully attached to the AST
13743 // Too strict, the source expression can be just built and not attached.
13744 // Liao, 9/21/2009
13745// ROSE_ASSERT( e->get_parent() != NULL);
13746 return deepCopy(e);
13747 }
13748
13750 {
13751 return deepCopy(s);
13752 }
13753
13754 //----------------- add into AST tree --------------------
13756 {
13757 ROSE_ASSERT(expList);
13758 ROSE_ASSERT(exp);
13759 expList->append_expression(exp);
13760 exp->set_parent(expList);
13761 }
13762
13763 void SageInterface::appendExpressionList(SgExprListExp *expList, const std::vector<SgExpression*>& exp)
13764 {
13765 for (size_t i = 0; i < exp.size(); ++i)
13766 appendExpression(expList, exp[i]);
13767 }
13768
13769# if 0
13770 // DQ (11/25/2011): Moved to the header file so that it could be seen as a template function.
13771
13772 // TODO consider the difference between C++ and Fortran
13773 // fixup the scope of arguments,no symbols for nondefining function declaration's arguments
13774template <class actualFunction>
13775void
13776// SageInterface::setParameterList(SgFunctionDeclaration * func,SgFunctionParameterList * paralist)
13777SageInterface::setParameterList(actualFunction * func,SgFunctionParameterList * paralist)
13778 {
13779 // DQ (11/25/2011): Modified this to be a templated function so that we can handle both
13780 // SgFunctionDeclaration and SgTemplateFunctionDeclaration (and their associated member
13781 // function derived classes).
13782
13783 ROSE_ASSERT(func);
13784 ROSE_ASSERT(paralist);
13785
13786 // Warn to users if a paralist is being shared
13787 if (paralist->get_parent() !=NULL)
13788 {
13789 cerr << "Waring! Setting a used SgFunctionParameterList to function: "
13790 << (func->get_name()).getString()<<endl
13791 << " Sharing parameter lists can corrupt symbol tables!"<<endl
13792 << " Please use deepCopy() to get an exclusive parameter list for each function declaration!"<<endl;
13793 // ROSE_ASSERT(false);
13794 }
13795
13796 // Liao,2/5/2008 constructor of SgFunctionDeclaration will automatically generate SgFunctionParameterList, so be cautious when set new paralist!!
13797 if (func->get_parameterList() != NULL)
13798 if (func->get_parameterList() != paralist)
13799 delete func->get_parameterList();
13800
13801 func->set_parameterList(paralist);
13802 paralist->set_parent(func);
13803 }
13804#endif
13805
13806// static
13807SgVariableSymbol* addArg(SgFunctionParameterList *paraList, SgInitializedName* initName, bool isPrepend)
13808 {
13809 ROSE_ASSERT(paraList != NULL);
13810 ROSE_ASSERT(initName != NULL);
13811
13812 if (isPrepend == true)
13813 paraList->prepend_arg(initName);
13814 else
13815 paraList->append_arg(initName);
13816
13817 // DQ (12/4/2011): If this is going to be set, make sure it will not be over written.
13818 // initName->set_parent(paraList);
13819 if (initName->get_parent() == NULL)
13820 initName->set_parent(paraList);
13821
13822 ROSE_ASSERT(initName->get_parent() == paraList);
13823
13824 SgFunctionDeclaration* func_decl= isSgFunctionDeclaration(paraList->get_parent());
13825
13826 // DQ (12/4/2011): This will not be true for function parameter lists in SgTemplateFunctionDeclaration cases.
13827 // Also in typical use the SgFunctionDeclaration is not known yet so the parent is not set.
13828 // ROSE_ASSERT(paraList->get_parent() != NULL);
13829 // ROSE_ASSERT(func_decl != NULL);
13830
13831 SgScopeStatement* scope = NULL;
13832 if (func_decl != NULL)
13833 {
13834 if ((func_decl->get_definingDeclaration()) == func_decl )
13835 {
13836 // defining function declaration, set scope and symbol table
13837 SgFunctionDefinition* func_def = func_decl->get_definition();
13838 ROSE_ASSERT(func_def);
13839 scope = func_def;
13840 }
13841 else
13842 {
13843 // nondefining declaration, set scope only, currently set to decl's scope, TODO
13844 scope = func_decl->get_scope();
13845 }
13846
13847 // fix up declptr of the init name
13848 initName->set_declptr(func_decl);
13849 }
13850
13851 // 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
13852 // that initName already has a scope.
13853 //
13854 // DQ (12/4/2011): Added check...(fails for case of SgTypeEllipse).
13855 // ROSE_ASSERT(initName->get_scope() != NULL);
13856 // ROSE_ASSERT(initName->get_scope() != NULL || isSgTypeEllipse(initName->get_type()) != NULL);
13857
13858 // ROSE_ASSERT (scope); -- scope may not be set because the function declaration may not have been inserted anywhere
13859
13860 initName->set_scope(scope);
13861 if (scope != NULL)
13862 {
13863 SgVariableSymbol* sym = isSgVariableSymbol(initName->get_symbol_from_symbol_table());
13864 if (sym == NULL)
13865 {
13866 sym = new SgVariableSymbol(initName);
13867 scope->insert_symbol(initName->get_name(), sym);
13868 sym->set_parent(scope->get_symbol_table());
13869 }
13870 return sym;
13871 }
13872 else
13873 {
13874 return NULL;
13875 }
13876 }
13877
13879{
13880 return addArg(paraList,initName,false);
13881}
13882
13884{
13885 return addArg(paraList,initName,true);
13886}
13887
13889{
13890 ROSE_ASSERT(decl);
13891 ROSE_ASSERT(pragma);
13892 if (decl->get_pragma()!=NULL) delete (decl->get_pragma());
13893 decl->set_pragma(pragma);
13894 pragma->set_parent(decl);
13895}
13896
13897
13899//TODO should we ensureBasicBlockAsScope(scope) ? like ensureBasicBlockAsParent(targetStmt);
13900//It might be well legal to append the first and only statement in a scope!
13902 {
13903 // DQ (4/3/2012): Simple globally visible function to call (used for debugging in ROSE).
13904 void testAstForUniqueNodes ( SgNode* node );
13905
13906#if 0
13907 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
13908#endif
13909
13910 // DQ (6/19/2012): Exit as a test...
13911 // ROSE_ASSERT(isSgClassDeclaration(stmt) == NULL);
13912
13913 if (scope == NULL)
13914 {
13915#if 0
13916 printf (" --- scope was not specified as input! \n");
13917#endif
13919 }
13920
13921 ROSE_ASSERT(stmt != NULL);
13922 ROSE_ASSERT(scope != NULL);
13923
13924#if 0
13925 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
13926#endif
13927
13928#if 0
13929 // DQ (2/2/2010): This fails in the projects/OpenMP_Translator "make check" tests.
13930 // DQ (1/2/2010): Introducing test that are enforced at lower levels to catch errors as early as possible.
13931 SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(stmt);
13932 if (declarationStatement != NULL)
13933 {
13934 ROSE_ASSERT(declarationStatement->get_firstNondefiningDeclaration() != NULL);
13935 ROSE_ASSERT(declarationStatement->get_definingDeclaration() != NULL);
13936 }
13937#endif
13938
13939#if 0
13940 // This fix breaks other transformations.
13941 // It is better to do this explicitly as needed before calling appendStatement();
13942 // Liao 10/19/2010
13943 // In rare cases, we are moving the statement from its original scope to another scope
13944 // We have to remove it from its original scope before append it to the new scope
13945 SgNode* old_parent= stmt->get_parent();
13946 if (old_parent)
13947 {
13948 removeStatement(stmt);
13949 }
13950#endif
13951
13952#if 0
13953 // catch-all for statement fixup
13954 // Must fix it before insert it into the scope,
13955 fixStatement(stmt,scope);
13956
13957 //-----------------------
13958 // append the statement finally
13959 // scope->append_statement (stmt);
13960 scope->insertStatementInScope(stmt,false);
13961 stmt->set_parent(scope); // needed?
13962#else
13963 // DQ (7/12/2012): Skip adding when this is a non-autonomous type declaration.
13964 bool skipAddingStatement = false;
13965 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
13966 if (classDeclaration != NULL)
13967 {
13968 // DQ (7/9/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
13969#if 0
13970 if (classDeclaration->get_parent() != NULL)
13971 {
13972 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());
13973 }
13974#endif
13975
13976#if 1
13977 // DQ (6/9/2013): This is the original code...
13978 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false);
13979#else
13980 // 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).
13981 // This fails to add enough statements to the AST.
13982 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false) || (classDeclaration->get_parent() != NULL);
13983#endif
13984
13985 // DQ (6/26/2013): Don't just check for SgTemplateInstantiationDecl, but also for SgClassDeclaration.
13986 // DQ (6/9/2013): Check if this is a SgTemplateInstantiationDecl, since it might be appearing
13987 // twice as a result of a template argument being instantiated and we only want to add it into
13988 // the scope once. This happens for test2013_198.C and I can't find a better solution.
13989 if (classDeclaration != NULL && scope->containsOnlyDeclarations() == true)
13990 {
13991 // Check if this instnatiated template has already been added to the scope.
13992
13993 // DQ (6/26/2013): This is a newer alternative to test for an existing statement in a scope.
13994 // const SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
13995 // SgDeclarationStatementPtrList::const_iterator existingDeclaration = find(declarationList.begin(),declarationList.end(),classDeclaration);
13996 bool statementAlreadyExistsInScope = scope->statementExistsInScope(classDeclaration);
13997 if (statementAlreadyExistsInScope == true)
13998 {
13999 if (isSgTemplateInstantiationDecl(classDeclaration) != NULL)
14000 {
14001// DQ (9/13/2014): Clean up this output when not printing developer warnings.
14002// #if 1
14003#if PRINT_DEVELOPER_WARNINGS
14004 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",
14005 classDeclaration,classDeclaration->class_name().c_str(),scope,scope->class_name().c_str());
14006#endif
14007 }
14008#if 1
14009 else
14010 {
14011#if 1
14012 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",
14013 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14014#endif
14015 }
14016#endif
14017 skipAddingStatement = true;
14018 }
14019 }
14020 }
14021 else
14022 {
14023 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(stmt);
14024 if (enumDeclaration != NULL)
14025 {
14026 // DQ (7/12/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14027 skipAddingStatement = (enumDeclaration->get_isAutonomousDeclaration() == false);
14028 }
14029 }
14030
14031#if 0
14032 // DQ (6/26/2013): This is an attempt to support better testing of possible redundant statements
14033 // that would be inserted into the current scope. This is however a bit expensive so we are using
14034 // this as a way to also debug the new cases where this happens.
14035 bool statementAlreadyExistsInScope = scope->statementExistsInScope(stmt);
14036 if (skipAddingStatement == false && statementAlreadyExistsInScope == true)
14037 {
14038#if 0
14039 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",
14040 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14041#endif
14042#if 0
14043 printf ("Exiting as a test! \n");
14044 ROSE_ABORT();
14045#endif
14046 skipAddingStatement = true;
14047 }
14048#endif
14049
14050#if 0
14051 printf (" --- skipAddingStatement = %s \n",skipAddingStatement ? "true" : "false");
14052#endif
14053
14054 if (skipAddingStatement == false)
14055 {
14056 // catch-all for statement fixup
14057 // Must fix it before insert it into the scope,
14058 // printf ("In appendStatementList(): Calling fixStatement() \n");
14059 fixStatement(stmt,scope);
14060 // printf ("DONE: In appendStatementList(): Calling fixStatement() \n");
14061
14062 //-----------------------
14063 // append the statement finally
14064 // scope->append_statement (stmt);
14065#if 0
14066 printf (" --- calling insertStatementInScope(): scope = %p = %s stmt = %p = %s \n",scope,scope->class_name().c_str(),stmt,stmt->class_name().c_str());
14067#endif
14068 scope->insertStatementInScope(stmt,false);
14069
14070 // DQ (6/9/2013): Added comment only: This is needed because some declaration have to have the
14071 // setting of there paremtn pointes delayed until now based on if they appear nested inside of
14072 // other declarations (e.g. "typedef struct { int x; } y;").
14073 stmt->set_parent(scope); // needed?
14074 }
14075#endif
14076
14077 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14078 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14079 // this). Also since this is only operating within a single scope it is likely too specific to C
14080 // instead of addressing the details of C++ where functions can be placed in alternative scopes and
14081 // use name qualification).
14082 // update the links after insertion!
14084 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14085 {
14086 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14087 }
14088
14089#if 0
14090 // DQ (6/26/2013): Turn on this test for debugging ROSE compiling rose.h header file.
14091 // Note that this is a stronger AST subtree test and not the weaker test for a redundant
14092 // statement in a single scope.
14093 // DQ (9/1/2012): this is a debugging mode that we need to more easily turn on and off.
14094 // DQ (4/3/2012): Added test to make sure that the pointers are unique.
14095 testAstForUniqueNodes(scope);
14096#else
14097 // printf ("In SageInterface::appendStatement(): Skipping test for unique statements in subtree \n");
14098#endif
14099 }
14100
14103{
14104 ROSE_ASSERT (stmt != NULL);
14105 ROSE_ASSERT (for_init_stmt != NULL);
14106
14107#if 0
14108 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());
14109#endif
14110
14111 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14112 // to record it being moved (and thus the macroExpansions that it might be associated with having
14113 // to force the macroExpansion's associated statements to be marked as a transformation.
14115
14116#if 0
14117 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());
14118#endif
14119
14120 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14121 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14122 // prepend, we only need to look at the scope.
14124
14125 for_init_stmt->append_init_stmt (stmt);
14126}
14127
14128void
14129SageInterface::appendStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14130 {
14131 for (size_t i = 0; i < stmts.size(); ++i)
14132 {
14133#if 0
14134#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14135 printf ("In appendStatementList(): stmts[i = %" PRIuPTR "] = %p = %s \n",i,stmts[i],stmts[i]->class_name().c_str());
14136 // printf ("In appendStatementList(): stmts[i = %" PRIuPTR "]->get_parent() = %p \n",i,stmts[i]->get_parent());
14137#endif
14138#endif
14139 appendStatement(stmts[i], scope); // Liao 5/15/2013, defer the logic of checking parent pointers to appendStatement()
14140#if 0
14141 if (stmts[i]->get_parent() != NULL)
14142 {
14143#if 0
14144#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14145 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());
14146#endif
14147#endif
14148 appendStatement(stmts[i], scope);
14149 }
14150 else
14151 {
14152 printf (" --- WARNING: In appendStatementList(): stmts[i = %" PRIuPTR "] not added to scope (because stmts[i]->get_parent() == NULL) \n",i);
14153 }
14154#endif
14155 }
14156 }
14157
14160 {
14161 ROSE_ASSERT (stmt != NULL);
14162
14163#if 0
14164 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14165#endif
14166
14167 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.1") == false);
14168
14169 if (scope == NULL)
14170 {
14172 }
14173
14174 ROSE_ASSERT(scope != NULL);
14175 // TODO handle side effect like SageBuilder::appendStatement() does
14176
14177 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.1a") == false);
14178
14179 // Must fix it before insert it into the scope,
14180 // otherwise assertions in insertStatementInScope() would fail
14181 fixStatement(stmt,scope);
14182
14183#if 0
14184 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",
14185 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14186#endif
14187
14188 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.2") == false);
14189
14190 // DQ (12/1/2015): If this is a moved statement then cause it to update internal data structures
14191 // to record it being moved (and thus the macroExpansions that it might be associated with having
14192 // to force the macroExpansion's associated statements to be marked as a transformation.
14194
14195#if 0
14196 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",
14197 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14198#endif
14199
14200 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.3") == false);
14201
14202 // DQ (12/1/2015): Also look at the statements on either side of the location where this statement
14203 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14204 // prepend, we only need to look at the scope.
14206
14207#if 0
14208 printf ("Calling insertStatementInScope() \n");
14209#endif
14210
14211 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.4") == false);
14212 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.4a") == false);
14213
14214 scope->insertStatementInScope(stmt,true);
14215 stmt->set_parent(scope); // needed?
14216
14217 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.5") == false);
14218
14219 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14220 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14221 // this). Also since this is only operating within a single scope it is likely too specific to C
14222 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14223 // use name qualification).
14224 // update the links after insertion!
14226 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14227 {
14228 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14229 }
14230
14231 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.6") == false);
14232
14233#if 0
14234 printf ("Leaving SageInterface::prependStatement() \n");
14235#endif
14236 } // prependStatement()
14237
14238
14241{
14242 ROSE_ASSERT (stmt != NULL);
14243 ROSE_ASSERT (for_init_stmt != NULL);
14244
14245#if 0
14246 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());
14247#endif
14248
14249 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14250 // to record it being moved (and thus the macroExpansions that it might be associated with having
14251 // to force the macroExpansion's associated statements to be marked as a transformation.
14253
14254#if 0
14255 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());
14256#endif
14257
14258 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14259 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14260 // prepend, we only need to look at the scope.
14262
14263 for_init_stmt->prepend_init_stmt (stmt);
14264}
14265
14266void SageInterface::prependStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14267 {
14268 for (size_t i = stmts.size(); i > 0; --i)
14269 {
14270 prependStatement(stmts[i - 1], scope);
14271 }
14272 }
14273
14278{
14279 bool rt = false;
14280 ROSE_ASSERT (scope != NULL);
14281 switch (scope->variantT())
14282 {
14283 case V_SgBasicBlock:
14284 case V_SgClassDefinition:
14285 case V_SgFunctionDefinition:
14286 case V_SgGlobal:
14287 case V_SgNamespaceDefinitionStatement: //?
14288 rt = true;
14289 break;
14290
14291 case V_SgAssociateStatement :
14292 case V_SgBlockDataStatement :
14293 case V_SgCatchOptionStmt:
14294 case V_SgDoWhileStmt:
14295 case V_SgForAllStatement:
14296 case V_SgForStatement:
14297 case V_SgFortranDo:
14298 case V_SgIfStmt:
14299 case V_SgSwitchStatement:
14300 case V_SgUpcForAllStatement:
14301 case V_SgWhileStmt:
14302 rt = false;
14303 break;
14304
14305 default:
14306 cout<<"unrecognized or unhandled scope type for SageInterface::hasSimpleChildrenList() "<<endl;
14307 break;
14308 }
14309 return rt;
14310}
14311
14312
14313// 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.
14315 {
14316 // When inserting a statement into global scope, if inserting at the top of scope it is best to insert
14317 // after the last statement from the preinclude file rose_edg_required_macros_and_functions.h.
14318
14319 SgDeclarationStatementPtrList & declarationList = globalScope->get_declarations();
14320
14321 SgStatement* last_statement = NULL;
14322 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
14323 // while (i != declarationList.end())
14324 while (i != declarationList.end() && (*i)->get_file_info() != NULL && (*i)->get_file_info()->isFrontendSpecific() == true)
14325 {
14326#if 0
14327 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");
14328#endif
14329 last_statement = *i;
14330
14331 i++;
14332 }
14333
14334 ROSE_ASSERT(last_statement != NULL);
14335#if 1
14336 printf ("last_statement = %p = %s \n",last_statement,last_statement->class_name().c_str());
14337#endif
14338#if 0
14339 printf ("Exiting as a test! \n");
14340 ROSE_ABORT();
14341#endif
14342
14343 return last_statement;
14344 }
14345
14346
14347 //TODO handle more side effect like SageBuilder::append_statement() does
14348 //Merge myStatementInsert()
14349 // insert SageInterface::insertStatement()
14350void SageInterface::insertStatement(SgStatement *targetStmt, SgStatement* newStmt, bool insertBefore, bool autoMovePreprocessingInfo /*= true */)
14351 {
14352 ROSE_ASSERT(targetStmt &&newStmt);
14353 ROSE_ASSERT(targetStmt != newStmt); // should not share statement nodes!
14354 SgNode* parent = targetStmt->get_parent();
14355 if (parent == NULL)
14356 {
14357 cerr << "Empty parent pointer for target statement. May be caused by the wrong order of target and new statements in insertStatement(targetStmt, newStmt)"<<endl;
14358 ROSE_ASSERT(parent);
14359 }
14360
14361 if (isSgLabelStatement(parent) != NULL)
14362 {
14363#if 0
14364 printf ("In SageInterface::insertStatement(): Detected case of label statement as parent, using parent of label statement \n");
14365#endif
14366 SgLabelStatement* labelStatement = isSgLabelStatement(parent);
14367 // parent = labelStatement->get_scope();
14368 parent = labelStatement->get_parent();
14369 ROSE_ASSERT(isSgLabelStatement(parent) == NULL);
14370 }
14371
14372#if 0
14373 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());
14374#endif
14375
14376 // DQ (12/2/2014): Not sure why this was here in the first place (likely debugging code from the fix for the SgLableStatement insertion.
14377 // SgFunctionDefinition* functionDefinition = SageInterface::getEnclosingProcedure(targetStmt);
14378 // ROSE_ASSERT(functionDefinition != NULL);
14379
14380 // Liao 3/2/2012. The semantics of ensureBasicBlockAsParent() are messy. input targetStmt may be
14381 // returned as it is if it is already a basic block as a body of if/while/catch/ etc.
14382 // We now have single statement true/false body for IfStmt etc
14383 // However, IfStmt::insert_child() is ambiguous and not implemented
14384 // So we make SgBasicBlock out of the single statement and
14385 // essentially call SgBasicBlock::insert_child() instead.
14386 // TODO: add test cases for If, variable, variable/struct inside if, etc
14387 // parent = ensureBasicBlockAsParent(targetStmt);
14388
14389 // must get the new scope after ensureBasicBlockAsParent ()
14390 SgScopeStatement* scope = targetStmt->get_scope();
14391 ROSE_ASSERT(scope);
14392
14393#if 0
14394 printf ("targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14395 printf ("scope = %p = %s \n",scope,scope->class_name().c_str());
14396#endif
14397
14398 // DQ (11/16/2014): This step is problematic if the targetStmt has been transformed to be associated with a SgLabelStatement.
14399 // The reason is that the targetStmt's parent will have been reset to be the SgLabelStatement and the logic in the set_parent()
14400 // function will assert fail when the parent is being set to itself (which is a good idea in general). A better solution might
14401 // 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
14402 // more sense in this special case of a SgLabelStatement.
14403 // newStmt->set_parent(targetStmt->get_parent());
14404 newStmt->set_parent(scope);
14405
14406 // 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.
14407 // The fix was the reuse the one that was found.
14408 fixStatement(newStmt,scope);
14409
14410 // DQ (9/16/2010): Added assertion that appears to be required to be true.
14411 // However, if this is required to be true then what about statements in
14412 // SgStatementExpression IR nodes?
14413 ROSE_ASSERT(isSgStatement(parent) != NULL);
14414
14415 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
14416 // appear before the statement to be attached to the inserted statement (and marked
14417 // to appear before that statement).
14418 ROSE_ASSERT(targetStmt != NULL);
14419 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
14420
14421#if 0
14422 printf ("In SageInterface::insertStatement(): after checking for associated comments \n");
14423 reportNodesMarkedAsModified(scope);
14424#endif
14425
14426 // TODO refactor this portion of code into a separate function
14427 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14428 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
14429 if (autoMovePreprocessingInfo) // Do this only if automatically handling of preprocessing information is request by users
14430 {
14431 if (comments != NULL && isSgBasicBlock(newStmt) == NULL)
14432 {
14433 vector<int> captureList;
14434#if 0
14435 printf ("Found attached comments (at %p = %s, inserting %p = %s insertBefore = %s): comments->size() = %" PRIuPTR " \n",
14436 targetStmt,targetStmt->class_name().c_str(),newStmt,newStmt->class_name().c_str(),insertBefore ? "true" : "false",comments->size());
14437#endif
14438 // DQ (9/17/2010): Assert that the new statement being inserted has no attached comments or CPP directives.
14439 if (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false)
14440 {
14441 // If the inserted statment has attached comments or CPP directives then this is gets a little
14442 // bit more comple and we don't support that at present.
14443 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");
14444 }
14445 // DQ (9/17/2010): commented out because it fails test in projects/OpenMP_Translator/for_firstprivate.c
14446 ROSE_ASSERT((newStmt->getAttachedPreprocessingInfo() == NULL) || (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false));
14447
14448 int commentIndex = 0;
14449 AttachedPreprocessingInfoType::iterator i;
14450 for (i = comments->begin(); i != comments->end(); i++)
14451 {
14452 ROSE_ASSERT ( (*i) != NULL );
14453#if 0
14454 printf (" Attached Comment (relativePosition=%s): %s\n",
14455 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
14456 (*i)->getString().c_str());
14457 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
14458 (*i)->get_file_info()->display("comment/directive location");
14459#endif
14460 PreprocessingInfo::RelativePositionType relativePosition = (insertBefore == true) ? PreprocessingInfo::before : PreprocessingInfo::after;
14461 if ((*i)->getRelativePosition() == relativePosition)
14462 {
14463 // accumulate into list
14464 captureList.push_back(commentIndex);
14465 }
14466
14467 commentIndex++;
14468 }
14469
14470 // printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
14471 if (captureList.empty() == false)
14472 {
14473 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
14474 // SgStatement* surroundingStatement = (insertBefore == true) ? getPreviousStatement(targetStmt) : getNextStatement(targetStmt);
14475 // SgStatement* surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14476 SgStatement* surroundingStatement = newStmt;
14477 ROSE_ASSERT(surroundingStatement != targetStmt);
14478 ROSE_ASSERT(surroundingStatement != NULL);
14479#if 0
14480 if (surroundingStatement == NULL)
14481 {
14482 // printf ("Warning: the surrounding statement for insertBefore = %s is NULL (so use the newStmt) \n",insertBefore ? "true" : "false");
14483 surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14484 }
14485#endif
14486 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
14487 // printf ("This is a valid surrounding statement = %s for insertBefore = %s \n",surroundingStatement->class_name().c_str(),insertBefore ? "true" : "false");
14488 vector<int>::iterator j = captureList.begin();
14489 while (j != captureList.end())
14490 {
14491 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
14492 // printf ("Attaching comments to newStmt = %p = %s \n",newStmt,newStmt->class_name().c_str());
14493 newStmt->addToAttachedPreprocessingInfo((*comments)[*j]);
14494
14495 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
14496 // printf ("Removing entry from comments list on targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14497 (*comments)[*j] = NULL;
14498
14499 j++;
14500 }
14501
14502 // Now remove each NULL entries in the comments vector.
14503 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
14504 for (size_t n = 0; n < captureList.size(); n++)
14505 {
14506 AttachedPreprocessingInfoType::iterator k = comments->begin();
14507 while (k != comments->end())
14508 {
14509 // Only modify the list once per iteration over the captureList
14510 if (*k == NULL)
14511 {
14512 comments->erase(k);
14513 break;
14514 }
14515 k++;
14516 }
14517 }
14518 }
14519 }
14520 else
14521 {
14522 // printf ("No attached comments (at %p of type: %s): \n",targetStmt,targetStmt->class_name().c_str());
14523 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14524 // I think that special rules apply to inserting a SgBasicBlock so disable comment relocation when inserting a SgBasicBlock.
14525 if (comments != NULL)
14526 {
14527 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");
14528 }
14529 }
14530 } // end if autoMovePreprocessingInfo
14531
14532
14533#if 0
14534 printf ("In SageInterface::insertStatement(): after processing associated comments \n");
14535 reportNodesMarkedAsModified(scope);
14536#endif
14537
14538 if (isSgIfStmt(parent))
14539 {
14540 if (isSgIfStmt(parent)->get_conditional()==targetStmt)
14541 {
14542 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14543 }
14544 else
14545 {
14546 if (isSgIfStmt(parent)->get_true_body()==targetStmt)
14547 {
14548 // Liao 3/2/2012
14549 // We have some choices:
14550 // 1) if the targeStmt is a basic block, we can append/prepend the new stmt
14551 // within the targetStmt. But this is not the exact semantics of insertStatment. It will break the outliner.
14552 // Since the targetStmt will have new content inside of it, which is not the semantics of
14553 // inserting anything before/or after it.
14554 // 2) always insert a padding basic block between parent and targetStmt
14555 // and we can legally insert before/after the target statement within the
14556 // padding basic block.
14557 //TODO: this insertion of padding basic block should ideally go into some AST normalization phase
14558 // so the transformation function (insertStatement) only does what it means to do, no more and no less.
14559 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14560 isSgIfStmt(parent)->set_true_body(newparent);
14561 newparent->set_parent(parent);
14562 insertStatement(targetStmt, newStmt,insertBefore);
14563 }
14564 else
14565 {
14566 if (isSgIfStmt(parent)->get_false_body()==targetStmt)
14567 {
14568 // ensureBasicBlockAsParent(targetStmt);
14569 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14570 isSgIfStmt(parent)->set_false_body(newparent);
14571 newparent->set_parent(parent);
14572 insertStatement(targetStmt, newStmt,insertBefore);
14573 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14574 }
14575 }
14576 }
14577 }
14578 else
14579 {
14580 if (isSgWhileStmt(parent))
14581 {
14582 if (isSgWhileStmt(parent)->get_condition()==targetStmt)
14583 {
14584 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14585 }
14586 else
14587 {
14588 if (isSgWhileStmt(parent)->get_body()==targetStmt)
14589 {
14590 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14591 isSgWhileStmt(parent)->set_body(newparent);
14592 newparent->set_parent(parent);
14593 insertStatement(targetStmt, newStmt,insertBefore);
14594 // ensureBasicBlockAsParent(targetStmt);
14595 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14596 }
14597 }
14598 }
14599 else
14600 {
14601 if (isSgDoWhileStmt(parent))
14602 {
14603 if (isSgDoWhileStmt(parent)->get_condition()==targetStmt)
14604 {
14605 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14606 }
14607 else
14608 {
14609 if (isSgDoWhileStmt(parent)->get_body()==targetStmt)
14610 {
14611 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14612 isSgDoWhileStmt(parent)->set_body(newparent);
14613 newparent->set_parent(parent);
14614 insertStatement(targetStmt, newStmt,insertBefore);
14615 // ensureBasicBlockAsParent(targetStmt);
14616 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14617 }
14618 }
14619 }
14620 else
14621 {
14622 if (isSgForStatement(parent))
14623 {
14624 if (isSgForStatement(parent)->get_loop_body()==targetStmt)
14625 {
14626 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14627 isSgForStatement(parent)->set_loop_body(newparent);
14628 newparent->set_parent(parent);
14629 insertStatement(targetStmt, newStmt,insertBefore);
14630 // ensureBasicBlockAsParent(targetStmt);
14631 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14632 }
14633 else
14634 {
14635 if (isSgForStatement(parent)->get_test()==targetStmt)
14636 {
14637 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14638 }
14639 }
14640 }
14641 else // \pp (2/24/2011) added support for UpcForAll
14642 {
14643 if (SgUpcForAllStatement* p = isSgUpcForAllStatement(parent))
14644 {
14645 //const bool stmt_present = (p->get_loop_body() == targetStmt || p->get_test() == targetStmt);
14646
14647 // \pp \todo what if !stmt_present
14648 // ROSE_ASSERT(stmt_present != NULL);
14649 insertStatement(p, newStmt, insertBefore);
14650 }
14651 else
14652 {
14653 if (SgOmpBodyStatement * p = isSgOmpBodyStatement (parent))
14654 {
14655 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14656 p->set_body(newparent);
14657 newparent->set_parent(parent);
14658 insertStatement(targetStmt, newStmt,insertBefore);
14659 }
14660 else
14661 {
14662 // It appears that all of the recursive calls are untimately calling this location.
14663 SgStatement* stmnt = isSgStatement(parent);
14664 ROSE_ASSERT(stmnt != NULL);
14665 stmnt->insert_statement(targetStmt,newStmt,insertBefore);
14666 }
14667 }
14668 }
14669 }
14670 }
14671 }
14672
14673 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14674 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14675 // this). Also since this is only operating within a single scope it is likely too specific to C
14676 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14677 // use name qualification).
14678 // update the links after insertion!
14680 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(newStmt) != NULL) )
14681 {
14682 updateDefiningNondefiningLinks(isSgFunctionDeclaration(newStmt),scope);
14683 }
14684
14685#if 0
14686 printf ("In SageInterface::insertStatement(): at BASE of function \n");
14687 reportNodesMarkedAsModified(scope);
14688#endif
14689 }
14690
14691
14692void SageInterface::insertStatementList(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts, bool insertBefore)
14693 {
14694 if (insertBefore)
14695 {
14696 for (size_t i = 0; i < newStmts.size(); ++i)
14697 {
14698 insertStatementBefore(targetStmt, newStmts[i]);
14699 }
14700 }
14701 else
14702 {
14703 for (size_t i = newStmts.size(); i > 0; --i)
14704 {
14705 insertStatementAfter(targetStmt, newStmts[i - 1]);
14706 }
14707 }
14708 }
14709
14710void SageInterface::insertStatementAfter(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true*/)
14711 {
14712 insertStatement(targetStmt,newStmt,false, autoMovePreprocessingInfo);
14713 }
14714
14715void SageInterface::insertStatementListAfter(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14716 {
14717 insertStatementList(targetStmt,newStmts,false);
14718 }
14719
14722 {
14723 ROSE_ASSERT (stmt != NULL);
14724 ROSE_ASSERT (scope != NULL);
14725 // Insert to be the declaration after current declaration sequence, if any
14726 SgStatement* l_stmt = findLastDeclarationStatement (scope);
14727 if (l_stmt)
14728 insertStatementAfter(l_stmt,stmt);
14729 else
14730 prependStatement(stmt, scope);
14731 }
14732
14734void SageInterface::insertStatementAfterLastDeclaration(std::vector<SgStatement*> stmt_list, SgScopeStatement* scope)
14735 {
14736 ROSE_ASSERT (scope != NULL);
14737 vector <SgStatement* >::iterator iter;
14738 SgStatement* prev_stmt = NULL;
14739 for (iter= stmt_list.begin(); iter != stmt_list.end(); iter++)
14740 {
14741 if (iter == stmt_list.begin())
14742 {
14744 }
14745 else
14746 {
14747 ROSE_ASSERT (prev_stmt != NULL);
14748 insertStatementAfter (prev_stmt, *iter);
14749 }
14750 prev_stmt = *iter;
14751 }
14752 }
14753
14755{
14756 ROSE_ASSERT(newStmt!=NULL);
14757 ROSE_ASSERT(scope!=NULL);
14758 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14759 if (!isSgDeclarationStatement(targetStmt)) {
14760 insertStatementBefore(targetStmt, newStmt, movePreprocessingInfo);
14761 return;
14762 }
14763 }
14764 appendStatement(newStmt, scope);
14765}
14766
14767void SageInterface::insertStatementListBeforeFirstNonDeclaration(const std::vector<SgStatement*> &newStmts,SgScopeStatement *scope)
14768{
14769 ROSE_ASSERT(scope!=NULL);
14770 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14771 if (!isSgDeclarationStatement(targetStmt)) {
14772 insertStatementListBefore(targetStmt, newStmts);
14773 return;
14774 }
14775 }
14776 appendStatementList(newStmts, scope);
14777}
14778
14779void SageInterface::insertStatementBefore(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true */)
14780 {
14781 insertStatement(targetStmt,newStmt,true, autoMovePreprocessingInfo);
14782 }
14783
14784void SageInterface::insertStatementListBefore(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14785 {
14786 insertStatementList(targetStmt,newStmts,true);
14787 }
14788
14789 //a wrapper for set_expression(), set_operand(), set_operand_exp() etc
14790 // special concern for lvalue, parent,
14791 // todo: warning overwriting existing operands
14793 {
14794 ROSE_ASSERT(target);
14795 ROSE_ASSERT(operand);
14796 ROSE_ASSERT(target!=operand);
14797 switch (target->variantT())
14798 {
14799 case V_SgActualArgumentExpression:
14800 isSgActualArgumentExpression(target)->set_expression(operand);
14801 break;
14802 case V_SgAsmOp:
14803 isSgAsmOp(target)->set_expression(operand);
14804 break;
14805 case V_SgSizeOfOp:
14806 isSgSizeOfOp(target)->set_operand_expr(operand);
14807 break;
14808 case V_SgTypeIdOp:
14809 isSgTypeIdOp(target)->set_operand_expr(operand);
14810 break;
14811 case V_SgVarArgOp:
14812 isSgVarArgOp(target)->set_operand_expr(operand);
14813 break;
14814 case V_SgVarArgStartOneOperandOp:
14815 isSgVarArgStartOneOperandOp(target)->set_operand_expr(operand);
14816 break;
14817 case V_SgAssignInitializer:
14818 isSgAssignInitializer (target)->set_operand(operand);
14819 break;
14820 default:
14821 if (isSgUnaryOp(target)!=NULL)
14822 isSgUnaryOp(target)->set_operand_i(operand);
14823 else
14824 {
14825 cerr<<"\tSageInterface::setOperand(): unhandled case for target expression of type "
14826 <<target->class_name()<<endl;
14827 ROSE_ABORT();
14828 }
14829 }// end switch
14830 operand->set_parent(target);
14831 markLhsValues(target);
14832 }
14833
14834 // binary and SgVarArgCopyOp, SgVarArgStartOp
14836 {
14837 ROSE_ASSERT(target);
14838 ROSE_ASSERT(lhs);
14839 ROSE_ASSERT(target!=lhs);
14840 bool hasrhs = false;
14841
14842 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14843 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14844 SgBinaryOp* binary = isSgBinaryOp(target);
14845
14846 if (varargcopy!=NULL)
14847 {
14848 varargcopy->set_lhs_operand(lhs);
14849 if( varargcopy->get_rhs_operand()!=NULL) hasrhs= true;
14850 }
14851 else if(varargstart!=NULL)
14852 {
14853 varargstart->set_lhs_operand(lhs);
14854 if( varargstart->get_rhs_operand()!=NULL) hasrhs= true;
14855 }
14856 else if(binary!=NULL)
14857 {
14858 binary->set_lhs_operand(lhs);
14859 if( binary->get_rhs_operand()!=NULL) hasrhs= true;
14860 }
14861 else
14862 {
14863 cout<<"SageInterface::setLhsOperand(): unhandled case for target expression of type "
14864 <<target->class_name()<<endl;
14865 ROSE_ABORT();
14866 }
14867 lhs->set_parent(target);
14868// only when both lhs and rhs are available, can we set lvalue
14869// there is assertion(rhs!=NULL) in markLhsValues()
14870 if (hasrhs)
14871 markLhsValues(target);
14872 }
14873
14875 {
14876 ROSE_ASSERT(target);
14877 ROSE_ASSERT(rhs);
14878 ROSE_ASSERT(target!=rhs);
14879 bool haslhs = false;
14880
14881 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14882 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14883 SgBinaryOp* binary = isSgBinaryOp(target);
14884
14885 if (varargcopy!=NULL)
14886 {
14887 varargcopy->set_rhs_operand(rhs);
14888 if( varargcopy->get_lhs_operand()!=NULL) haslhs= true;
14889 }
14890 else if(varargstart!=NULL)
14891 {
14892 varargstart->set_rhs_operand(rhs);
14893 if( varargstart->get_lhs_operand()!=NULL) haslhs= true;
14894 }
14895 else if(binary!=NULL)
14896 {
14897 binary->set_rhs_operand(rhs);
14898 if( binary->get_lhs_operand()!=NULL) haslhs= true;
14899 }
14900 else
14901 {
14902 cout<<"SageInterface::setRhsOperand(): unhandled case for target expression of type "
14903 <<target->class_name()<<endl;
14904 ROSE_ABORT();
14905 }
14906 rhs->set_parent(target);
14907// only when both lhs and rhs are available, can we set lvalue
14908 if (haslhs)
14909 markLhsValues(target);
14910 }
14911
14912// DQ (1/25/2010): Added to simplify handling of directories (e.g. for code generation).
14913void SageInterface::moveToSubdirectory ( std::string directoryName, SgFile* file )
14914 {
14915 // This support makes use of the new SgDirectory IR node. It causes the unparser to
14916 // generate a subdirectory and unparse the file into the subdirectory. It works
14917 // by internally calling the system function "system()" to call "mkdir directoryName"
14918 // and then chdir()" to change the current directory. These steps are handled by the
14919 // unparser.
14920
14921 // This function just does the transformation to insert a SgDirectory IR node between
14922 // the referenced SgFile and it's project (fixing up parents and file lists etc.).
14923
14924 // Add a directory and unparse the code (to the new directory)
14925 SgDirectory* directory = new SgDirectory(directoryName);
14926
14927 SgFileList* parentFileList = isSgFileList(file->get_parent());
14928 ROSE_ASSERT(parentFileList != NULL);
14929 directory->set_parent(file->get_parent());
14930
14931 SgProject* project = NULL;
14932 SgDirectory* parentDirectory = isSgDirectory(parentFileList->get_parent());
14933
14934 if (parentDirectory != NULL)
14935 {
14936 // Add a directory to the list in the SgDirectory node.
14937 parentDirectory->get_directoryList()->get_listOfDirectories().push_back(directory);
14938
14939 // Erase the reference to the file in the project's file list.
14940 // parentDirectory->get_fileList().erase(find(parentDirectory->get_fileList().begin(),parentDirectory->get_fileList().end(),file));
14941 }
14942 else
14943 {
14944 project = isSgProject(parentFileList->get_parent());
14945 ROSE_ASSERT(project != NULL);
14946
14947 // Add a directory to the list in the SgProject node.
14948 project->get_directoryList()->get_listOfDirectories().push_back(directory);
14949
14950 // Erase the reference to the file in the project's file list.
14951 // project->get_fileList().erase(find(project->get_fileList().begin(),project->get_fileList().end(),file));
14952 }
14953
14954 // Put the file into the new directory.
14955 directory->get_fileList()->get_listOfFiles().push_back(file);
14956
14957 // Erase the reference to the file in the project's file list.
14958 parentFileList->get_listOfFiles().erase(find(parentFileList->get_listOfFiles().begin(),parentFileList->get_listOfFiles().end(),file));
14959
14960 file->set_parent(directory);
14961}
14962
14963
14964//------------------------- AST repair----------------------------
14965//----------------------------------------------------------------
14967 {
14968 ROSE_ASSERT(structDecl != NULL);
14969 ROSE_ASSERT(scope != NULL);
14970 SgClassDeclaration* nondefdecl = isSgClassDeclaration(structDecl->get_firstNondefiningDeclaration());
14971 ROSE_ASSERT(nondefdecl != NULL);
14972
14973 // ROSE_ASSERT(structDecl->get_definingDeclaration() != NULL);
14974 SgClassDeclaration* defdecl = isSgClassDeclaration(structDecl->get_definingDeclaration());
14975 // ROSE_ASSERT(defdecl != NULL);
14976
14977 // Liao, 9/2/2009
14978 // fixup missing scope when bottomup AST building is used
14979 if (structDecl->get_scope() == NULL)
14980 structDecl->set_scope(scope);
14981 if (nondefdecl->get_scope() == NULL)
14982 nondefdecl->set_scope(scope);
14983
14984#if 0
14985 if (structDecl->get_parent() == NULL)
14986 structDecl->set_parent(scope);
14987 if (nondefdecl->get_parent() == NULL)
14988 nondefdecl->set_parent(scope);
14989#else
14990 // 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");
14991
14992 // DQ (7/21/2012): Can we assert this here? NO!
14993 // ROSE_ASSERT(structDecl->get_parent() == NULL);
14994 // ROSE_ASSERT(nondefdecl->get_parent() == NULL);
14995#endif
14996
14997 SgName name = structDecl->get_name();
14998
14999 // This is rare case (translation error) when scope->lookup_class_symbol(name) will find something
15000 // but nondefdecl->get_symbol_from_symbol_table() returns NULL
15001 // But symbols are associated with nondefining declarations whenever possible
15002 // and AST consistent check will check the nondefining declarations first
15003 // Liao, 9/2/2009
15004 // SgClassSymbol* mysymbol = scope->lookup_class_symbol(name);
15005 SgClassSymbol* mysymbol = isSgClassSymbol(nondefdecl->get_symbol_from_symbol_table());
15006
15007 // DQ (3/14/2014): This is false for a copy of a class declaration being inserted into the AST.
15008 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15009 // ROSE_ASSERT(mysymbol != NULL);
15010
15011 if (mysymbol == NULL)
15012 {
15013 printf ("Note: SageInterface::fixStructDeclaration(): structDecl = %p nondefdecl = %p (mysymbol == NULL) \n",structDecl,nondefdecl);
15014
15015 // 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...
15016 // DQ (12/4/2011): Only generate symbols and set the scope if this is the correct scope.
15017 ROSE_ASSERT(structDecl->get_scope() != NULL);
15018
15019 if (scope == structDecl->get_scope())
15020 {
15021 mysymbol = new SgClassSymbol(nondefdecl);
15022 ROSE_ASSERT(mysymbol);
15023
15024 // I need to check the rest of these functions.
15025 printf ("############## DANGER:DANGER:DANGER ################\n");
15026
15027 printf ("In SageInterface::fixStructDeclaration(): Adding class symbol to scope = %p = %s \n",scope,scope->class_name().c_str());
15028 scope->insert_symbol(name, mysymbol);
15029
15030 // ROSE_ASSERT(defdecl != NULL);
15031 if (defdecl)
15032 defdecl->set_scope(scope);
15033 nondefdecl->set_scope(scope);
15034
15035 printf ("*** WARNING: In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Commented out the setting of the parent to be the same as the scope \n");
15036#if 0
15037 if (defdecl)
15038 defdecl->set_parent(scope);
15039 nondefdecl->set_parent(scope);
15040#endif
15041 }
15042 else
15043 {
15044 printf ("In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Skipped building an associated symbol! \n");
15045 }
15046 }
15047
15048 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15049 ROSE_ASSERT(nondefdecl->get_type() != NULL);
15050
15051 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15052 ROSE_ASSERT(nondefdecl->get_type()->variantT() != V_SgNode);
15053
15054 // DQ (9/4/2012): This should be a SgClassType IR node.
15055 ROSE_ASSERT(isSgClassType(nondefdecl->get_type()) != NULL);
15056
15057 // fixup SgClassType, which is associated with the first non-defining declaration only
15058 // and the other declarations share it.
15059 if (nondefdecl->get_type() == NULL)
15060 {
15061 nondefdecl->set_type(SgClassType::createType(nondefdecl));
15062 }
15063 ROSE_ASSERT (nondefdecl->get_type() != NULL);
15064
15065 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15066 if (defdecl != NULL)
15067 {
15068 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15069 ROSE_ASSERT(defdecl->get_type()->variantT() != V_SgNode);
15070
15071 // DQ (9/4/2012): This should be a SgClassType IR node.
15072 ROSE_ASSERT(isSgClassType(defdecl->get_type()) != NULL);
15073 }
15074
15075 // ROSE_ASSERT(defdecl != NULL);
15076 if (defdecl != NULL)
15077 {
15078 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15079 ROSE_ASSERT(defdecl->get_type() != NULL);
15080 if (defdecl->get_type() != nondefdecl->get_type())
15081 {
15082 printf ("ERROR: defdecl->get_type() != nondefdecl->get_type(): what are these: \n");
15083 printf (" defdecl->get_type() = %p = %s \n",defdecl ->get_type(),defdecl ->get_type()->class_name().c_str());
15084 SgNamedType* namedType_definingDecl = isSgNamedType(defdecl->get_type());
15085 if (namedType_definingDecl != NULL)
15086 {
15087 printf ("namedType_definingDecl->get_declaration() = %p = %s \n",namedType_definingDecl->get_declaration(),namedType_definingDecl->get_declaration()->class_name().c_str());
15088 }
15089 printf (" nondefdecl->get_type() = %p = %s \n",nondefdecl->get_type(),nondefdecl->get_type()->class_name().c_str());
15090 SgNamedType* namedType_nondefiningDecl = isSgNamedType(nondefdecl->get_type());
15091 if (namedType_nondefiningDecl != NULL)
15092 {
15093 printf ("namedType_nondefiningDecl->get_declaration() = %p = %s \n",namedType_nondefiningDecl->get_declaration(),namedType_nondefiningDecl->get_declaration()->class_name().c_str());
15094 }
15095 }
15096 //ROSE_ASSERT(defdecl->get_type() == nondefdecl->get_type());
15097 }
15098 }
15099
15100
15102 {
15103 fixStructDeclaration(classDecl,scope);
15104 }
15105
15106
15108 {
15109 ROSE_ASSERT(structDecl);
15110 ROSE_ASSERT(scope);
15111 SgNamespaceDeclarationStatement* nondefdecl = isSgNamespaceDeclarationStatement(structDecl->get_firstNondefiningDeclaration());
15112 ROSE_ASSERT(nondefdecl);
15113 // Liao, 9/2/2009
15114 // fixup missing scope when bottomup AST building is used
15115 if (structDecl->get_parent() == NULL)
15116 structDecl->set_parent(scope);
15117 if (nondefdecl->get_parent() == NULL)
15118 nondefdecl->set_parent(scope);
15119
15120 // tps : (09/03/2009) Namespace should not have a scope
15121 /*
15122 if (structDecl->get_scope() == NULL)
15123 structDecl->set_scope(scope);
15124 if (nondefdecl->get_scope() == NULL)
15125 nondefdecl->set_scope(scope);
15126 */
15127
15128 SgName name= structDecl->get_name();
15129 // SgNamespaceSymbol* mysymbol = scope->lookup_namespace_symbol(name);
15130 SgNamespaceSymbol* mysymbol = isSgNamespaceSymbol(nondefdecl->get_symbol_from_symbol_table());
15131 if (mysymbol==NULL)
15132 {
15133 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15134 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15135 if (scope == structDecl->get_scope())
15136 {
15137 mysymbol = new SgNamespaceSymbol(name,nondefdecl);
15138 ROSE_ASSERT(mysymbol);
15139
15140 printf ("In SageInterface::fixNamespaceDeclaration(): inserting namespace symbol into scope = %p = %s \n",scope,scope->class_name().c_str());
15141 scope->insert_symbol(name, mysymbol);
15142
15143 SgNamespaceDeclarationStatement* defdecl = isSgNamespaceDeclarationStatement(structDecl->get_definingDeclaration());
15144 ROSE_ASSERT(defdecl);
15145 defdecl->set_scope(scope);
15146 nondefdecl->set_scope(scope);
15147
15148 defdecl->set_parent(scope);
15149 nondefdecl->set_parent(scope);
15150 }
15151 }
15152 }
15153
15155 {
15156 ROSE_ASSERT(varDecl != NULL);
15157 ROSE_ASSERT(scope != NULL);
15158
15159 SgInitializedNamePtrList namelist = varDecl->get_variables();
15160
15161 // printf ("In SageInterface::fixVariableDeclaration(): Is this a recursive call! \n");
15162
15163#if 0
15164 printf ("In SageInterface::fixVariableDeclaration(): varDecl = %p scope = %p = %s \n",varDecl,scope,scope->class_name().c_str());
15165#endif
15166
15167 ROSE_ASSERT(namelist.size() > 0);
15168
15169 SgInitializedNamePtrList::iterator i;
15170 for (i = namelist.begin(); i != namelist.end(); i++)
15171 {
15172 SgInitializedName *initName = *i;
15173 ROSE_ASSERT(initName != NULL);
15174
15175 SgName name = initName->get_name();
15176#if 0
15177 printf (" -- initName = %p : %s\n", initName, name.str());
15178 printf (" -- initName->get_scope() = %p (%s)\n", initName->get_scope(), initName->get_scope() ? initName->get_scope()->class_name().c_str() : "");
15179#endif
15180
15181 // DQ (11/19/2011): When used with C++, the variable may already have an associated scope
15182 // and be using name qualification, so might not be associated with the current scope.
15183 SgScopeStatement* requiredScope = scope;
15184 SgScopeStatement* preAssociatedScope = initName->get_scope();
15185 // printf ("In SageInterface::fixVariableDeclaration() preAssociatedScope = %p \n",preAssociatedScope);
15186
15187 if (preAssociatedScope != NULL)
15188 {
15189#if 0
15190 printf ("In SageInterface::fixVariableDeclaration(): Note that this variable already has an associated scope! preAssociatedScope = %p = %s (but will be reset below) \n",preAssociatedScope,preAssociatedScope->class_name().c_str());
15191#endif
15192 // ROSE_ASSERT(preAssociatedScope == scope);
15193 requiredScope = preAssociatedScope;
15194 }
15195
15196 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15197 // initName->set_scope(scope);
15198 initName->set_scope(requiredScope);
15199
15200 // optional?
15201 // DQ (7/9/2012): Don't set this since it will be set later (see test2012_107.C) (LATER) Putting this back (mark declarations to not be output as compiler generated -- and not to be output).
15202 // DQ (7/12/2012): This is not correct for C++, so don't set it here (unless we use the current scope instead of scope).
15203 // Yes, let's set it to the current top of the scope stack. This might be a problem if the scope stack is not being used...
15204 // varDecl->set_parent(scope);
15205 if (topScopeStack() != NULL)
15206 {
15207 varDecl->set_parent(topScopeStack());
15208 ROSE_ASSERT(varDecl->get_parent() != NULL);
15209 }
15210
15211 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15212 // symbol table
15213 // ROSE_ASSERT(scope != NULL);
15214 // SgVariableSymbol* varSymbol = scope->lookup_variable_symbol(name);
15215 ROSE_ASSERT(requiredScope != NULL);
15216 SgVariableSymbol* varSymbol = requiredScope->lookup_variable_symbol(name);
15217#if 0
15218 printf (" -- varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15219#endif
15220
15221 if (varSymbol == NULL)
15222 {
15223 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15224 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15225 if (scope == initName->get_scope())
15226 {
15227 if (isSgTemplateVariableDeclaration(varDecl)) {
15228 varSymbol = new SgTemplateVariableSymbol(initName);
15229 } else {
15230 varSymbol = new SgVariableSymbol(initName);
15231 }
15232 ROSE_ASSERT(varSymbol);
15233
15234 // DQ (5/16/2013): We now want to use the SgScopeStatement::insert_symbol() functions since we put
15235 // the complexity of handling namespaces into the implementation of that function.
15236 scope->insert_symbol(name, varSymbol);
15237 }
15238 }
15239 else
15240 {
15241 // TODO consider prepend() and insert(), prev_decl_time is position dependent.
15242 // cout<<"sageInterface.C:5130 debug: found a previous var declaration!!...."<<endl;
15243 SgInitializedName* prev_decl = varSymbol->get_declaration();
15244 ROSE_ASSERT(prev_decl);
15245
15246 // DQ (11/19/2011): Don't let prev_decl_item point be a self reference.
15247 // initName->set_prev_decl_item(prev_decl);
15248 if (initName != prev_decl)
15249 initName->set_prev_decl_item(prev_decl);
15250
15251 ROSE_ASSERT(initName->get_prev_decl_item() != initName);
15252
15253 } //end if
15254 } //end for
15255
15256 // Liao 12/8/2010
15257 // For Fortran, a common statement may refer to a variable which is declared later.
15258 // In this case, a fake symbol is used for that variable reference.
15259 // But we have to replace the fake one with the real one once the variable declaration is inserted into AST
15261 {
15262 fixVariableReferences(scope);
15263 }
15264 }
15265
15266int SageInterface::fixVariableReferences(SgNode* root, bool cleanUnusedSymbols/*=true*/)
15267{
15268 ROSE_ASSERT(root);
15269 int counter=0;
15270 Rose_STL_Container<SgNode*> varList;
15271
15272 SgVarRefExp* varRef=NULL;
15273 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(root, V_SgVarRefExp);
15274 for (Rose_STL_Container<SgNode*>::iterator i=reflist.begin();i!=reflist.end();i++)
15275 {
15276 varRef= isSgVarRefExp(*i);
15277 ROSE_ASSERT(varRef->get_symbol());
15278 SgInitializedName* initname= varRef->get_symbol()->get_declaration();
15279
15280 ROSE_ASSERT (initname != NULL);
15281 if (initname->get_type()==SgTypeUnknown::createType())
15282 {
15283 SgName varName=initname->get_name();
15284 SgSymbol* realSymbol = NULL;
15285
15286#if 1
15287 // CH (5/7/2010): Before searching SgVarRefExp objects, we should first deal with class/structure
15288 // members. Or else, it is possible that we assign the wrong symbol to those members if there is another
15289 // variable with the same name in parent scopes. Those members include normal member referenced using . or ->
15290 // operators, and static members using :: operators.
15291 //
15292 if (SgArrowExp* arrowExp = isSgArrowExp(varRef->get_parent()))
15293 {
15294 if (varRef == arrowExp->get_rhs_operand_i())
15295 {
15296 // make sure the lhs operand has been fixed
15297 counter += fixVariableReferences(arrowExp->get_lhs_operand_i());
15298 SgType* lhs_type = arrowExp->get_lhs_operand_i()->get_type() ;
15299 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15300 SgPointerType* ptrType = isSgPointerType(lhs_type);
15301 ROSE_ASSERT(ptrType);
15302 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));
15303 ROSE_ASSERT(clsType);
15304 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15305 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15306 ROSE_ASSERT(decl);
15307
15308 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15309 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15310 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15311 }
15312 else
15313 {
15314 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15315 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15316 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15317 }
15318 }
15319 else if (SgDotExp* dotExp = isSgDotExp(varRef->get_parent()))
15320 {
15321 if (varRef == dotExp->get_rhs_operand_i())
15322 {
15323 // make sure the lhs operand has been fixed
15324 counter += fixVariableReferences(dotExp->get_lhs_operand_i());
15325
15326 SgType* lhs_type = dotExp->get_lhs_operand_i()->get_type() ;
15327 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15328 SgClassType* clsType = isSgClassType(lhs_type);
15329 ROSE_ASSERT(clsType);
15330 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15331 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15332 ROSE_ASSERT(decl);
15333
15334 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15335 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15336 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15337 }
15338 else
15339 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15340 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15341 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15342 }
15343 else
15344#endif
15345 {
15346 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15347 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15348 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15349 }
15350
15351 // should find a real symbol at this final fixing stage!
15352 // This function can be called any time, not just final fixing stage
15353 if (realSymbol==NULL)
15354 {
15355 //cerr<<"Error: cannot find a symbol for "<<varName.getString()<<endl;
15356 //ROSE_ASSERT(realSymbol);
15357 }
15358 else {
15359 // release placeholder initname and symbol
15360 ROSE_ASSERT(realSymbol!=(varRef->get_symbol()));
15361#if 0
15362 // CH (5/12/2010):
15363 // To delete a symbol node, first check if there is any node in memory
15364 // pool which points to this symbol node. Only if no such node exists,
15365 // this symbol together with its initialized name can be deleted.
15366 //
15367 bool toDelete = true;
15368
15369 SgSymbol* symbolToDelete = varRef->get_symbol();
15370 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15371 counter ++;
15372
15373 if (varList.empty())
15374 {
15375 VariantVector vv(V_SgVarRefExp);
15376 varList = NodeQuery::queryMemoryPool(vv);
15377 }
15378
15379 for (Rose_STL_Container<SgNode*>::iterator i = varList.begin();
15380 i != varList.end(); ++i)
15381 {
15382 if (SgVarRefExp* var = isSgVarRefExp(*i))
15383 {
15384 if (var->get_symbol() == symbolToDelete)
15385 {
15386 toDelete = false;
15387 break;
15388 }
15389 }
15390 }
15391 if (toDelete)
15392 {
15393 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15394 delete symbolToDelete;
15395 }
15396
15397#else
15398
15399 // CH (2010/7/26): We cannot delete those initname and symbol here, since there may be other variable references
15400 // which point to them. We will delay this clear just before AstTests.
15401#if 0
15402 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15403 delete (varRef->get_symbol());
15404#endif
15405
15406 //std::cout << "Fixed variable reference: " << realSymbol->get_name().str() << std::endl;
15407 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15408 counter ++;
15409#endif
15410 }
15411 }
15412 } // end for
15413 // Liao 2/1/2013: delete unused initname and symbol, considering possible use by the current subtree from root node
15414 if (cleanUnusedSymbols)
15416 return counter;
15417}
15418
15420{
15421 Rose_STL_Container<SgNode*> symbolList;
15422 VariantVector sym_vv(V_SgVariableSymbol);
15423 symbolList = NodeQuery::queryMemoryPool(sym_vv);
15424
15425 Rose_STL_Container<SgNode*> varList;
15426 VariantVector var_vv(V_SgVarRefExp);
15427 //varList = NodeQuery::queryMemoryPool(var_vv);
15428 if (root != NULL)
15429 {
15430 varList = NodeQuery::querySubTree(root, V_SgVarRefExp);
15431 }
15432
15433 for (Rose_STL_Container<SgNode*>::iterator i = symbolList.begin();
15434 i != symbolList.end(); ++i)
15435 {
15436 SgVariableSymbol* symbolToDelete = isSgVariableSymbol(*i);
15437 ROSE_ASSERT(symbolToDelete);
15438 if (symbolToDelete->get_declaration()->get_type() != SgTypeUnknown::createType())
15439 continue;
15440 // symbol with a declaration of SgTypeUnknown will be deleted
15441 bool toDelete = true;
15442
15443 if (root != NULL) // if root is specified. We further check if the symbol is referenced by any nodes of the tree rooted at "root"
15444 {
15445 for (Rose_STL_Container<SgNode*>::iterator j = varList.begin();
15446 j != varList.end(); ++j)
15447 {
15448 SgVarRefExp* var = isSgVarRefExp(*j);
15449 ROSE_ASSERT(var);
15450
15451 if (var->get_symbol() == symbolToDelete)
15452 {
15453 toDelete = false;
15454 break;
15455 }
15456 }
15457 }
15458
15459 if (toDelete)
15460 {
15461#if 0
15462 std::cout << "Symbol " << symbolToDelete->get_name().str() << ' ' << symbolToDelete <<
15463 ' ' << symbolToDelete->get_declaration() << " is deleted." << std::endl;
15464#endif
15465 delete symbolToDelete->get_declaration();
15466 delete symbolToDelete;
15467 }
15468 }
15469}
15470
15471
15473/*
15474 * label statement has special scope: the closest function definition , not SgBasicBlock or others!
15475 */
15477 {
15478 SgLabelStatement* label_stmt = isSgLabelStatement(stmt);
15479 ROSE_ASSERT(label_stmt);
15480 SgName name = label_stmt->get_label();
15481
15482 // PP (07/18/23): In Ada, label symbols should be inserted in the current scope's symbol table
15483 const bool symbolAtFunctionLevel = !is_Ada_language();
15484 SgScopeStatement* label_scope = symbolAtFunctionLevel ? getEnclosingFunctionDefinition(scope,true)
15485 : scope;
15486
15487 // DQ (11/16/2014): Added error checking for when the input scope is the SgFunctionDefinition instead of a nested scope.
15488 if (isSgFunctionDefinition(scope) != nullptr)
15489 {
15490 ASSERT_not_null(label_scope);
15491 }
15492
15493 if (label_scope) //Should we assert this instead? No for bottom up AST building
15494 {
15495 label_stmt->set_scope(label_scope);
15496 SgLabelSymbol* lsymbol = label_scope->lookup_label_symbol(name);
15497
15498 if (lsymbol == nullptr)
15499 {
15500 // SgLabelStatement should always be in the function scope
15501 // PP (07/18/23): in Ada symbols should be at the innermost scope
15502 lsymbol= new SgLabelSymbol(label_stmt);
15503 ASSERT_not_null(lsymbol);
15504 label_scope->insert_symbol(lsymbol->get_name(), lsymbol);
15505 }
15506 }
15507 }
15508
15509
15511//efExp are created transparently as needed.
15513 SgLabelSymbol::label_type_enum label_type, SgScopeStatement* label_scope)
15514 {
15515 ROSE_ASSERT (stmt != NULL);
15516 ROSE_ASSERT (label_value >0 && label_value <=99999); //five digits for Fortran label
15517
15518 // Added optional label_type and label_scope [Rasmussen 2019.01.20]
15519 if (label_scope == NULL)
15520 {
15521 label_scope = getEnclosingFunctionDefinition(stmt);
15522 }
15523 ROSE_ASSERT (label_scope != NULL);
15524 SgName label_name(StringUtility::numberToString(label_value));
15525 SgLabelSymbol * symbol = label_scope->lookup_label_symbol (label_name);
15526 if (symbol == NULL)
15527 {
15528 // DQ (12/4/2011): This is the correct handling for SgLabelStatement (always in the function scope, same as C and C++).
15529 // DQ (2/2/2011): We want to call the old constructor (we now have another constructor that takes a SgInitializedName pointer).
15530 // symbol = new SgLabelSymbol(NULL);
15531 symbol = new SgLabelSymbol((SgLabelStatement*) NULL);
15532 ROSE_ASSERT(symbol != NULL);
15533 symbol->set_fortran_statement(stmt);
15534 symbol->set_numeric_label_value(label_value);
15535 label_scope->insert_symbol(label_name,symbol);
15536 }
15537 else
15538 {
15539 cerr<<"Error. SageInterface::setFortranNumericLabel() tries to set a duplicated label value!"<<endl;
15540 ROSE_ASSERT (false);
15541 }
15542
15543 // SgLabelRefExp
15544 SgLabelRefExp* ref_exp = buildLabelRefExp(symbol);
15545 ref_exp->set_parent(stmt);
15546
15547 switch(label_type)
15548 {
15549 case SgLabelSymbol::e_start_label_type:
15550 {
15551 stmt->set_numeric_label(ref_exp);
15552 break;
15553 }
15554 case SgLabelSymbol::e_end_label_type:
15555 {
15556 stmt->set_end_numeric_label(ref_exp);
15557 break;
15558 }
15559 default:
15560 {
15561 std::cerr << "SageInterface::setFortranNumericLabel: unimplemented for label_type " << label_type << "\n";
15562 ROSE_ABORT(); // NOT IMPLEMENTED
15563 }
15564 }
15565
15566 }
15567
15568
15571{
15572 int result =10;
15573 ROSE_ASSERT (func_def != NULL);
15574 ROSE_ASSERT (SageInterface::is_Fortran_language()== true);
15575 std::set<SgNode*> symbols = func_def->get_symbol_table()->get_symbols();
15576
15577 // find the max label value, +10 to be the suggested next label value
15578 std::set<SgNode*>::iterator iter ;
15579 for (iter=symbols.begin(); iter !=symbols.end(); iter++)
15580 {
15581 SgLabelSymbol * l_symbol = isSgLabelSymbol(*iter);
15582 if (l_symbol)
15583 {
15584 int cur_val = l_symbol->get_numeric_label_value();
15585 if (result <=cur_val)
15586 result = cur_val +10;
15587 }
15588 }
15589
15590 ROSE_ASSERT (result <= 99999); // max 5 digits for F77 label
15591 return result;
15592}
15593
15595/*
15596 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15597 */
15599 {
15600 // DQ (3/5/2012): Added test.
15601 ROSE_ASSERT(scope != NULL);
15602
15603 // fix function type table's parent edge
15604 // Liao 5/4/2010
15606 ROSE_ASSERT(fTable != NULL);
15607
15608 if (fTable->get_parent() == NULL)
15609 {
15610 // DQ (3/5/2012): This is a problem for test2012_13.C (test code taken from test2004_42.C).
15611 // fTable->set_parent(getGlobalScope(scope));
15612#if 0
15613 printf ("WARNING: Skip setting the scope of the SgFunctionTypeTable scope = %p = %s \n",scope,scope->class_name().c_str());
15614#endif
15615 fTable->set_parent(getGlobalScope(scope));
15616 }
15617
15618#if 0
15619 printf ("In SageInterface::fixStatement(): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15620#endif
15621
15622 // Liao 4/23/2010, Fix function symbol
15623 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15624 // Added SgProgramHeaderStatement [Rasmussen, 2020.01.19]
15625 SgFunctionDeclaration * func = isSgFunctionDeclaration(stmt);
15626 SgMemberFunctionDeclaration * mfunc = isSgMemberFunctionDeclaration(stmt);
15627 SgTemplateFunctionDeclaration * tfunc = isSgTemplateFunctionDeclaration(stmt);
15628 SgTemplateMemberFunctionDeclaration * tmfunc = isSgTemplateMemberFunctionDeclaration(stmt);
15629 SgProcedureHeaderStatement * procfunc = isSgProcedureHeaderStatement(stmt);
15630 SgProgramHeaderStatement * progfunc = isSgProgramHeaderStatement(stmt);
15631
15632 if (tmfunc != NULL)
15633 assert(tmfunc->variantT() == V_SgTemplateMemberFunctionDeclaration);
15634 else if (mfunc != NULL)
15635 assert(mfunc->variantT() == V_SgMemberFunctionDeclaration || mfunc->variantT() == V_SgTemplateInstantiationMemberFunctionDecl);
15636 else if (tfunc != NULL)
15637 assert(tfunc->variantT() == V_SgTemplateFunctionDeclaration);
15638 else if (procfunc != NULL)
15639 assert(procfunc->variantT() == V_SgProcedureHeaderStatement);
15640 else if (progfunc != NULL)
15641 assert(progfunc->variantT() == V_SgProgramHeaderStatement);
15642 else if (func != NULL)
15643 assert(func->variantT() == V_SgFunctionDeclaration || func->variantT() == V_SgTemplateInstantiationFunctionDecl);
15644 else ROSE_ABORT();
15645
15646#if 0
15647 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15648 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15649#endif
15650
15651 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15652 // It is an error to put the symbol for a function into the current scope if the function's scope
15653 // is explicitly set to be different. So this should be allowed only if the function's scope is
15654 // not explicitly set, or if the scopes match. This is an example of something different for C++
15655 // than for C or other simpler languages.
15656 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15657 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15658 {
15659#if 0
15660 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());
15661#endif
15662 SgFunctionSymbol* func_symbol = NULL;
15663
15664 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
15665 // In this case these are unavailable from this point.
15666 if (tmfunc != NULL)
15667 {
15668 SgTemplateParameterPtrList & templateParameterList = tmfunc->get_templateParameters();
15669 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type());
15670 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),NULL);
15671 func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15672 }
15673 else if (mfunc != NULL)
15674 {
15675 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(mfunc);
15676 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationMemberFunctionDecl != NULL) ? &(templateInstantiationMemberFunctionDecl->get_templateArguments()) : NULL;
15677 // func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),NULL);
15678 func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15679 }
15680 else if (tfunc != NULL)
15681 {
15682 SgTemplateParameterPtrList & templateParameterList = tfunc->get_templateParameters();
15683#if 0
15684 printf ("In SageInterface::fixStatement(): templateParameterList.size() = %" PRIuPTR " \n",templateParameterList.size());
15685#endif
15686 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type());
15687 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),NULL);
15688 func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15689 }
15690 else if (procfunc != NULL)
15691 {
15692#if 0
15693 printf ("In SageInterface::fixStatement(): procfunc->get_name() = %s calling lookup_function_symbol() \n",procfunc->get_name().str());
15694#endif
15695 func_symbol = scope->lookup_function_symbol (procfunc->get_name(), procfunc->get_type());
15696 assert(func_symbol != NULL);
15697 }
15698 else if (progfunc != NULL)
15699 {
15700 func_symbol = scope->lookup_function_symbol (progfunc->get_name(), progfunc->get_type());
15701 assert(func_symbol != NULL);
15702 }
15703 else if (func != NULL)
15704 {
15705#if 0
15706 printf ("In SageInterface::fixStatement(): func->get_name() = %s calling lookup_function_symbol() \n",func->get_name().str());
15707#endif
15708 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(func);
15709 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationFunctionDecl != NULL) ? &(templateInstantiationFunctionDecl->get_templateArguments()) : NULL;
15710 // func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),NULL);
15711 func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15712
15713 // 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
15714 // 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
15715 // opportunity to fixup the function to have a symbol in the scope's symbol table.
15716 if (func_symbol == NULL)
15717 {
15718 // scope->print_symboltable("In SageInterface::fixStatement()");
15719 func_symbol = new SgFunctionSymbol(func);
15720 scope->insert_symbol(func->get_name(), func_symbol);
15721 }
15722 }
15723 else
15724 {
15725 ROSE_ABORT();
15726 }
15727#if 0
15728 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15729#endif
15730 assert(func_symbol != NULL);
15731 }
15732 }
15733
15735/*
15736 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15737 */
15739 {
15740 // DQ (12/4/2011): This function has not been implemented yet. It will assert fail if it is required.
15741 printf ("Need to handle SgTemplateDeclaration IR nodes as well...(implement later) \n");
15742 }
15743
15744
15747 {
15748 // fix symbol table
15749 if (isSgVariableDeclaration(stmt))
15750 {
15751 fixVariableDeclaration(isSgVariableDeclaration(stmt), scope);
15752 }
15753 else if (isStructDeclaration(stmt))
15754 {
15755 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
15756 ROSE_ASSERT(classDeclaration != nullptr);
15757 fixStructDeclaration(classDeclaration,scope);
15758 }
15759 else if (isSgClassDeclaration(stmt))
15760 {
15761 fixClassDeclaration(isSgClassDeclaration(stmt),scope);
15762 }
15763 else if (isSgLabelStatement(stmt))
15764 {
15765 fixLabelStatement(isSgLabelStatement(stmt),scope);
15766 }
15767 else if (isSgFunctionDeclaration(stmt))
15768 {
15769#if 1
15770 fixFunctionDeclaration(isSgFunctionDeclaration(stmt),scope);
15771#else
15772 // fix function type table's parent edge
15773 // Liao 5/4/2010
15775 ROSE_ASSERT(fTable);
15776 if (fTable->get_parent() == NULL)
15777 fTable->set_parent(getGlobalScope(scope));
15778
15779 // Liao 4/23/2010, Fix function symbol
15780 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15781 SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt);
15782 SgMemberFunctionDeclaration* mfunc = isSgMemberFunctionDeclaration(stmt);
15783
15784 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15785 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15786
15787 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15788 // It is an error to put the symbol for a function into the current scope if the function's scope
15789 // is explicitly set to be different. So this should be allowed only if the function's scope is
15790 // not explicitly set, or if the scopes match. This is an example of something different for C++
15791 // than for C or other simpler languages.
15792 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15793 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15794 {
15795#if 0
15796 printf ("Looking up the function symbol using name = %s and type = %p = %s \n",func->get_name().str(),func->get_type(),func->get_type()->class_name().c_str());
15797#endif
15798 SgFunctionSymbol* func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type());
15799
15800 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15801 if (func_symbol == NULL)
15802 {
15803 // DQ (12/3/2011): Added support for C++ member functions.
15804 // func_symbol = new SgFunctionSymbol (func);
15805 if (mfunc != NULL)
15806 {
15807 func_symbol = new SgMemberFunctionSymbol (func);
15808 }
15809 else
15810 {
15811 func_symbol = new SgFunctionSymbol (func);
15812 }
15813 ROSE_ASSERT (func_symbol != NULL);
15814
15815 scope->insert_symbol(func->get_name(), func_symbol);
15816 }
15817 else
15818 {
15819 printf ("In SageInterface::fixStatement(): found a valid function so no need to insert new symbol \n");
15820 }
15821 }
15822#if 0
15823 // Fix local symbol, a symbol directly refer to this function declaration
15824 // This could happen when a non-defining func decl is copied, the corresonding symbol will point to the original source func
15825 // symbolTable->find(this) used inside get_symbol_from_symbol_table() won't find the copied decl
15826 SgSymbol* local_symbol = func ->get_symbol_from_symbol_table();
15827 if (local_symbol == NULL) //
15828 {
15829 if (func->get_definingDeclaration() == NULL) // prototype function
15830 {
15831 SgFunctionDeclaration * src_func = func_symbol->get_declaration();
15832 if (func != src_func )
15833 {
15834 ROSE_ASSERT (src_func->get_firstNondefiningDeclaration () == src_func);
15835 func->set_firstNondefiningDeclaration (func_symbol->get_declaration());
15836 }
15837 }
15838 }
15839#endif
15840#endif
15841 }
15842 else if (isSgTemplateDeclaration(stmt) != NULL)
15843 {
15844 // DQ (12/3/2011): Added new case for SgTemplateDeclaration (adding template declarations to the AST).
15845 fixTemplateDeclaration(isSgTemplateDeclaration(stmt),scope);
15846 }
15847
15848#if 0
15849 // DQ (12/4/2011): This WAS not the correct behavior for C++ since declarations can appear structureally in different
15850 // scopes than where the are positioned (e.g. member functions defined outside of there associated class).
15851 // This this code is very dangerous.
15852
15853 // fix scope pointer for statements explicitly storing scope pointer
15854 switch (stmt->variantT())
15855 {
15856 // The case of SgLabelStatement should maybe be included.
15857 case V_SgEnumDeclaration:
15858 case V_SgTemplateDeclaration:
15859 case V_SgTypedefDeclaration:
15860 case V_SgFunctionDeclaration:
15861 case V_SgMemberFunctionDeclaration:
15862 case V_SgTemplateInstantiationFunctionDecl:
15863 {
15864 // DQ (12/4/2011): We can't just set the scope this simily (except in C). In C++ the scope should have
15865 // already been set or we can let it default to the current scope where it si located structurally.
15866 // stmt->set_scope(scope);
15867 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
15868 {
15869 stmt->set_scope(scope);
15870 }
15871 break;
15872 }
15873
15874 default:
15875 {
15876 // debugging support...
15877 printf ("In SageInterface::fixStatement(): switch default case used (likely OK): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15878 ROSE_ASSERT(stmt->hasExplicitScope() == false);
15879#if 0
15880 printf ("switch case not handled properly: stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15881 ROSE_ABORT();
15882#endif
15883 break;
15884 }
15885 }
15886#else
15887 // If the scoep has to be set and it has not yet been set, then set it directly.
15888 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
15889 {
15890 stmt->set_scope(scope);
15891 }
15892#endif
15893 }
15894
15895
15908 {
15909 // DQ (11/19/2012): Note that this appears to be an expensive function presently taking 22.5% of the total time
15910 // to process the tests/CompilerTests/Cxx_tests/rosePerformance.C file. So this is a performance problem.
15911
15912 ROSE_ASSERT(func != NULL && scope != NULL);
15913
15914 ROSE_ASSERT(func != NULL);
15915 ROSE_ASSERT(scope != NULL);
15916
15917 SgStatementPtrList stmtList, sameFuncList;
15918
15919 // SgFunctionDeclaration* first_nondef = NULL;
15920 // Some annoying part of scope
15921 if (scope->containsOnlyDeclarations())
15922 {
15923 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
15924 SgDeclarationStatementPtrList::iterator i;
15925 for (i=declList.begin();i!=declList.end();i++)
15926 stmtList.push_back(*i);
15927 }
15928 else
15929 {
15930 stmtList = scope->getStatementList();
15931 }
15932
15933 SgFunctionDeclaration* firstNondefiningFunctionDeclaration = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
15934 if (firstNondefiningFunctionDeclaration != NULL)
15935 {
15936 // If there exists a non-NULL reference to a firstNondefiningFunctionDeclaration
15937 // then use it (unless we want to handle where it might be set wrong).
15938#if 0
15939 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid pointer to a firstNondefiningFunctionDeclaration = %p \n",func,firstNondefiningFunctionDeclaration);
15940#endif
15941 }
15942
15943 // DQ (3/12/2012): Added assertion
15944 // ROSE_ASSERT(scope == func->get_firstNondefiningDeclaration()->get_scope());
15945 ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope() != NULL);
15946
15947 // 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.
15948 if (func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) == NULL)
15949 {
15950 printf ("WARNING: symbol for func->get_firstNondefiningDeclaration() = %p = %s = %s is not present in the scope = %p = %s associated with the firstNondefiningDeclaration \n",
15951 func->get_firstNondefiningDeclaration(),func->get_firstNondefiningDeclaration()->class_name().c_str(),func->get_name().str(),
15953 }
15954 // ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) != NULL);
15955
15956#if 0
15957 // It would be better to find the first non-defining declaration via the symbol.
15958 SgSymbol* functionSymbol = scope->lookup_function_symbol(func->get_name(),func->get_type());
15959 if (functionSymbol != NULL)
15960 {
15961 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid symbol = %p \n",func,functionSymbol);
15962 }
15963 else
15964 {
15965 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p functionSymbol == NULL \n",func);
15966 }
15967#endif
15968
15969 // Find the same function declaration list, including func itself
15970 SgStatementPtrList::iterator j;
15971 for (j = stmtList.begin(); j != stmtList.end(); j++)
15972 {
15973 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
15974 if (func_decl != NULL)
15975 {
15976 // DQ (11/19/2012): This call to the isSameFunction() function is taking a total of 22.1%
15977 // of the total execution time of the tests/CompilerTests/Cxx_tests/rosePerformance.C file.
15978 if (isSameFunction(func_decl, func))
15979 {
15980 // Assume all defining functions have definingdeclaration links set properly already!!
15981 sameFuncList.push_back(func_decl);
15982 }
15983 }
15984 }
15985
15986#if 0
15987 printf ("func = %p \n",func);
15988 printf ("func->get_definingDeclaration() = %p \n",func->get_definingDeclaration());
15989#endif
15990
15991 ROSE_ASSERT(func != NULL);
15992
15993 if (func->get_definingDeclaration() == func)
15994 {
15995 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
15996 isSgFunctionDeclaration(*j)->set_definingDeclaration(func);
15997 }
15998 else
15999 {
16000 ROSE_ASSERT(func != NULL);
16001
16002 // DQ (3/9/2012): Added assertion to avoid empty list that would be an error in both cases below.
16003 ROSE_ASSERT(sameFuncList.empty() == false);
16004
16005 if (func == isSgFunctionDeclaration(*(sameFuncList.begin()))) // is first_nondefining declaration
16006 {
16007 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16008 {
16009 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16010#if 0
16011 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Testing j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16012#endif
16013 // DQ (3/9/2012): Avoid setting the function to be it's own firstNondefiningDeclaration.
16014 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16015 if (func_decl != func)
16016 {
16017 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16018 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16019 if (func_decl->get_firstNondefiningDeclaration() == NULL)
16020 {
16021#if 0
16022 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Calling j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16023#endif
16024 func_decl->set_firstNondefiningDeclaration(func);
16025 }
16026 }
16027 }
16028 }
16029 else // is a following nondefining declaration, grab any other's first nondefining link then
16030 {
16031#if 0
16032 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Testing func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16033#endif
16034 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16035 // func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16036 if (func->get_firstNondefiningDeclaration() == NULL)
16037 {
16038#if 0
16039 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Calling func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16040#endif
16041 func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16042 }
16043 }
16044 }
16045 }
16046
16047PreprocessingInfo* SageInterface::attachComment(SgSourceFile * source_file, const std::string & content, PreprocessingInfo::DirectiveType directive_type, PreprocessingInfo::RelativePositionType position) {
16048 assert(source_file != NULL);
16049 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16050
16051 SgGlobal * global_scope = source_file->get_globalScope();
16052
16053 PreprocessingInfo* result = new PreprocessingInfo(directive_type, content, "Transformation generated",0, 0, 0, position);
16054 ROSE_ASSERT(result);
16055
16056 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16057 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16058 // when multiple files are used on the command line.
16059 result->get_file_info()->setTransformation();
16060
16061 global_scope->addToAttachedPreprocessingInfo(result, position);
16062
16063 return result;
16064}
16065
16066//---------------------------------------------------------------
16068 SgLocatedNode* target, const string& content,
16069 PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/,
16070 PreprocessingInfo::DirectiveType dtype /* PreprocessingInfo::CpreprocessorUnknownDeclaration */)
16071 {
16072 ASSERT_not_null(target); //dangling comment is not allowed
16073
16074 PreprocessingInfo* result = NULL;
16075 PreprocessingInfo::DirectiveType mytype=dtype;
16076 string comment;
16077
16078 // Rasmussen (11/3/2020): Added Ada and Jovial style comments
16079 // DQ (5/5/2010): infer comment type from target's language
16080 if (mytype == PreprocessingInfo::CpreprocessorUnknownDeclaration)
16081 {
16082 // This is a rather expensive way to detect the language type (chases pointers back to the SgFile object).
16083 if (is_C_language() || is_C99_language())
16084 {
16085 // Comment = "/* "+ content + " */";
16086 mytype = PreprocessingInfo::C_StyleComment;
16087 }
16088 else if (is_Cxx_language() || is_Java_language())
16089 {
16090 // Comment = "// "+ content;
16091 mytype = PreprocessingInfo::CplusplusStyleComment;
16092 }
16093 else if (is_Fortran_language() || is_CAF_language()) //FMZ:3/23/2009
16094 {
16095 // Comment = "! "+ content;
16096 mytype = PreprocessingInfo::F90StyleComment;
16097 }
16098 else if (is_Ada_language())
16099 {
16100 // Comment = "-- " + content;
16101 mytype = PreprocessingInfo::AdaStyleComment;
16102 }
16103 else if (is_Jovial_language())
16104 {
16105 // Comment = "% " + content + " %";
16106 mytype = PreprocessingInfo::JovialStyleComment;
16107 }
16108 else
16109 {
16110 cout << "WARNING: SageInterface::attachComment(): Unknown programming language \n";
16111 ROSE_ABORT();
16112 }
16113 }
16114
16115 // Once the langauge type is set (discovered automatically or more directly specified by the user).
16116 bool resetPositionInfo = false;
16117 switch (mytype)
16118 {
16119 case PreprocessingInfo::C_StyleComment: comment = "/* " + content + " */"; break;
16120 case PreprocessingInfo::CplusplusStyleComment: comment = "// " + content; break;
16121 case PreprocessingInfo::FortranStyleComment: comment = " C " + content; break;
16122 case PreprocessingInfo::F90StyleComment: comment = "!" + content; break;
16123 case PreprocessingInfo::AdaStyleComment: comment = "-- " + content; break;
16124 case PreprocessingInfo::JovialStyleComment:
16125 // The Jovial comment content will already have the comment delimiters, '%' or '"'
16126 comment = content;
16127 break;
16128 case PreprocessingInfo::CpreprocessorLineDeclaration:
16129 comment = "#myline " + content;
16130 mytype = PreprocessingInfo::CplusplusStyleComment;
16131 resetPositionInfo = true;
16132 break;
16133 case PreprocessingInfo::CpreprocessorIfndefDeclaration: comment = "#ifndef " + content + "\n"; break;
16134 case PreprocessingInfo::CpreprocessorDefineDeclaration: comment = "#define " + content + "\n"; break;
16135 case PreprocessingInfo::CpreprocessorEndifDeclaration: comment = "#endif" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16136 case PreprocessingInfo::CpreprocessorEnd_ifDeclaration: comment = "#end if" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16137
16138 default:
16139 {
16140 printf ("Error: default in switch reached in SageInterface::attachComment() PreprocessingInfo::DirectiveType == %d \n",mytype);
16141 ROSE_ABORT();
16142 }
16143 }
16144
16145 result = new PreprocessingInfo (mytype,comment, "transformation-generated", 0, 0, 0, position);
16146
16147 // If this is a Cpp Line declaration then we have to set the position to match the statement.
16148 if (resetPositionInfo == true)
16149 {
16150 // Call the Sg_File_Info::operator=() member function.
16151 *(result->get_file_info()) = *(target->get_file_info());
16152 }
16153 else
16154 {
16155 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16156 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16157 // when multiple files are used on the command line.
16158 result->get_file_info()->setTransformation();
16159 }
16160
16161 ASSERT_not_null(result);
16162 target->addToAttachedPreprocessingInfo(result);
16163 return result;
16164 }
16165
16166void SageInterface::guardNode(SgLocatedNode * target, std::string guard) {
16167 PreprocessingInfo * if_macro = new PreprocessingInfo(
16168 PreprocessingInfo::CpreprocessorIfDeclaration,
16169 "#if " + guard,
16170 "transformation-generated", 0, 0, 0,
16171 PreprocessingInfo::before
16172 );
16173 target->addToAttachedPreprocessingInfo(if_macro);
16174
16175 PreprocessingInfo * endif_macro = new PreprocessingInfo(
16176 PreprocessingInfo::CpreprocessorEndifDeclaration,
16177 "#endif",
16178 "transformation-generated", 0, 0, 0,
16179 PreprocessingInfo::after
16180 );
16181 target->addToAttachedPreprocessingInfo(endif_macro);
16182
16183// DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16184// This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16185// when multiple files are used on the command line.
16186 if_macro->get_file_info()->setTransformation();
16187 endif_macro->get_file_info()->setTransformation();
16188}
16189
16190// internal hash table to cache the results: fileHeaderDict[file][header-key]
16191// header-key:
16192// system header : <header.h>
16193// non-system headers : "header.h"
16194static map<SgSourceFile*, map<string, PreprocessingInfo*> > fileHeaderDict;
16196PreprocessingInfo * SageInterface::findHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader)
16197{
16198 string header_key;
16199 if (isSystemHeader)
16200 header_key="<"+header_file_name+">";
16201 else
16202 header_key="\""+header_file_name+"\"";
16203
16204 if (fileHeaderDict.count(source_file) && fileHeaderDict[source_file].count(header_key))
16205 return fileHeaderDict[source_file][header_key];
16206
16207 vector<SgLocatedNode*> candidates;
16208 // do a fresh check. we only check global scope's declarations since we insert header into global scope
16209 // check SgGlobal
16210 SgGlobal* global= source_file -> get_globalScope();
16211
16212 candidates.push_back(global);
16213
16214 //check declarations within the global scope
16215 SgDeclarationStatementPtrList decl_stmt_list = global->get_declarations();
16216 for (SgDeclarationStatementPtrList::iterator iter= decl_stmt_list.begin(); iter!=decl_stmt_list.end(); iter++)
16217 candidates.push_back(*iter);
16218
16219 bool found = false;
16220 for (size_t ci=0; ci<candidates.size(); ci++)
16221 {
16222 SgLocatedNode* locatedNode= candidates[ci];
16223 AttachedPreprocessingInfoType *comments = locatedNode->getAttachedPreprocessingInfo ();
16224
16225 if (comments == NULL) continue;
16226 AttachedPreprocessingInfoType::iterator i;
16227 for (i = comments->begin (); i != comments->end (); i++)
16228 {
16229 if ((*i)->getTypeOfDirective () != PreprocessingInfo::CpreprocessorIncludeDeclaration) continue;
16230 string content = (*i)->getString ();
16231 if (content.find(header_key) != string::npos)
16232 {
16233 fileHeaderDict[source_file][header_key] = *i;
16234 found =true;
16235 break;
16236 }
16237
16238 } // each comment
16239
16240 if (found) break;
16241 } // each node
16242
16243 if (found)
16244 return fileHeaderDict[source_file][header_key];
16245 return NULL;
16246}
16247
16249SageInterface::insertHeader(SgSourceFile * source_file, const string & header_file_name, bool isSystemHeader, PreprocessingInfo::RelativePositionType position)
16250 {
16251 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16252 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16253 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16254 bool supportTokenUnparsing = false;
16255
16256 assert(source_file != NULL);
16257 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16258
16259 SgGlobal * global_scope = source_file->get_globalScope();
16260
16261 string content;
16262 if (isSystemHeader)
16263 content = "#include <" + header_file_name + "> \n";
16264 else
16265 content = "#include \"" + header_file_name + "\" \n";
16266
16267 PreprocessingInfo* result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, position);
16268 ROSE_ASSERT(result);
16269
16270 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16271 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16272 // when multiple files are used on the command line.
16273 result->get_file_info()->setTransformation();
16274
16275 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16276 supportTokenUnparsing = source_file->get_unparse_tokens();
16277 bool supportUnparseHeaders = source_file->get_unparseHeaderFiles();
16278
16279#if 0
16280 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16281 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16282 printf ("source_file = %p \n",source_file);
16283 printf ("global_scope = %p \n",global_scope);
16284#endif
16285#if 0
16286 printf ("Exiting as a test! \n");
16287 ROSE_ABORT();
16288#endif
16289
16290 // global_scope->addToAttachedPreprocessingInfo(result, position);
16291 if (supportTokenUnparsing == false)
16292 {
16293 global_scope->addToAttachedPreprocessingInfo(result, position);
16294 }
16295 else
16296 {
16297 // global_scope->prepend_statement(null_statement);
16298 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16299
16300 if (supportUnparseHeaders == true)
16301 {
16302 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16303 int physical_file_id = global_scope->get_startOfConstruct()->get_physical_file_id();
16304#if 0
16305 printf ("physical_file_id = %d \n",physical_file_id);
16306#endif
16307 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16308 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16309#if 0
16310 printf ("Exiting as a test! \n");
16311 ROSE_ABORT();
16312#endif
16313 }
16314
16315 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16316
16317 global_scope->prepend_statement(emptyDeclaration);
16318 }
16319
16320#if 0
16321 printf ("Exiting as a test! \n");
16322 ROSE_ASSERT(false);
16323#endif
16324
16325 return result;
16326 }
16327
16328PreprocessingInfo* SageInterface::insertHeader(const string& filename, PreprocessingInfo::RelativePositionType position /*=after*/, bool isSystemHeader /*=false*/, SgScopeStatement* scope /*=NULL*/)
16329 {
16330 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16331 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16332 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16333 bool supportTokenUnparsing = false;
16334
16335 // DQ (8/12/2020): This is a compiler warning.
16336 // bool successful = false;
16337
16338#if 0
16339 printf ("In SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16340 printf (" --- position = %s \n",PreprocessingInfo::relativePositionName(position).c_str());
16341#endif
16342
16343 if (scope == NULL)
16345
16346 ROSE_ASSERT(scope);
16347
16348 SgGlobal* globalScope = getGlobalScope(scope);
16349 ROSE_ASSERT(globalScope != NULL);
16350
16351 // 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
16352 // if the input scope is within a header file,
16353 // its global scope will jump to a .cpp file. Later looping will not find a match.
16354 SgScopeStatement* srcScope = globalScope;
16355 PreprocessingInfo* result=NULL;
16356 string content;
16357 if (isSystemHeader)
16358 content = "#include <" + filename + "> \n";
16359 else
16360 content = "#include \"" + filename + "\" \n";
16361
16362 // DQ (11/21/2019): Token based unparsing has an additional requirement, we need to mark that the
16363 // whitespace around the statement has been modified. This will trigger the unparser to output
16364 // the comments and CPP directives when using the token-based unparsing. The insertion of a header
16365 // file requires this support else the original token stream will not have the added header file.
16366
16367 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16368 SgSourceFile* sourceFile = getEnclosingSourceFile(scope);
16369 ROSE_ASSERT(sourceFile != NULL);
16370
16371 supportTokenUnparsing = sourceFile->get_unparse_tokens();
16372
16373 bool supportUnparseHeaders = sourceFile->get_unparseHeaderFiles();
16374 // if unparsing header and the scope is within a header file, we adjust srcScope to be scope, not its enclosing global scope
16375 if (supportUnparseHeaders)
16376 {
16377 string filename= scope->get_file_info()->get_filename();
16378 string suffix = Rose::StringUtility ::fileNameSuffix(filename);
16379
16380 // vector.tcc: This is an internal header file, included by other library headers
16381 if (suffix=="h" ||suffix=="hpp"|| suffix=="hh"||suffix=="H" ||suffix=="hxx"||suffix=="h++" ||suffix=="tcc")
16382 srcScope = scope;
16383 }
16384
16385#if 0
16386 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16387 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16388 printf ("sourceFile = %p \n",sourceFile);
16389 printf ("globalScope = %p \n",globalScope);
16390#endif
16391#if 0
16392 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16393#endif
16394#if 0
16395 printf ("Exiting as a test! \n");
16396 ROSE_ABORT();
16397#endif
16398
16399 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations();
16400
16401#if 0
16402 printf ("stmtList.size() = %zu \n",stmtList.size());
16403#endif
16404
16405 if (stmtList.size() > 0) // the source file is not empty
16406 {
16407 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16408 {
16409 // must have this judgement, otherwise wrong file will be modified!
16410 // It could also be the transformation generated statements with #include attached
16411 if ( ((*j)->get_file_info())->isSameFile(srcScope->get_file_info ()) || ((*j)->get_file_info ())->isTransformation() )
16412 {
16413 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16414 ROSE_ASSERT(result != NULL);
16415#if 0
16416 printf ("Building a PreprocessingInfo: result = %p \n",result);
16417#endif
16418 // DQ (3/22/2019): Fixing this to work with the token-based unparsing.
16419 // add to the last position
16420 // TODO: support to add to the first,
16421 // TODO: support fine positioning with #include directives
16422 // (*j)->addToAttachedPreprocessingInfo(result,position);
16423
16424 if (supportTokenUnparsing == false)
16425 {
16426 (*j)->addToAttachedPreprocessingInfo(result,position);
16427 }
16428 else
16429 {
16430 (*j)->addToAttachedPreprocessingInfo(result,position);
16431#if 0
16432 printf ("In SageInterface::insertHeader(): Calling set_containsTransformationToSurroundingWhitespace(true) \n");
16433#endif
16434#if 1
16435 // DQ (12/31/2020): Set the whitespace around the statement as being modified.
16436 (*j)->set_containsTransformationToSurroundingWhitespace(true);
16437#endif
16438#if 0
16439 SgDeclarationStatement* declarationStatement = *j;
16440
16441 // DQ (1/5/2021): Don't call unparseToString, since this triggers the unparer which then unparses
16442 // from the token stream and makrs some token stream elements as already unparsed.
16443 // printf ("declarationStatement = %p = %s unparseToString() = %s \n",declarationStatement,
16444 // declarationStatement->class_name().c_str(),declarationStatement->unparseToString().c_str());
16445 printf ("In SageInterface::insertHeader(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
16446 printf ("In SageInterface::insertHeader(): declarationStatement->get_containsTransformationToSurroundingWhitespace() = %s \n",
16447 declarationStatement->get_containsTransformationToSurroundingWhitespace() ? "true" : "false");
16448#endif
16449#if 0
16450 // Liao, let's try the new way.
16451 // global_scope->prepend_statement(null_statement);
16452 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16453
16454 if (supportUnparseHeaders == true)
16455 {
16456 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16457 int physical_file_id = globalScope->get_startOfConstruct()->get_physical_file_id();
16458#if 0
16459 printf ("physical_file_id = %d \n",physical_file_id);
16460#endif
16461 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16462 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16463#if 0
16464 printf ("Exiting as a test! \n");
16465 ROSE_ASSERT(false);
16466#endif
16467 }
16468
16469 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16470
16471 globalScope->insert_statement(*j,emptyDeclaration);
16472#endif
16473 }
16474#if 0
16475 printf ("break out of for loop: result = %p \n",result);
16476#endif
16477 // DQ (8/12/2020): This is a compiler warning.
16478 // successful = true;
16479 break;
16480 }
16481 }
16482 }
16483 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16484 {
16485 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16486 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16487 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16488 ROSE_ASSERT(false);
16489 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16490 ROSE_ASSERT(result);
16491 globalScope->addToAttachedPreprocessingInfo(result,position);
16492
16493 // DQ (8/12/2020): This is a compiler warning.
16494 // successful = true;
16495 }
16496
16497 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16498 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16499 // when multiple files are used on the command line.
16500 // DQ (3/12/2019): This can be NULL for the omp tests.
16501 if (result != NULL)
16502 {
16503 result->get_file_info()->setTransformation();
16504 }
16505
16506 // must be inserted once somehow
16507 // 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
16508 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16509 // ROSE_ASSERT(successful==true);
16510
16511#if 0
16512 printf ("Exiting as a test! \n");
16513 ROSE_ASSERT(false);
16514#endif
16515
16516#if 0
16517 printf ("Leaving SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16518#endif
16519
16520#if 0
16521 printf ("Exiting as a test! \n");
16522 ROSE_ASSERT(false);
16523#endif
16524
16525 return result;
16526 }
16527
16528
16529// 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
16530void SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader)
16531{
16532 ROSE_ASSERT (stmt != NULL);
16533 ROSE_ASSERT (newheader != NULL);
16534
16535#if 0
16536 printf ("In SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader) \n");
16537#endif
16538
16540
16541 if (asLastHeader )
16542 position = PreprocessingInfo::after;
16543 else
16544 position = PreprocessingInfo::before;
16545
16546
16547 // Find existing first and last header.
16548 AttachedPreprocessingInfoType *comments = stmt->getAttachedPreprocessingInfo ();
16549
16550 if (comments != NULL)
16551 {
16552 PreprocessingInfo * firstExistingHeader = NULL;
16553 PreprocessingInfo * lastExistingHeader = NULL;
16554 PreprocessingInfo * firstExistingEndif = NULL;
16555
16556 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16557 // PreprocessingInfo * lastExistingEndif = NULL;
16558
16559 AttachedPreprocessingInfoType::iterator i, firsti, lasti;
16560 for (i = comments->begin (); i != comments->end (); i++)
16561 {
16562 // DQ (9/12/2020): this original code is not sufficent since when the final #include is enclosed in a
16563 // #ifdef #endif the added include directive might not be visible in the generated file.
16564 // This actually happened in the case of wget application: wget.c source file.
16565#if 0
16566 // Original version of code.
16567 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16568 {
16569 // Only set first header for the first time
16570 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16571 {
16572 if (firstExistingHeader == NULL)
16573 {
16574 firstExistingHeader = (*i);
16575 firsti = i;
16576 }
16577 // always updates last header
16578 lastExistingHeader = (*i);
16579 lasti = i;
16580 }
16581 }
16582#else
16583 // DQ (9/12/2020): New version of code. Addresses insertion after last endif if it is after any #include.
16584 if ( (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration ||
16585 (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration )
16586 {
16587 // Only set first header for the first time
16588 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16589 {
16590 if (firstExistingHeader == NULL)
16591 {
16592 firstExistingHeader = (*i);
16593 firsti = i;
16594 }
16595 // always updates last header
16596 lastExistingHeader = (*i);
16597 lasti = i;
16598 }
16599 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration)
16600 {
16601 if (firstExistingEndif == NULL)
16602 {
16603 firstExistingEndif = (*i);
16604 firsti = i;
16605 }
16606 // always updates last header
16607 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16608 // lastExistingEndif = (*i);
16609 lasti = i;
16610 }
16611 }
16612#endif
16613 }
16614
16615 // based on existing header positions, insert the new header
16616 if (asLastHeader)
16617 {
16618 if (lastExistingHeader == NULL) // No last header at all, just append to after
16619 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16620 else
16621 {
16622 comments->insert (lasti+1, newheader);
16623 }
16624 }
16625 else // add as the first header
16626 {
16627 if (firstExistingHeader == NULL) // no existing header at all, just append to after
16628 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16629 else
16630 {
16631 comments->insert (firsti, newheader);
16632 }
16633 }
16634 }
16635 else // No comments at all, first and last header mean the same, just attach to the located node
16636 stmt->addToAttachedPreprocessingInfo(newheader, position);
16637
16638#if 0
16639 printf ("Exiting as a test! \n");
16640 ROSE_ASSERT(false);
16641#endif
16642
16643}
16644
16645
16646// The recommended version
16647PreprocessingInfo* SageInterface::insertHeader(SgSourceFile * source_file, const std::string & filename, bool isSystemHeader , bool asLastHeader)
16648{
16649 ROSE_ASSERT (source_file != NULL);
16650 SgGlobal* globalScope = source_file->get_globalScope();
16651 ROSE_ASSERT (globalScope != NULL);
16652
16653 PreprocessingInfo* result=NULL;
16654 string content;
16655 if (isSystemHeader)
16656 content = "#include <" + filename + "> \n";
16657 else
16658 content = "#include \"" + filename + "\" \n";
16659
16660#if 0
16661 // 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.
16663
16664 if (asLastHeader )
16665 position = PreprocessingInfo::after;
16666 else
16667 position = PreprocessingInfo::before;
16668#endif
16669
16670 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations ();
16671 if (stmtList.size()>0) // the source file is not empty
16672 {
16673 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16674 {
16675 // Attach to the first eligible located statement
16676 //must have this judgement, otherwise wrong file will be modified!
16677 //It could also be the transformation generated statements with #include attached
16678 if ( (*j)->get_file_info()->isSameFile(globalScope->get_file_info()) || (*j)->get_file_info()->isTransformation() )
16679 {
16680#if 0
16681 printf ("In SageInterface::insertHeader(): Found statement to attached #include: *j = %p = %s \n",*j,(*j)->class_name().c_str());
16682 printf (" --- unparseToString() = %s \n",(*j)->unparseToString().c_str());
16683#endif
16684 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16685 ROSE_ASSERT(result);
16686 insertHeader (*j, result, asLastHeader);
16687 //successful = true;
16688#if 0
16689 printf ("Exiting as a test! \n");
16690 ROSE_ABORT();
16691#endif
16692 break;
16693 }
16694 } // end for
16695 }
16696 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16697 {
16698 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16699 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16700 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16701 ROSE_ABORT();
16702#if 0 // [Robb Matzke 2021-03-24]: unreachable
16703 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration,
16704 content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16705 ROSE_ASSERT(result);
16706 globalScope->addToAttachedPreprocessingInfo(result,position);
16707#endif
16708 // successful = true;
16709 }
16710
16711#if 0
16712 printf ("In SageInterface::insertHeader(): Marking include file for filename = %s as a transformation \n",filename.c_str());
16713#endif
16714
16715 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16716 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16717 // when multiple files are used on the command line.
16718 if (result)
16719 result->get_file_info()->setTransformation();
16720
16721#if 0
16722 printf ("Exiting as a test! \n");
16723 ROSE_ASSERT(false);
16724#endif
16725
16726 // must be inserted once somehow
16727 // 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
16728 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16729 // ROSE_ASSERT(successful==true);
16730 return result;
16731
16732} // end insertHeader
16733
16734
16737SageInterface::attachArbitraryText(SgLocatedNode* target, const std::string & text, PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/)
16738 {
16739 // DQ (1/13/2014): This function needs a better mechanism than attaching text to the AST unparser as a CPP directive.
16740
16741 ROSE_ASSERT(target != NULL); //dangling #define xxx is not allowed in the ROSE AST
16742 PreprocessingInfo* result = NULL;
16743
16744 // DQ (1/13/2014): It is a mistake to attach arbitrary test to the AST as a #define
16745 // (since we evaluate all #define CPP declarations to be a self-referential macro).
16746 // For now I will make it a #if CPP declaration, since these are not evaluated internally.
16747 // PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorDefineDeclaration;
16748 PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorIfDeclaration;
16749
16750 // DQ (1/13/2014): Output a warning so that this can be fixed whereever it is used.
16751 printf ("Warning: attachArbitraryText(): attaching arbitrary text to the AST as a #if declaration: text = %s \n",text.c_str());
16752
16753 result = new PreprocessingInfo (mytype,text, "transformation-generated", 0, 0, 0, position);
16754 ROSE_ASSERT(result);
16755
16756 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16757 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16758 // when multiple files are used on the command line.
16759 result->get_file_info()->setTransformation();
16760
16761 target->addToAttachedPreprocessingInfo(result);
16762
16763 return result;
16764 }
16765
16766
16768// 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.
16770{
16771 // This is part of Wave support in ROSE.
16772// #if CAN_NOT_COMPILE_WITH_ROSE != true
16773// #if CAN_NOT_COMPILE_WITH_ROSE == 0
16774#ifndef USE_ROSE
16775 ROSE_ASSERT(target != NULL);
16776 AttachedPreprocessingInfoType *info= target->getAttachedPreprocessingInfo ();
16777 if (info == NULL) return;
16778 AttachedPreprocessingInfoType::iterator j;
16779 for (j = info->begin (); j != info->end (); j++)
16780 {
16781 if ((*j)->getTypeOfDirective()==PreprocessingInfo::CMacroCall)
16782 {
16783#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
16784 // DQ (2/17/2016): The token_container type is not defined if Wave is not available.
16785 std::ostringstream os;
16786 token_container tc = (*j)->get_macro_call()->expanded_macro;
16787 token_container::const_iterator iter;
16788 for (iter=tc.begin(); iter!=tc.end(); iter++)
16789 os<<(*iter).get_value();
16790 //cout<<"Found a macro call: "<<(*j)->getString()<<
16791 //"\nexpanding it to: "<<os.str()<<endl;
16792 string pragmaText = target->get_pragma()->get_pragma();
16793 string targetString = (*j)->getString();
16794 string replacement = os.str();
16795 // repeat until not found
16796 size_t pos1 = pragmaText.find(targetString);
16797 while (pos1 != string::npos)
16798 {
16799 pragmaText.replace(pos1, targetString.size(), replacement);
16800 pos1 = pragmaText.find(targetString);
16801 }
16802 delete target->get_pragma();
16803 target->set_pragma(buildPragma(pragmaText));
16804#endif
16805 } // end if
16806 } // end for
16807#endif
16808}
16809
16814 using namespace SageBuilder;
16815 SgStatement* body = NULL;
16816 if (isSgWhileStmt(loopOrSwitch) || isSgDoWhileStmt(loopOrSwitch) ||
16817 isSgForStatement(loopOrSwitch)) {
16818 body = SageInterface::getLoopBody(isSgScopeStatement(loopOrSwitch));
16819 } else if (isSgSwitchStatement(loopOrSwitch)) {
16820 body = isSgSwitchStatement(loopOrSwitch)->get_body();
16821 }
16822 ROSE_ASSERT (body);
16823 std::vector<SgBreakStmt*> breaks = SageInterface::findBreakStmts(body);
16824 if (!breaks.empty()) {
16825 static int breakLabelCounter = 0;
16826 SgLabelStatement* breakLabel =
16827 buildLabelStatement("breakLabel" +
16828StringUtility::numberToString(++breakLabelCounter),
16830 isSgScopeStatement(loopOrSwitch->get_parent()));
16831 insertStatement(loopOrSwitch, breakLabel, false);
16832 for (size_t j = 0; j < breaks.size(); ++j) {
16833 SgGotoStatement* newGoto = buildGotoStatement(breakLabel);
16834
16835 isSgStatement(breaks[j]->get_parent())->replace_statement(breaks[j],
16836 newGoto);
16837 newGoto->set_parent(breaks[j]->get_parent());
16838 }
16839 }
16840 }
16841
16843 {
16844 ROSE_ASSERT(node!=NULL);
16845 SgClassDeclaration *decl = isSgClassDeclaration(node);
16846 if (decl==NULL)
16847 return false;
16848 else
16849 return (decl->get_class_type() == SgClassDeclaration::e_struct)? true:false;
16850 }
16851
16853 {
16854 ROSE_ASSERT(node!=NULL);
16855 SgClassDeclaration *decl = isSgClassDeclaration(node);
16856 if (decl==NULL)
16857 return false;
16858 else
16859 return (decl->get_class_type() == SgClassDeclaration::e_union)? true:false;
16860 }
16861
16862
16863void
16864SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
16865 PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
16866 {
16867 ROSE_ASSERT(stmt_src != NULL);
16868 ROSE_ASSERT(stmt_dst != NULL);
16869 AttachedPreprocessingInfoType* infoList = stmt_src->getAttachedPreprocessingInfo();
16870
16871 if (infoList == NULL)
16872 {
16873#if 0
16874 printf ("In SageInterface::movePreprocessingInfo(): infoList == NULL: exiting movePreprocessingInfo() \n");
16875#endif
16876 return;
16877 }
16878
16879 AttachedPreprocessingInfoType* infoToRemoveList = new AttachedPreprocessingInfoType();
16880
16881#if 0
16882 printf ("In SageInterface::movePreprocessingInfo(): \n");
16883 printf (" --- stmt_src = %p = %s src_position = %d \n",stmt_src,stmt_src->class_name().c_str(),src_position);
16884 SgDeclarationStatement* src_declarationStatement = isSgDeclarationStatement(stmt_src);
16885 if (src_declarationStatement != NULL)
16886 {
16887 printf ("src_declarationStatement->get_firstNondefiningDeclaration() = %p \n",src_declarationStatement->get_firstNondefiningDeclaration());
16888 printf ("src_declarationStatement->get_definingDeclaration() = %p \n",src_declarationStatement->get_definingDeclaration());
16889 }
16890 printf (" --- stmt_dst = %p = %s dst_position = %d \n",stmt_dst,stmt_dst->class_name().c_str(),dst_position);
16891 SgDeclarationStatement* dst_declarationStatement = isSgDeclarationStatement(stmt_dst);
16892 if (dst_declarationStatement != NULL)
16893 {
16894 printf ("dst_declarationStatement->get_firstNondefiningDeclaration() = %p \n",dst_declarationStatement->get_firstNondefiningDeclaration());
16895 printf ("dst_declarationStatement->get_definingDeclaration() = %p \n",dst_declarationStatement->get_definingDeclaration());
16896 }
16897 printf (" --- src_position = %s \n",PreprocessingInfo::relativePositionName(src_position).c_str());
16898 printf (" --- dst_position = %s \n",PreprocessingInfo::relativePositionName(dst_position).c_str());
16899 printf (" --- usePrepend = %s \n",usePrepend ? "true" : "false");
16900
16901 printf (" --- infoList = %p \n",infoList);
16902 printf (" --- infoToRemoveList = %p \n",infoToRemoveList);
16903
16904 AttachedPreprocessingInfoType* dst_infoList = stmt_dst->getAttachedPreprocessingInfo();
16905 printf (" --- dst_infoList = %p \n",dst_infoList);
16906#endif
16907#if 0
16908 printf ("****************************************************************** \n");
16909 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_src \n");
16911 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_dst \n");
16913 printf ("****************************************************************** \n");
16914#endif
16915
16916 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
16917 // This is a bug in the support for building a new prototype from a defining function declaration
16918 // and caused this problem. This assertion will prevent this sort of error from happening again.
16919 ROSE_ASSERT(infoList == NULL || stmt_src->getAttachedPreprocessingInfo() != stmt_dst->getAttachedPreprocessingInfo());
16920
16921
16922#if 0
16923 printf (" --- infoList->size() = %zu \n",infoList->size());
16924 printf (" --- infoToRemoveList->size() = %zu \n",infoToRemoveList->size());
16925#endif
16926
16927#if 0
16928 int counter = 0;
16929
16930 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
16931 {
16932 // DQ (11/19/2020): Added assertion.
16933 ROSE_ASSERT(*i != NULL);
16934
16935 // DQ (11/19/2020): Why do we have a dynamic cast here.
16936 // PreprocessingInfo * info = dynamic_cast<PreprocessingInfo*> (*i);
16937 PreprocessingInfo * info = *i;
16938 ROSE_ASSERT(info != NULL);
16939
16940 // printf ("counter = %d \n",counter);
16941 printf ("counter = %d Processing PreprocessingInfo = %s \n",counter,info->getString().c_str());
16942 counter++;
16943 }
16944
16945 counter = 0;
16946#endif
16947
16948 PreprocessingInfo* prevItem = NULL;
16949
16950 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
16951 {
16952 ROSE_ASSERT(*i != NULL);
16953
16954 PreprocessingInfo * info = *i;
16955 ROSE_ASSERT(info != NULL);
16956
16957 if ( // match enum values in http://rosecompiler.org/ROSE_HTML_Reference/classPreprocessingInfo.html
16958 (info->getTypeOfDirective()==PreprocessingInfo::C_StyleComment)||
16959 (info->getTypeOfDirective()==PreprocessingInfo::CplusplusStyleComment)||
16960 (info->getTypeOfDirective()==PreprocessingInfo::FortranStyleComment)||
16961 (info->getTypeOfDirective()==PreprocessingInfo::F90StyleComment)||
16962 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeDeclaration )||
16963 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeNextDeclaration )||
16964 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDefineDeclaration )||
16965 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorUndefDeclaration)||
16966 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfdefDeclaration )||
16967 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfndefDeclaration )||
16968 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfDeclaration )||
16969 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDeadIfDeclaration )||
16970 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElseDeclaration )||
16971 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElifDeclaration )||
16972 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEndifDeclaration ) ||
16973 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEnd_ifDeclaration ) ||
16974 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorLineDeclaration) ||
16975 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorErrorDeclaration) ||
16976 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorWarningDeclaration) ||
16977 // DQ (12/28/2020): Added support for C linkage specifications.
16978 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationStart) ||
16979 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationEnd)
16980 )
16981 {
16982 // move all source preprocessing info if the desired source type is not specified or matching
16983 // a specified desired source type
16984 if ( src_position == PreprocessingInfo::undef || info->getRelativePosition() == src_position)
16985 {
16986 if (usePrepend == true)
16987 {
16988 // Liao (1/27/2015): modification to fix order of CPP directives when a list of them are moved.
16989 if (prevItem == NULL)
16990 {
16991 // addToAttachedPreprocessingInfo() is poorly designed, the last parameter is used
16992 // to indicate appending or prepending by reusing the type of relative position.
16993 // this is very confusing for users
16994 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::before);
16995 }
16996 else // there is a previous item, insert after it
16997 {
16998 stmt_dst->insertToAttachedPreprocessingInfo(info, prevItem);
16999 }
17000 prevItem = info;
17001 }
17002 else
17003 {
17004 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::after);
17005 }
17006 // 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.
17007 info->setAsTransformation();
17008
17009 // DQ (10/13/2015): This is a problem for the token-based unparsing since we don't want to have this
17010 // set_containsTransformationToSurroundingWhitespace() function cause the isModified flag to be set.
17011 // So we have to detect it being set and reset it as needed. An alternative would be to have a
17012 // non-ROSETTA generate function that didn't have the isModified flag set for the seter access function.
17013 // Note that the inputmoveDeclarationToInnermostScope_test2015_123.C file demonstrates this problem.
17014 bool isMarkedAsModified = stmt_dst->get_isModified();
17015 stmt_dst->set_containsTransformationToSurroundingWhitespace(true);
17016 if (isMarkedAsModified == false)
17017 {
17018 if (stmt_dst->get_isModified() == true)
17019 {
17020 stmt_dst->set_isModified(false);
17021 }
17022 }
17023 (*infoToRemoveList).push_back(*i);
17024 }
17025
17026 // adjust dst position if needed
17027 if (dst_position != PreprocessingInfo::undef)
17028 {
17029 info->setRelativePosition(dst_position);
17030 }
17031 } // end if
17032 } // end for
17033
17034 // Remove the element from the list of comments at the current astNode
17035 AttachedPreprocessingInfoType::iterator j;
17036 for (j = (*infoToRemoveList).begin(); j != (*infoToRemoveList).end(); j++)
17037 {
17038 infoList->erase( find(infoList->begin(),infoList->end(),*j) );
17039 }
17040 }
17041
17042
17043//----------------------------
17044// Sometimes, the preprocessing info attached to a declaration has to be
17045// moved 'up' if another declaration is inserted before it.
17046// This is a workaround for the broken LowLevelRewrite::insert() and the private
17047// LowLevelRewrite::reassociatePreprocessorDeclarations()
17048//
17049// input:
17050// *stmt_dst: the new inserted declaration
17051// *stmt_src: the existing declaration with preprocessing information
17052// tasks:
17053// judge if stmt_src has propressingInfo with headers, ifdef, etc..
17054// add them into stmt_dst
17055// delete them from stmt_dst
17056// More general usage: move preprocessingInfo of stmt_src to stmt_dst, should used before any
17057// LoweLevel::remove(stmt_src)
17059 PreprocessingInfo::RelativePositionType src_position/*=PreprocessingInfo::undef*/,
17060 PreprocessingInfo::RelativePositionType dst_position/*=PreprocessingInfo::undef*/,
17061 bool usePrepend /*= false */)
17062 {
17063 movePreprocessingInfo (stmt_src, stmt_dst, src_position, dst_position, usePrepend);
17064 } // moveUpPreprocessingInfo()
17065
17066
17071static bool isNotRelPos (const PreprocessingInfo* info,
17073{
17074 return info && (info->getRelativePosition () != pos);
17075}
17076
17081static bool isRelPos (const PreprocessingInfo* info,
17083{
17084 return info && !isNotRelPos (info, pos);
17085}
17086
17087
17089void SageInterface::cutPreprocessingInfo (SgLocatedNode* src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17090{
17091 ASSERT_not_null(src_node);
17092
17093 // [Rasmussen,Sottile 2023.01.10]: Replaced deleted bind2nd (as of 2017)
17094 AttachedPreprocessingInfoType* info = src_node->get_attachedPreprocessingInfoPtr();
17095 if (info)
17096 {
17097 // copy elements to save_buf where isRelPos() is false
17098 remove_copy_if(info->begin(),
17099 info->end(),
17100 back_inserter(save_buf),
17101 [pos](auto x) { return !isRelPos(x, pos); }
17102 );
17103
17104 // delete copied elements from save_buf
17105 AttachedPreprocessingInfoType::iterator
17106 new_end = remove_if(info->begin(),
17107 info->end(),
17108 [pos](auto x) { return isRelPos(x, pos); }
17109 );
17110 info->erase(new_end, info->end());
17111 }
17112}
17113
17114static AttachedPreprocessingInfoType *
17115createInfoList (SgLocatedNode* s)
17116{
17117 ROSE_ASSERT (s);
17118 AttachedPreprocessingInfoType* info_list = s->get_attachedPreprocessingInfoPtr ();
17119 if (!info_list)
17120 {
17121 info_list = new AttachedPreprocessingInfoType;
17122 ROSE_ASSERT (info_list);
17123 s->set_attachedPreprocessingInfoPtr (info_list);
17124 }
17125
17126 // Guarantee a non-NULL pointer.
17127 ROSE_ASSERT (info_list);
17128 return info_list;
17129}
17130
17132void SageInterface::pastePreprocessingInfo (SgLocatedNode* dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17133{
17134 if (save_buf.size()==0) return;
17135 // if front
17136 AttachedPreprocessingInfoType* info = createInfoList (dst_node);
17137 ROSE_ASSERT (info);
17138
17139 // DQ (9/26/2007): Commented out as part of move from std::list to std::vector
17140 // printf ("Commented out front_inserter() as part of move from std::list to std::vector \n");
17141 // copy (save_buf.rbegin (), save_buf.rend (), front_inserter (*info));
17142
17143 // Liao (10/3/2007), vectors can only be appended at the rear
17144 if (pos==PreprocessingInfo::before)
17145 {
17146 for(AttachedPreprocessingInfoType::reverse_iterator i=save_buf.rbegin();i!=save_buf.rend();i++)
17147 info->insert(info->begin(),*i);
17148 }
17149 // if back
17150 else if (pos==PreprocessingInfo::after)
17151 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17152 else if (pos==PreprocessingInfo::inside)
17153 {
17154 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17155 cerr<<"SageInterface::pastePreprocessingInfo() pos==PreprocessingInfo::inside is not supported."<<endl;
17156 save_buf[0]->display("ttt");
17157 }
17158}
17159
17161{
17162 ROSE_ASSERT(locatedNode != NULL);
17163 AttachedPreprocessingInfoType *comments =
17164 locatedNode->getAttachedPreprocessingInfo ();
17165
17166 if (comments != NULL)
17167 {
17168 printf ("-----------------------------------------------\n");
17169 printf ("Found an IR node (at %p of type: %s) in file %s \n",
17170 locatedNode, locatedNode->class_name ().c_str (),
17171 (locatedNode->get_file_info ()->get_filenameString ()).c_str ());
17172 int counter = 0;
17173 AttachedPreprocessingInfoType::iterator i;
17174 for (i = comments->begin (); i != comments->end (); i++)
17175 {
17176 printf
17177 ("with attached preprocessingInfo numbering #%d :------------- \nclassification= %s:\nString format:%s\n",
17178 counter++,
17179 PreprocessingInfo::directiveTypeName ((*i)->getTypeOfDirective ()).
17180 c_str (), (*i)->getString ().c_str ());
17181 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
17182 printf ("relative position is: inside\n");
17183 else
17184 printf ("relative position is: %s\n", \
17185 ((*i)->getRelativePosition () == PreprocessingInfo::before) ? "before" : "after");
17186 }
17187 }
17188 else
17189 {
17190 printf ("No attached preprocessing info. (at %p of type: %s): \n", locatedNode,
17191 locatedNode->sage_class_name ());
17192 }
17193}
17194
17206template <class ParentNode>
17207static
17208SgBasicBlock* ensureBasicBlock_aux( ParentNode& stmt,
17209 SgStatement* (ParentNode::*getter) () const,
17210 void (ParentNode::*setter) (SgStatement*)
17211 )
17212{
17213 SgStatement* const body_stmt = (stmt.*getter)();
17214 SgBasicBlock* basicblock = isSgBasicBlock(body_stmt);
17215
17216 if (basicblock == NULL) {
17217 basicblock = SageBuilder::buildBasicBlock(body_stmt);
17218 (stmt.*setter)(basicblock);
17219 basicblock->set_parent(&stmt);
17220 }
17221
17222 ROSE_ASSERT (basicblock != NULL);
17223 return basicblock;
17224}
17225
17227{
17228 SgStatement* b = fs->get_loop_body();
17229 if (!isSgBasicBlock(b)) {
17231 fs->set_loop_body(b);
17232 b->set_parent(fs);
17233
17234 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17236 }
17237 ROSE_ASSERT (isSgBasicBlock(b));
17238 return isSgBasicBlock(b);
17239}
17240
17242{
17243 SgStatement* b = cs->get_body();
17244 if (!isSgBasicBlock(b)) {
17246 cs->set_body(b);
17247 b->set_parent(cs);
17248
17249 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17251 }
17252 ROSE_ASSERT (isSgBasicBlock(b));
17253 return isSgBasicBlock(b);
17254}
17255
17257{
17258 SgStatement* b = cs->get_body();
17259 if (!isSgBasicBlock(b)) {
17261 cs->set_body(b);
17262 b->set_parent(cs);
17263
17264 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17266 }
17267 ROSE_ASSERT (isSgBasicBlock(b));
17268 return isSgBasicBlock(b);
17269}
17270
17272{
17273 ROSE_ASSERT (fs != NULL);
17274
17275 return ensureBasicBlock_aux(*fs, &SgUpcForAllStatement::get_loop_body, &SgUpcForAllStatement::set_loop_body);
17276}
17277
17279 SgStatement* b = fs->get_body();
17280 if (!isSgBasicBlock(b)) {
17282 fs->set_body(b);
17283 b->set_parent(fs);
17284
17285 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17287 }
17288 ROSE_ASSERT (isSgBasicBlock(b));
17289 return isSgBasicBlock(b);
17290 }
17291
17293 SgStatement* b = fs->get_body();
17294 if (!isSgBasicBlock(b)) {
17296 fs->set_body(b);
17297 b->set_parent(fs);
17298
17299 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17301 }
17302 ROSE_ASSERT (isSgBasicBlock(b));
17303 return isSgBasicBlock(b);
17304 }
17305
17307 SgStatement* b = fs->get_body();
17308 if (!isSgBasicBlock(b)) {
17310 fs->set_body(b);
17311 b->set_parent(fs);
17312
17313 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17315 }
17316 ROSE_ASSERT (isSgBasicBlock(b));
17317 return isSgBasicBlock(b);
17318 }
17319
17321 SgStatement* b = fs->get_true_body();
17322 if (!isSgBasicBlock(b)) {
17324 fs->set_true_body(b);
17325 b->set_parent(fs);
17326
17327 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17329#if 0
17330 printf ("In SageInterface::ensureBasicBlockAsTrueBodyOfIf(): Added SgBasicBlock b = %p to addedBasicBlockNodes.size() = %zu \n",b,addedBasicBlockNodes.size());
17331#endif
17332 }
17333 ROSE_ASSERT (isSgBasicBlock(b));
17334 return isSgBasicBlock(b);
17335 }
17336
17337// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17339 {
17340 // Record where normalization have been done so that we can preform denormalizations as required
17341 // for the token-based unparsing to generate minimal diffs.
17342
17343 SgBasicBlock* bb = isSgBasicBlock(s);
17344 ROSE_ASSERT(bb != NULL);
17345 addedBasicBlockNodes.push_back(bb);
17346#if 0
17347 printf ("In SageInterface::recordNormalizations(): Added SgBasicBlock = %p to addedBasicBlockNodes.size() = %zu \n",bb,addedBasicBlockNodes.size());
17348#endif
17349 }
17350
17351// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17353 {
17354 // Remove unused basic block IR nodes added as part of normalization.
17355 // This function should be called before the unparse step.
17356
17357#if 0
17358 printf ("In SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17359#endif
17360
17361 for (vector<SgBasicBlock*>::iterator i = addedBasicBlockNodes.begin(); i != addedBasicBlockNodes.end(); i++)
17362 {
17363 SgBasicBlock* b = *i;
17364 ROSE_ASSERT(b != NULL);
17365 if (b->get_statements().size() == 1)
17366 {
17367#if 0
17368 printf ("This SgBasicBlock can be denormalized: b = %p \n",b);
17369#endif
17370 SgStatement* parentOfBlock = isSgStatement(b->get_parent());
17371 ROSE_ASSERT(parentOfBlock != NULL);
17372
17373 bool wasPreviouslyModified = parentOfBlock->get_isModified();
17374
17375 SgStatement* s = b->get_statements()[0];
17376 ROSE_ASSERT(s != NULL);
17377
17378 switch (parentOfBlock->variantT())
17379 {
17380 case V_SgIfStmt:
17381 {
17382 SgIfStmt* ifStatement = isSgIfStmt(parentOfBlock);
17383 if (b == ifStatement->get_true_body())
17384 {
17385#if 0
17386 printf ("Calling set_true_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17387#endif
17388 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17389 ifStatement->set_true_body(s);
17390#if 0
17391 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17392#endif
17393 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17394 s->set_parent(ifStatement);
17395#if 0
17396 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17397#endif
17398 *i = NULL;
17399 // delete b;
17400 }
17401 else
17402 {
17403 ROSE_ASSERT(b == ifStatement->get_false_body());
17404#if 0
17405 printf ("Calling set_false_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17406#endif
17407 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17408 ifStatement->set_false_body(s);
17409#if 0
17410 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17411#endif
17412 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17413 s->set_parent(ifStatement);
17414#if 0
17415 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17416#endif
17417 *i = nullptr;
17418#if 0
17419 printf ("Mark as NOT modified after calling set_false_body on ifStatement = %p = %n \n",ifStatement,ifStatement->class_name().c_str());
17420#endif
17421#if 0
17422 printf ("Error: case not handled in case V_SgIfStmt: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17423 ROSE_ABORT();
17424#endif
17425 }
17426 break;
17427 }
17428
17429 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17430 case V_SgWhileStmt:
17431 {
17432 SgWhileStmt* whileStatement = isSgWhileStmt(parentOfBlock);
17433 if (b == whileStatement->get_body())
17434 {
17435 whileStatement->set_body(s);
17436 s->set_parent(whileStatement);
17437 }
17438 break;
17439 }
17440
17441 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17442 case V_SgSwitchStatement:
17443 {
17444 SgSwitchStatement* switchStatement = isSgSwitchStatement(parentOfBlock);
17445 if (b == switchStatement->get_body())
17446 {
17447 switchStatement->set_body(s);
17448 s->set_parent(switchStatement);
17449 }
17450 break;
17451 }
17452
17453 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17454 case V_SgForStatement:
17455 {
17456 SgForStatement* forStatement = isSgForStatement(parentOfBlock);
17457 if (b == forStatement->get_loop_body())
17458 {
17459 forStatement->set_loop_body(s);
17460 s->set_parent(forStatement);
17461 }
17462 break;
17463 }
17464
17465 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17466 case V_SgCaseOptionStmt:
17467 {
17468 SgCaseOptionStmt* caseOptionStatement = isSgCaseOptionStmt(parentOfBlock);
17469 if (b == caseOptionStatement->get_body())
17470 {
17471 caseOptionStatement->set_body(s);
17472 s->set_parent(caseOptionStatement);
17473 }
17474 break;
17475 }
17476
17477 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17478 case V_SgDefaultOptionStmt:
17479 {
17480 SgDefaultOptionStmt* defaultOptionStatement = isSgDefaultOptionStmt(parentOfBlock);
17481 if (b == defaultOptionStatement->get_body())
17482 {
17483 defaultOptionStatement->set_body(s);
17484 s->set_parent(defaultOptionStatement);
17485 }
17486 break;
17487 }
17488
17489 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17490 case V_SgDoWhileStmt:
17491 {
17492 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(parentOfBlock);
17493 if (b == doWhileStatement->get_body())
17494 {
17495 doWhileStatement->set_body(s);
17496 s->set_parent(doWhileStatement);
17497 }
17498 break;
17499 }
17500
17501 default:
17502 {
17503 printf ("Error: case not handled in switch: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17504 ROSE_ABORT();
17505 }
17506 }
17507
17508 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17509 if (wasPreviouslyModified == false)
17510 {
17511 if (parentOfBlock->get_isModified() == true)
17512 {
17513#if 0
17514 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());
17515#endif
17516 parentOfBlock->set_isModified(false);
17517 }
17518
17519 }
17520#if 0
17521 printf ("Exiting as a test! \n");
17522 ROSE_ABORT();
17523#endif
17524 }
17525 }
17526
17527#if 0
17528 printf ("Leaving SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17529#endif
17530 }
17531
17532
17534 SgStatement* b = fs->get_false_body();
17535 // if no false body at all AND no-create-empty-body
17536 if (!createEmptyBody && (b == NULL || isSgNullStatement(b)))
17537 return NULL;
17538 if (!isSgBasicBlock(b)) {
17539 b = SageBuilder::buildBasicBlock(b); // This works if b is NULL as well (producing an empty block)
17540 fs->set_false_body(b);
17541 b->set_parent(fs);
17542
17543 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17545 }
17546 ROSE_ASSERT (isSgBasicBlock(b));
17547 return isSgBasicBlock(b);
17548 }
17549
17551 SgStatement* b = fs->get_body();
17552 if (!isSgBasicBlock(b)) {
17554 fs->set_body(b);
17555 b->set_parent(fs);
17556 }
17557 ROSE_ASSERT (isSgBasicBlock(b));
17558 return isSgBasicBlock(b);
17559 }
17560
17562{
17563 SgStatement* b = fs->get_body();
17564 if (!isSgBasicBlock(b)) {
17566 fs->set_body(b);
17567 b->set_parent(fs);
17568 }
17569 ROSE_ASSERT (isSgBasicBlock(b));
17570 return isSgBasicBlock(b);
17571}
17572
17574{
17575 bool rt = false;
17576 ROSE_ASSERT(s);
17577 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17578 ROSE_ASSERT(p);
17579
17580 switch (p->variantT())
17581 {
17582 case V_SgForStatement:
17583 {
17584 if (isSgForStatement(p)->get_loop_body() == s)
17585 rt = true;
17586 break;
17587 }
17588 case V_SgUpcForAllStatement: // PP
17589 {
17590 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17591 if (upcforall.get_loop_body() == s)
17592 rt = true;
17593 break;
17594 }
17595 case V_SgWhileStmt:
17596 {
17597 if (isSgWhileStmt(p)->get_body() == s)
17598 rt = true;
17599 break;
17600 }
17601 case V_SgDoWhileStmt:
17602 {
17603 if (isSgDoWhileStmt(p)->get_body() == s)
17604 rt = true;
17605 break;
17606 }
17607 case V_SgSwitchStatement:
17608 {
17609 if (isSgSwitchStatement(p)->get_body() == s)
17610 rt = true;
17611 break;
17612 }
17613 case V_SgCaseOptionStmt:
17614 {
17615 if (isSgCaseOptionStmt(p)->get_body() == s)
17616 rt = true;
17617 break;
17618 }
17619 case V_SgDefaultOptionStmt:
17620 {
17621 if (isSgDefaultOptionStmt(p)->get_body() == s)
17622 rt = true;
17623 break;
17624 }
17625 case V_SgCatchOptionStmt:
17626 {
17627 if (isSgCatchOptionStmt(p)->get_body() == s)
17628 rt = true;
17629 break;
17630 }
17631 case V_SgIfStmt:
17632 {
17633 if (isSgIfStmt(p)->get_true_body() == s)
17634 rt = true;
17635 else if (isSgIfStmt(p)->get_false_body() == s)
17636 rt = true;
17637 break;
17638 }
17639 default:
17640 {
17641 if (isSgOmpBodyStatement(p))
17642 rt = true;
17643 break;
17644 }
17645 }
17646 return rt;
17647}
17648
17650//etc.
17652{
17653 ROSE_ASSERT (singleStmt != NULL); // not NULL
17654 ROSE_ASSERT (isSgBasicBlock(singleStmt) == NULL); //not a block
17655 ROSE_ASSERT (isBodyStatement(singleStmt) == true); // is a body statement
17656
17657 SgBasicBlock* rt = NULL;
17658
17659
17660
17661 SgStatement* s = singleStmt;
17662 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17663 ROSE_ASSERT(p);
17664 switch (p->variantT())
17665 {
17666 case V_SgForStatement:
17667 {
17668 if (isSgForStatement(p)->get_loop_body() == s)
17669 rt = ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17670 break;
17671 }
17672 case V_SgUpcForAllStatement: // PP
17673 {
17674 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17675
17676 if (upcforall.get_loop_body() == s)
17677 rt = ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17678 break;
17679 }
17680 case V_SgWhileStmt:
17681 {
17682 if (isSgWhileStmt(p)->get_body() == s)
17683 rt = ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17684 break;
17685 }
17686 case V_SgDoWhileStmt:
17687 {
17688 if (isSgDoWhileStmt(p)->get_body() == s)
17689 rt = ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17690 break;
17691 }
17692 case V_SgSwitchStatement:
17693 {
17694 if (isSgSwitchStatement(p)->get_body() == s)
17695 rt = ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17696 break;
17697 }
17698 case V_SgCaseOptionStmt:
17699 {
17700 if (isSgCaseOptionStmt(p)->get_body() == s)
17701 rt = ensureBasicBlockAsBodyOfCaseOption(isSgCaseOptionStmt(p));
17702 break;
17703 }
17704 case V_SgDefaultOptionStmt:
17705 {
17706 if (isSgDefaultOptionStmt(p)->get_body() == s)
17707 rt = ensureBasicBlockAsBodyOfDefaultOption(isSgDefaultOptionStmt(p));
17708 break;
17709 }
17710 case V_SgCatchOptionStmt:
17711 {
17712 if (isSgCatchOptionStmt(p)->get_body() == s)
17713 rt = ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17714 break;
17715 }
17716 case V_SgIfStmt:
17717 {
17718 if (isSgIfStmt(p)->get_true_body() == s)
17719 rt = ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17720 else if (isSgIfStmt(p)->get_false_body() == s)
17721 rt = ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17722 break;
17723 }
17724 default:
17725 {
17726 if (isSgOmpBodyStatement(p))
17727 {
17728 rt = ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17729 }
17730 break;
17731 }
17732 }
17733 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.
17734 return rt;
17735}
17736
17737#if 0
17738SgLocatedNode* SageInterface::ensureBasicBlockAsParent(SgStatement* s)
17739{
17740 ROSE_ASSERT(s);
17741
17742 //Vulov: The parent of a statement is not necessarily a statement. It could be SgStatementExpression
17743 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17744 ROSE_ASSERT(p);
17745 switch (p->variantT())
17746 {
17747 case V_SgBasicBlock: return isSgBasicBlock(p);
17748 case V_SgForStatement:
17749 {
17750 if (isSgForStatement(p)->get_loop_body() == s)
17751 return ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17752 else if (isSgForStatement(p)->get_test() == s)
17753 {
17754 }
17755 else if (isSgForStatement(p)->get_for_init_stmt() == s)
17756 {
17757 }
17758 else ROSE_ABORT();
17759 break;
17760 }
17761 case V_SgUpcForAllStatement: // PP
17762 {
17763 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17764
17765 if (upcforall.get_loop_body() == s)
17766 return ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17767
17768 ROSE_ASSERT( (s == upcforall.get_for_init_stmt())
17769 || (s == upcforall.get_test())
17770 );
17771 break;
17772 }
17773 case V_SgWhileStmt:
17774 {
17775 if (isSgWhileStmt(p)->get_body() == s)
17776 return ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17777 else if (isSgWhileStmt(p)->get_condition() == s)
17778 {
17779 }
17780 else ROSE_ABORT();
17781 break;
17782 }
17783 case V_SgDoWhileStmt:
17784 {
17785 if (isSgDoWhileStmt(p)->get_body() == s)
17786 return ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17787 else if (isSgDoWhileStmt(p)->get_condition() == s)
17788 {
17789 }
17790 else ROSE_ABORT();
17791 break;
17792 }
17793 case V_SgSwitchStatement:
17794 {
17795 if (isSgSwitchStatement(p)->get_body() == s)
17796 return ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17797 else if (isSgSwitchStatement(p)->get_item_selector() == s)
17798 {
17799 }
17800 else ROSE_ABORT();
17801 break;
17802 }
17803 case V_SgCatchOptionStmt:
17804 {
17805 if (isSgCatchOptionStmt(p)->get_body() == s)
17806 return ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17807 else if (isSgCatchOptionStmt(p)->get_condition() == s)
17808 {
17809 }
17810 else ROSE_ABORT();
17811 break;
17812 }
17813 case V_SgIfStmt:
17814 {
17815 if (isSgIfStmt(p)->get_true_body() == s)
17816 return ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17817 else if (isSgIfStmt(p)->get_false_body() == s)
17818 return ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17819 else if (isSgIfStmt(p)->get_conditional() == s)
17820 {
17821 }
17822 else ROSE_ABORT();
17823 break;
17824 }
17825 default:
17826 {
17827 if (isSgOmpBodyStatement(p))
17828 {
17829 return ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17830 }
17831 else
17832 // Liao, 7/3/2008 We allow other conditions to fall through,
17833 // they are legal parents with list of statements as children.
17834 //cerr << "Unhandled parent block:"<< p->class_name() << endl;
17835 // ROSE_ASSERT (!"Bad parent in ensureBasicBlockAsParent");
17836 break;
17837 }
17838 }
17839 return p;
17840}
17841
17842 void SageInterface::changeAllLoopBodiesToBlocks(SgNode* top) {
17843 cerr<<"Warning: SageInterface::changeAllLoopBodiesToBlocks() is being replaced by SageInterface::changeAllBodiesToBlocks()."<<endl;
17844 cerr<<"Please use SageInterface::changeAllBodiesToBlocks() if you can."<<endl;
17846 }
17847
17848#endif
17849 void SageInterface::changeAllBodiesToBlocks(SgNode* top, bool createEmptyBody /*= true*/ ) {
17850 class Visitor: public AstSimpleProcessing {
17851 public:
17852 bool allowEmptyBody;
17853 Visitor (bool flag):allowEmptyBody(flag) {}
17854 virtual void visit(SgNode* n) {
17855
17856 bool wasPreviouslyModified = n->get_isModified();
17857
17858 switch (n->variantT()) {
17859 case V_SgForStatement: {
17860 ensureBasicBlockAsBodyOfFor(isSgForStatement(n));
17861 break;
17862 }
17863 case V_SgWhileStmt: {
17864 ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(n));
17865 break;
17866 }
17867 case V_SgDoWhileStmt: {
17868 ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(n));
17869 break;
17870 }
17871 case V_SgSwitchStatement: {
17872 ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(n));
17873 break;
17874 }
17875 case V_SgIfStmt: {
17876 ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(n));
17877 ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(n), allowEmptyBody);
17878#if 0
17879 // DQ (10/6/2015): Debugging why changes are being made to the AST for token-based unparsing.
17880 printf ("In changeAllBodiesToBlocks(): case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
17881#endif
17882#if 0
17883 // Reset this to false as a test.
17884 if (n->get_isModified() == true)
17885 {
17886 n->set_isModified(false);
17887 printf ("In changeAllBodiesToBlocks(): AFTER RESET: case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
17888 }
17889#endif
17890 break;
17891 }
17892 case V_SgCatchOptionStmt: {
17893 ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(n));
17894 break;
17895 }
17896 case V_SgUpcForAllStatement: {
17897 ensureBasicBlockAsBodyOfUpcForAll(isSgUpcForAllStatement(n));
17898 break;
17899 }
17900
17901 default:
17902 {
17903 if (isSgOmpBodyStatement(n))
17904 ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(n));
17905 break;
17906 }
17907 }
17908
17909 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17910 if (wasPreviouslyModified == false)
17911 {
17912 if (n->get_isModified() == true)
17913 {
17914#if 0
17915 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());
17916#endif
17917 n->set_isModified(false);
17918 }
17919
17920 }
17921
17922 }
17923 };
17924 Visitor(createEmptyBody).traverse(top, postorder);
17925 }
17926
17927
17928// Replace a given expression with a list of statements produced by a
17929// generator. The generator, when given a variable as input, must produce
17930// some code which leaves its result in the given variable. The output
17931// from the generator is then inserted into the original program in such a
17932// way that whenever the expression had previously been evaluated, the
17933// statements produced by the generator are run instead and their result is
17934// used in place of the expression.
17935// Assumptions: not currently traversing from or the statement it is in
17936void
17938 {
17939 // DQ (3/11/2006): The problem here is that the test expression for a "for loop" (SgForStmt)
17940 // is assumed to be a SgExpression. This was changed in Sage III as part of a bugfix and so
17941 // the original assumptions upon which this function was based are not incorrect, hence the bug!
17942 // Note that a number of cases were changed when this fix was made to SageIII (see documentation
17943 // for SgScopeStatement).
17944
17945#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
17946 SgStatement* enclosingStatement = getStatementOfExpression(from);
17947 SgExprStatement* exprStatement = isSgExprStatement(enclosingStatement);
17948
17949 SgForStatement* forStatement = isSgForStatement(enclosingStatement);
17950 SgReturnStmt* returnStatement = isSgReturnStmt(enclosingStatement);
17951 SgVariableDeclaration* varDeclarationStatement = isSgVariableDeclaration(enclosingStatement);
17952
17953
17954 // DQ (3/11/2006): Bugfix for special cases of conditional that are either SgStatement or SgExpression IR nodes.
17955
17956 ROSE_ASSERT (exprStatement || forStatement || returnStatement || varDeclarationStatement);
17957
17958 if (varDeclarationStatement)
17959 {
17961 }
17962 else
17963 {
17964 SgExpression* root = getRootOfExpression(from);
17965 ROSE_ASSERT (root);
17966 // printf ("root = %p \n",root);
17967 {
17968 if (forStatement && forStatement->get_increment() == root)
17969 {
17970 // printf ("Convert step of for statement \n");
17971 // Convert step of for statement
17972 // for (init; test; e) body; (where e contains from) becomes
17973 // for (init; test; ) {
17974 // body (with "continue" changed to "goto label");
17975 // label: e;
17976 // }
17977 // std::cout << "Converting for step" << std::endl;
17978 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(forStatement->get_increment());
17979 forStatement->get_increment()->set_parent(incrStmt);
17980
17981 SageInterface::addStepToLoopBody(forStatement, incrStmt);
17983 forStatement->set_increment(ne);
17984 ne->set_parent(forStatement);
17986 }
17987 else
17988 {
17989 SgStatement* enclosingStmtParent = isSgStatement(enclosingStatement->get_parent());
17990 assert (enclosingStmtParent);
17991 SgWhileStmt* whileStatement = isSgWhileStmt(enclosingStmtParent);
17992 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(enclosingStmtParent);
17993 SgIfStmt* ifStatement = isSgIfStmt(enclosingStmtParent);
17994 SgSwitchStatement* switchStatement = isSgSwitchStatement(enclosingStmtParent);
17995 SgForStatement* enclosingForStatement = isSgForStatement(enclosingStmtParent);
17996 if (enclosingForStatement && enclosingForStatement->get_test() == exprStatement)
17997 {
17998 // Convert test of for statement:
17999 // for (init; e; step) body; (where e contains from) becomes
18000 // for (init; true; step) {
18001 // bool temp;
18002 // temp = e;
18003 // if (!temp) break;
18004 // body;
18005 // }
18006 // in which "temp = e;" is rewritten further
18007 // std::cout << "Converting for test" << std::endl;
18008 pushTestIntoBody(enclosingForStatement);
18010 }
18011 else if (whileStatement && whileStatement->get_condition() == exprStatement)
18012 {
18013 // printf ("Convert while statements \n");
18014 // Convert while statement:
18015 // while (e) body; (where e contains from) becomes
18016 // while (true) {
18017 // bool temp;
18018 // temp = e;
18019 // if (!temp) break;
18020 // body;
18021 // }
18022 // in which "temp = e;" is rewritten further
18023 // std::cout << "Converting while test" << std::endl;
18024 pushTestIntoBody(whileStatement);
18025 // FixSgTree(whileStatement);
18027 }
18028 else if (doWhileStatement && doWhileStatement->get_condition() == exprStatement)
18029 {
18030 // printf ("Convert do-while statements \n");
18031 // Convert do-while statement:
18032 // do body; while (e); (where e contains from) becomes
18033 // {bool temp = true;
18034 // do {
18035 // body (with "continue" changed to "goto label";
18036 // label:
18037 // temp = e;} while (temp);}
18038 // in which "temp = e;" is rewritten further
18039 // std::cout << "Converting do-while test" << std::endl;
18040 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18041 // printf ("Building IR node #14: new SgBasicBlock = %p \n",new_statement);
18042 assert (doWhileStatement->get_parent());
18043 new_statement->set_parent(doWhileStatement->get_parent());
18044 myStatementInsert(doWhileStatement, new_statement, false);
18045 SageInterface::myRemoveStatement(doWhileStatement);
18046 SgName varname = "rose__temp1"; // Does not need to be unique, but must not be used in user code anywhere
18047 SgAssignInitializer* assignInitializer = buildAssignInitializer(
18048 buildBoolValExp(true));
18049 //SageInterface::getBoolType(doWhileStatement));
18051 varname, buildBoolType(), assignInitializer, new_statement);
18052
18053 SgInitializedName* initname = new_decl->get_variables().back();
18054 initname->set_scope(new_statement);
18055
18056 // DQ (12/14/2006): set the parent of the SgAssignInitializer to the variable (SgInitializedName).
18057 assignInitializer->set_parent(initname);
18058
18059#if 1
18060 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18062#else
18063 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18064 new_statement->insert_symbol(varname, varsym);
18065 varsym->set_parent(new_statement->get_symbol_table());
18066#endif
18067
18068 SageInterface::appendStatement(new_decl, new_statement);
18069 SageInterface::appendStatement(doWhileStatement, new_statement);
18070 assert (varsym);
18071 SgCastExp* castExp1 = buildCastExp(root,buildBoolType());
18072 SgVarRefExp* vr = buildVarRefExp(varsym);
18073 vr->set_lvalue(true);
18074
18075 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp1);
18076
18077 SageInterface::addStepToLoopBody(doWhileStatement, temp_setup);
18078 SgVarRefExp* varsymVr = buildVarRefExp(varsym);
18079
18081 varsymVr->set_parent(condStmt);
18082 doWhileStatement->set_condition(condStmt);
18083 condStmt->set_parent(doWhileStatement);
18085 }
18086 else if (ifStatement && ifStatement->get_conditional() == exprStatement)
18087 {
18088 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18089 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18090 assert (ifStatement->get_parent());
18091 new_statement->set_parent(ifStatement->get_parent());
18092 myStatementInsert(ifStatement, new_statement, false);
18094 SgName varname = "rose__temp2"; // Does not need to be unique, but must not be used in user code anywhere
18095 SgBoolValExp* trueVal = buildBoolValExp(true);
18096
18098
18100 buildBoolType(), ai,new_statement);
18101 SgInitializedName* initname = new_decl->get_variables().back();
18102 ai->set_parent(initname);
18103 initname->set_scope(new_statement);
18104#if 1
18105 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18107#else
18108 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18109 new_statement->insert_symbol(varname, varsym);
18110 varsym->set_parent(new_statement->get_symbol_table());
18111#endif
18112 SageInterface::appendStatement(new_decl, new_statement);
18113 ifStatement->set_parent(new_statement);
18114 assert (varsym);
18115
18116 SgCastExp* castExp2 = SageBuilder::buildCastExp(root, SageInterface::getBoolType(ifStatement));
18117 SgVarRefExp* vr = buildVarRefExp(varsym);
18118 vr->set_lvalue(true);
18119 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp2 );
18120 SageInterface::appendStatement(temp_setup, new_statement);
18121 SageInterface::appendStatement(ifStatement, new_statement);
18124 ifStatement->set_conditional(es);
18125 es->set_parent(ifStatement);
18127 }
18128 else if (switchStatement && switchStatement->get_item_selector() == exprStatement)
18129 {
18130 SgExpression* switchCond = exprStatement->get_expression();
18131 ROSE_ASSERT (switchCond);
18132 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18133 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18134 assert (switchStatement->get_parent());
18135 new_statement->set_parent(switchStatement->get_parent());
18136 myStatementInsert(switchStatement, new_statement, false);
18137 SageInterface::myRemoveStatement(switchStatement);
18138 SgName varname = "rose__temp3"; // Does not need to be unique, but must not be used in user code anywhere
18139 switchCond->set_parent(NULL);
18140 SgVariableDeclaration* new_decl = SageBuilder::buildVariableDeclaration(varname, switchCond->get_type(), SageBuilder::buildAssignInitializer(switchCond), new_statement);
18142 SageInterface::appendStatement(new_decl, new_statement);
18143 switchStatement->set_parent(new_statement);
18144 assert (varsym);
18145
18146
18147 SageInterface::appendStatement(switchStatement, new_statement);
18150 switchStatement->set_item_selector(es);
18151 es->set_parent(switchStatement);
18153 }
18154 else
18155 {
18156 // printf ("Handles expression and return statements \n");
18157 // Handles expression and return statements
18158 // std::cout << "Converting other statement" << std::endl;
18160 }
18161 }
18162 }
18163 }
18164
18165#endif
18166
18167 // printf ("Leaving replaceExpressionWithStatement(from,to) \n");
18168 }
18169
18178
18179// Similar to replaceExpressionWithStatement, but with more restrictions.
18180// Assumptions: from is not within the test of a loop or if
18181// not currently traversing from or the statement it is in
18183 {
18184
18185#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18186 SgStatement* stmt = getStatementOfExpression(from);
18187
18188 if (isSgExprStatement(stmt))
18189 {
18190 SgExpression* top = getRootOfExpression(from);
18191
18192
18193 if (top == from)
18194 {
18195 SgStatement* generated = to->generate(0);
18196 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18197 generated->set_parent(stmt->get_parent());
18198 return;
18199 }
18200 else
18201 {
18202 if (isSgAssignOp(top) && isSgAssignOp(top)->get_rhs_operand() == from)
18203 {
18204 SgAssignOp* t = isSgAssignOp(top);
18205 SgStatement* generated = to->generate(t->get_lhs_operand());
18206 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18207 generated->set_parent(stmt->get_parent());
18208 return;
18209 }
18210 else
18211 {
18212 // printf ("In replaceSubexpressionWithStatement(): Statement not generated \n");
18213 }
18214 }
18215 }
18216
18217 // cout << "1: " << getStatementOfExpression(from)->unparseToString() << endl;
18219 // cout << "2: " << getStatementOfExpression(from)->unparseToString() << endl;
18220 convertInitializerIntoAssignment(init);
18221 // cout << "3: " << getStatementOfExpression(from)->unparseToString() << endl;
18222 // cout << "3a: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18223 SgExprStatement* new_stmt = isSgExprStatement(getStatementOfExpression(from));
18224 assert (new_stmt != NULL); // Should now have this form because of conversion
18225 replaceAssignmentStmtWithStatement(new_stmt, to);
18226
18227 // printf ("In replaceSubexpressionWithStatement: new_stmt = %p = %s \n",new_stmt,new_stmt->class_name().c_str());
18228 // cout << "4: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18229
18230#endif
18231 }
18232
18233
18234 // Liao, 6/27/2008
18235 //Tasks
18236 // find all return statements
18237 // rewrite it to temp = expression; return temp; if expression is not a single value.
18238 // insert s right before 'return xxx;'
18240 {
18241 int result = 0;
18242 ROSE_ASSERT(func&&s);
18243 // vector<SgReturnStmt* > stmts = findReturnStmts(func);
18244 Rose_STL_Container <SgNode* > stmts = NodeQuery::querySubTree(func, V_SgReturnStmt);
18245 //vector<SgReturnStmt*>::iterator i;
18246 Rose_STL_Container<SgNode*>::iterator i;
18247 for (i=stmts.begin();i!=stmts.end();i++)
18248 {
18249 SgReturnStmt* cur_stmt = isSgReturnStmt(*i);
18250 ROSE_ASSERT(cur_stmt);
18251 SgExpression * exp = cur_stmt->get_expression();
18252 // TV (05/03/2011) Catch the case "return ;" where exp is NULL
18253 bool needRewrite = (exp != NULL) && !(isSgValueExp(exp));
18254 if (needRewrite)
18255 {
18256 splitExpression(exp);
18257 }
18258 // avoid reusing the statement
18259 if (result>=1 )
18260 s = copyStatement(s);
18261 insertStatementBefore(cur_stmt,s);
18262 result ++;
18263 } // for
18264 if (stmts.size()==0 ) // a function without any return at all,
18265 {
18266 SgBasicBlock * body = func->get_definition()->get_body();
18267 if (body== NULL)
18268 {
18269 cout<<"In instrumentEndOfFunction(), found an empty function body.! "<<endl;
18270 ROSE_ABORT();
18271 }
18272 appendStatement(s,body);
18273 result ++;
18274 }
18275 return result;
18276 } // instrumentEndOfFunction
18277
18279 {
18280 ROSE_ASSERT(stmt);
18281 return ((stmt->get_declarationModifier()).get_storageModifier()).isStatic();
18282 } // isStatic()
18283
18286 {
18287 ROSE_ASSERT(stmt);
18288 return ((stmt->get_declarationModifier()).get_storageModifier()).setStatic();
18289 }
18290
18292 {
18293 ROSE_ASSERT(stmt);
18294 return ((stmt->get_declarationModifier()).get_storageModifier()).isExtern();
18295 } // isExtern()
18296
18297
18300 {
18301 ROSE_ASSERT(stmt);
18302 return ((stmt->get_declarationModifier()).get_storageModifier()).setExtern();
18303 }
18304
18305 // Check if an SgInitializedName is "mutable' (has storage modifier set)
18307 {
18308 ROSE_ASSERT(name);
18309 return name->get_storageModifier().isMutable();
18310 }
18311
18312 // True if a parameter name is a Jovial output parameter
18314 {
18315 return isMutable(name);
18316 }
18317
18318 // Get a vector of Jovial input parameters from the function parameter list
18319 // TODO: Look into making this work for Fortran
18320 std::vector<SgInitializedName*> SageInterface::getInParameters(const SgInitializedNamePtrList &params)
18321 {
18322 std::vector<SgInitializedName*> in_params;
18323 BOOST_FOREACH (SgInitializedName* name, params)
18324 {
18325 if (!isJovialOutParam(name)) in_params.push_back(name);
18326 }
18327 return in_params;
18328 }
18329
18330 // Get a list of Jovial output parameters from the function parameter list
18331 // TODO: Look into making this work for Fortran
18332 std::vector<SgInitializedName*> SageInterface::getOutParameters(const SgInitializedNamePtrList &params)
18333 {
18334 std::vector<SgInitializedName*> out_params;
18335 BOOST_FOREACH (SgInitializedName* name, params)
18336 {
18337 if (isJovialOutParam(name)) out_params.push_back(name);
18338 }
18339 return out_params;
18340 }
18341
18343 switch (expr->variantT()) {
18344 case V_SgCharVal: return (long long)(isSgCharVal(expr)->get_value());
18345 case V_SgUnsignedCharVal: return isSgUnsignedCharVal(expr)->get_value();
18346 case V_SgShortVal: return (long long)(isSgShortVal(expr)->get_value());
18347 case V_SgUnsignedShortVal: return isSgUnsignedShortVal(expr)->get_value();
18348 case V_SgIntVal: return (long long)(isSgIntVal(expr)->get_value());
18349 case V_SgUnsignedIntVal: return isSgUnsignedIntVal(expr)->get_value();
18350 case V_SgLongIntVal: return (long long)(isSgLongIntVal(expr)->get_value());
18351 case V_SgUnsignedLongVal: return isSgUnsignedLongVal(expr)->get_value();
18352 case V_SgLongLongIntVal: return isSgLongLongIntVal(expr)->get_value();
18353 case V_SgUnsignedLongLongIntVal: return isSgUnsignedLongLongIntVal(expr)->get_value();
18354 case V_SgBoolValExp: return (long long )(isSgBoolValExp(expr)->get_value());
18355
18356 // DQ (2/18/2015): Make this a better error message.
18357 // default: ROSE_ASSERT (!"Bad kind in getIntegerConstantValue");
18358 default:
18359 {
18360 printf ("ERROR: In SageInterface::getIntegerConstantValue(): default reached: expr = %p = %s \n",expr,expr->class_name().c_str());
18361 ROSE_ASSERT (false);
18362 }
18363
18364 }
18365
18366 ROSE_ASSERT (!"Bad kind return in getIntegerConstantValue");
18367 return 0;
18368 }
18369
18370
18371#ifdef ROSE_ENABLE_BINARY_ANALYSIS
18372// tps : 28 Oct 2008 - support for finding the main interpretation
18373// rpm : 18 Sep 2009 - rewritten to support multiple files per interpretation
18377SageInterface::getMainInterpretation(SgAsmGenericFile *file)
18378{
18379 SgBinaryComposite *binary = getEnclosingNode<SgBinaryComposite>(file);
18380 ROSE_ASSERT(binary!=NULL);
18381
18382 /* Find the only header or the PE header of this file */
18383 SgAsmGenericHeader *requisite_header = NULL; /*the returned interpretation must point to this header*/
18384 const SgAsmGenericHeaderPtrList &headers = file->get_headers()->get_headers();
18385 if (1==headers.size()) {
18386 requisite_header = headers[0];
18387 } else {
18388 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18389 if (isSgAsmPEFileHeader(*hi)) {
18390 requisite_header = isSgAsmPEFileHeader(*hi);
18391 break;
18392 }
18393 }
18394 }
18395 ROSE_ASSERT(requisite_header!=NULL);
18396
18397 /* Find an interpretation that points to this header */
18398 const SgAsmInterpretationPtrList &interps = binary->get_interpretations()->get_interpretations();
18399 for (SgAsmInterpretationPtrList::const_iterator ii=interps.begin(); ii!=interps.end(); ++ii) {
18400 const SgAsmGenericHeaderPtrList &headers = (*ii)->get_headers()->get_headers();
18401 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18402 if ((*hi)==requisite_header)
18403 return *ii;
18404 }
18405 }
18406
18407 ROSE_ASSERT(!"no appropriate interpretation");
18408 return NULL;
18409}
18410#endif
18411
18413 {
18414 public:
18415 // This is the simpliest possible version of a deep copy SgCopyHelp::copyAst() member function.
18416 // Note that the root of the does not have its file info set like its children.
18417 virtual SgNode *copyAst(const SgNode *n)
18418 {
18419 // DQ (2/26/2009): This defines a simple concept of "deep" copy. It forms a more testable building block, I hope.
18420 SgNode* copy = n->copy(*this);
18421
18422 // Also mark this as a transformation and to be output in unparsing (so it will be output by the code generator).
18423 Sg_File_Info* fileInfo = copy->get_file_info();
18424 if (fileInfo != NULL)
18425 {
18426 // Must make this for output (checked in unparser), marking as a transformation is not checked
18427 fileInfo->setOutputInCodeGeneration();
18428 fileInfo->setTransformation();
18429 }
18430
18431 return copy;
18432 }
18433 } collectDependentDeclarationsCopyType;
18434
18435
18437 {
18438 // This traversal collects the includes at the top of a file.
18439
18440 public:
18441 vector<PreprocessingInfo*> cppDirectiveList;
18442
18443 void visit(SgNode *astNode);
18444 };
18445
18446
18447void
18449 {
18450 SgLocatedNode* locatedNode = isSgLocatedNode(astNode);
18451 if (locatedNode != NULL)
18452 {
18453 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
18454
18455 if (comments != NULL)
18456 {
18457#if 0
18458 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18459#endif
18460 AttachedPreprocessingInfoType::iterator i;
18461 for (i = comments->begin(); i != comments->end(); i++)
18462 {
18463 ROSE_ASSERT ( (*i) != NULL );
18464#if 0
18465 printf (" Attached Comment (relativePosition=%s): %s\n",
18466 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18467 (*i)->getString().c_str());
18468 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
18469 (*i)->get_file_info()->display("comment/directive location");
18470#endif
18471
18472 // We only save the #include directives, but likely we should be collecting ALL directives to
18473 // avoid the collection of #include that is meant to be hidden in an #if 0 ... #endif pairing.
18474 // if ((*i)->getTypeOfDirective() == PreprocessingInfo::CpreprocessorIncludeDeclaration)
18475 {
18476 // This is an include directive.
18477 cppDirectiveList.push_back(*i);
18478#if 0
18479 printf (" Attached include directive (relativePosition=%s): %s\n",
18480 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18481 (*i)->getString().c_str());
18482#endif
18483 }
18484 }
18485 }
18486 else
18487 {
18488#if 0
18489 printf ("No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18490#endif
18491 }
18492 }
18493 }
18494
18495
18496// This is part of a mechanism to collect directives from code that is to be outlined.
18497// However if we collect include directives we likely should really be collecting ALL
18498// directives (since the #include could be inside of an #if 0 ... #endif pairing.
18499// This level of detail will be addressed later (in an iterative approach).
18500vector<PreprocessingInfo*>
18501collectCppDirectives ( SgSourceFile* file )
18502 {
18503 // This function is used to collect include directives from the whole file.
18505 t.traverse(file,preorder);
18506
18507 return t.cppDirectiveList;
18508 }
18509
18510
18511vector<PreprocessingInfo*>
18512collectCppDirectives ( SgLocatedNode* n )
18513 {
18514 // This function is used to collect include directives from specific dependent declarations.
18516 t.traverse(n,preorder);
18517
18518 return t.cppDirectiveList;
18519 }
18520
18521// Debugging support.
18522void
18523outputPreprocessingInfoList ( const vector<PreprocessingInfo*> & l )
18524 {
18525 // This function support debugging the generated directive lists.
18526
18527 vector<PreprocessingInfo*>::const_iterator i = l.begin();
18528 while ( i != l.end() )
18529 {
18530 printf (" Attached include directive (relativePosition=%s): %s\n",
18531 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18532 (*i)->getString().c_str());
18533 i++;
18534 }
18535 }
18536
18537
18538
18540getAssociatedDeclaration( SgScopeStatement* scope )
18541 {
18542 //TODO This should become a member of SgScopeStatement
18543
18544 SgDeclarationStatement* declaration = NULL;
18545 switch(scope->variantT())
18546 {
18547 case V_SgNamespaceDefinitionStatement:
18548 {
18549 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
18550 declaration = namespaceDefinition->get_namespaceDeclaration();
18551 break;
18552 }
18553
18554 case V_SgClassDefinition:
18555 case V_SgTemplateInstantiationDefn: // Liao, 5/12/2009
18556 {
18557 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
18558 declaration = classDefinition->get_declaration();
18559 break;
18560 }
18561
18562 default:
18563 {
18564 printf ("Error: default reached in getAssociatedDeclaration(): scope = %p = %s \n",scope,scope->class_name().c_str());
18565 ROSE_ABORT();
18566 }
18567 }
18568
18569 // There may be some scopes that don't have an associated declaration.
18570 ROSE_ASSERT(declaration != NULL);
18571
18572 return declaration;
18573 }
18574
18575
18577 {
18578 public:
18579 // Accumulate a list of copies of associated declarations referenced in the AST subtree
18580 // (usually of the outlined functions) to insert in the separate file to support outlining.
18581 vector<SgDeclarationStatement*> declarationList;
18582
18583 // Save the list of associated symbols of dependent declarations identified so that we can
18584 // support their replacement in the new AST.
18585 vector<SgSymbol*> symbolList;
18586
18587 // Keep track of declarations already copied so that we don't copy them more than once and try to insert them.
18588 set<SgDeclarationStatement*> alreadySavedDeclarations;
18589
18590 // Required visit function for the AST traversal
18591 void visit(SgNode *astNode);
18592 private:
18593 void addDeclaration(SgDeclarationStatement* decl);
18594 };
18595
18597getGlobalScopeDeclaration( SgDeclarationStatement* inputDeclaration )
18598 {
18599 // DQ (2/16/2009): Basically if a class is used from a namespace (or any outer scope) and we
18600 // outline the reference to the class, we have to declare not the class but the outer scope
18601 // (which will have the class included).
18602
18603 SgDeclarationStatement* returnDeclaration = inputDeclaration;
18604
18605 // I think that we have to copy the outer scope if the declaration's scope is not SgGlobal.
18606 SgScopeStatement* scope = inputDeclaration->get_scope();
18607 ROSE_ASSERT(scope != NULL);
18608
18609 // printf ("inputDeclaration->get_scope() = %p = %s \n",scope,scope->class_name().c_str());
18610
18611 // If the input declaration is not in global scope then find the parent declaration that is in global scope!
18612 SgGlobal* globalScope = isSgGlobal(scope);
18613 if (globalScope == NULL)
18614 {
18615 // Traverse back to the global scope to include outer declarations which contain the "declaration"
18616 // printf ("Traverse back to the global scope to include outer declarations \n");
18617
18618 SgScopeStatement* parentScope = scope;
18619 SgDeclarationStatement* associatedDeclaration = returnDeclaration;
18620 ROSE_ASSERT(parentScope != NULL);
18621 while (globalScope == NULL)
18622 {
18623 associatedDeclaration = getAssociatedDeclaration(parentScope);
18624 ROSE_ASSERT(associatedDeclaration != NULL);
18625
18626 parentScope = parentScope->get_scope();
18627 globalScope = isSgGlobal(parentScope);
18628 }
18629
18630 returnDeclaration = associatedDeclaration;
18631 }
18632
18633 return returnDeclaration;
18634 }
18635
18636
18637// Debugging support.
18638void
18639outputDeclarationList ( const vector<SgDeclarationStatement*> & l )
18640 {
18641 // This function support debugging the generated declarations.
18642
18643 int counter = 0;
18644 vector<SgDeclarationStatement*>::const_iterator i = l.begin();
18645 while ( i != l.end() )
18646 {
18647 printf ("In outputDeclarationList(): list[%d] = %p = %s = %s \n",counter++,*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
18648 i++;
18649 }
18650 }
18651
18652void CollectDependentDeclarationsTraversal::addDeclaration(SgDeclarationStatement* declaration)
18653{
18654 // If there was a declaration found then handle it.
18655 if (declaration != NULL)
18656 {
18657 // Reset the defining declaration in case there is an outer declaration that is more important
18658 // to consider the dependent declaration (e.g. a class in a namespace). In general this will
18659 // find the associated outer declaration in the global scope.
18660 SgDeclarationStatement* dependentDeclaration = getGlobalScopeDeclaration(declaration);
18661
18662 // This declaration is in global scope so we just copy the declaration
18663 // For namespace declarations: they may have the save name but they have to be saved separated.
18664 if (alreadySavedDeclarations.find(dependentDeclaration) == alreadySavedDeclarations.end())
18665 {
18666#if 0
18667 printf ("In CollectDependentDeclarationsTraversal::visit(): selected dependentDeclaration = %p = %s = %s \n",
18668 dependentDeclaration,dependentDeclaration->class_name().c_str(),SageInterface::get_name(dependentDeclaration).c_str());
18669#endif
18670 // DQ (2/22/2009): Semantics change for this function, just save the original declaration, not a copy of it.
18671 declarationList.push_back(dependentDeclaration);
18672
18673 // Record this as a copied declaration
18674 alreadySavedDeclarations.insert(dependentDeclaration);
18675#if 0
18676 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18677 printf ("############### ADDING dependentDeclaration = %p = %s to alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18678 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18679#endif
18680 // DQ (2/21/2009): Added assertions (will be inforced in SageInterface::appendStatementWithDependentDeclaration()).
18681 // ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
18682 }
18683 else
18684 {
18685#if 0
18686 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18687 printf ("############### EXISTING dependentDeclaration = %p = %s found in alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18688 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18689#endif
18690 }
18691 }
18692}
18693
18695static std::vector<SgTypedefDeclaration*> collectTypedefDeclarations(SgType* type)
18696{
18697 ROSE_ASSERT(type != NULL);
18698 std::vector<SgTypedefDeclaration*> result;
18699 SgType* currentType = type;
18700
18701 SgModifierType* modType = NULL;
18702 SgPointerType* pointType = NULL;
18703 SgReferenceType* refType = NULL;
18704 SgArrayType* arrayType = NULL;
18705 SgTypedefType* typedefType = NULL;
18706
18707 while (true)
18708 {
18709 modType = isSgModifierType(currentType);
18710 if(modType)
18711 {
18712 currentType = modType->get_base_type();
18713 }
18714 else
18715 {
18716 refType = isSgReferenceType(currentType);
18717 if(refType)
18718 {
18719 currentType = refType->get_base_type();
18720 }
18721 else
18722 {
18723 pointType = isSgPointerType(currentType);
18724 if ( pointType)
18725 {
18726 currentType = pointType->get_base_type();
18727 }
18728 else
18729 {
18730 arrayType = isSgArrayType(currentType);
18731 if (arrayType)
18732 {
18733 currentType = arrayType->get_base_type();
18734 }
18735 else
18736 {
18737 typedefType = isSgTypedefType(currentType);
18738 if (typedefType)
18739 {
18740 currentType = typedefType->get_base_type();
18741 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(typedefType->get_declaration());
18742 // have to try to get the defining declaration for a defining typedef declaration
18743 // otherwise AST traversal will not visit the non-defining one for a defining typedef declaration
18744 // sortSgNodeListBasedOnAppearanceOrderInSource() won't work properly
18745 SgTypedefDeclaration* decl = isSgTypedefDeclaration(tdecl->get_definingDeclaration());
18746 if (decl ==NULL)
18747 decl = tdecl;
18748 result.push_back(decl);
18749 }
18750 else
18751 {
18752 // Exit the while(true){} loop!
18753 break;
18754 }
18755 }
18756 }
18757 }
18758 }
18759 }
18760#if 0
18761 // debug here
18762 if (result.size()>0)
18763 {
18764 cout<<"------------Found a chain of typedef decls: count="<<result.size()<<endl;
18765 for (vector <SgTypedefDeclaration*>::const_iterator iter = result.begin();
18766 iter!=result.end(); iter ++)
18767 cout<<(*iter)->unparseToString()<<endl;
18768 }
18769#endif
18770 return result;
18771}
18772
18774void
18776 {
18777 // Statements that can cause us to have declaration dependences:
18778 // 1) variable declarations (through their types)
18779 // 2) function calls
18780 // 3) typedefs (through their base types)
18781 // Not implemented:
18782 // 4) static member functions (through their class)
18783 // 5) static data members (through their class)
18784 // 6) namespaces
18785 // 7) #include<> CPP directives.
18786
18787 // DQ (2/22/2009): Changing the semantics for this function,
18788 // just save the original declaration, not a copy of it.
18789
18790#if 0
18791 // Debugging support.
18792 Sg_File_Info* fileInfo = astNode->get_file_info();
18793 if (fileInfo != NULL && fileInfo->isFrontendSpecific() == false && (isSgStatement(astNode) != NULL) )
18794 {
18795 printf ("\n\nIn CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18796 // fileInfo->display("In CollectDependentDeclarationsTraversal::visit()");
18797 int counter = 0;
18798 printf ("alreadySavedDeclarations.size() = %" PRIuPTR " \n",alreadySavedDeclarations.size());
18799 for (set<SgDeclarationStatement*>::iterator i = alreadySavedDeclarations.begin(); i != alreadySavedDeclarations.end(); i++)
18800 {
18801 printf ("alreadySavedDeclarations %d: %p = %s \n",counter++,*i,(*i)->class_name().c_str());
18802 }
18803 }
18804#endif
18805
18806 // The following conditionals set this variable
18807 SgDeclarationStatement* declaration = NULL;
18808
18809 // 1) ------------------------------------------------------------------
18810 // Collect the declarations associated with referenced types in variable declarations (or any types associated with SgInitializedName IR nodes)
18811 SgInitializedName* initializedname = isSgInitializedName(astNode);
18812 if (initializedname != NULL)
18813 {
18814 SgType* type = initializedname->get_type();
18815
18816 // handle all dependent typedef declarations, if any
18817 std::vector <SgTypedefDeclaration*> typedefVec = collectTypedefDeclarations(type);
18818 for (std::vector <SgTypedefDeclaration*>::const_iterator iter =typedefVec.begin();
18819 iter != typedefVec.end(); iter++)
18820 {
18821 SgTypedefDeclaration* typedef_decl = *iter;
18822 addDeclaration(typedef_decl);
18823 symbolList.push_back(typedef_decl->get_symbol_from_symbol_table());
18824 }
18825
18826 // handle base type:
18827
18828 // We now can to strip typedefs since they are already handled by collectTypedefDeclarations()
18829 // this also reach to the defining body of a defining typedef declaration
18830 // and treat it as an independent declarations,
18831 // the assumption here is that a defining typedef declaration will only has its
18832 // nondefining declaration copied to avoid redefining of the struct.
18833 // This is also a workaround for an AST copy bug: defining body gets lost after copying
18834 // a defining typedef declaration.
18835 // Liao, 5/8/2009
18836 //
18837 // e.g. typedef struct hypre_BoxArray_struct
18838 // {
18839 // int alloc_size;
18840 // } hypre_BoxArray;
18841 //
18842 // struct hypre_BoxArray_struct will be treated as a strippedType and its declaration
18843 // will be inserted.
18844 //
18845 SgType* strippedType = type->stripType();
18846 SgNamedType* namedType = isSgNamedType(strippedType);
18847 if (namedType != NULL)
18848 {
18849 // Note that since this was obtained via the types and types are shared, this is the non-defining
18850 // declaration in original program (not the separate file is this is to support outlining into a
18851 // separate file.
18852 SgDeclarationStatement* named_decl = namedType->get_declaration();
18853 // the case of class declaration, including struct, union
18854 SgClassDeclaration* classDeclaration = isSgClassDeclaration(named_decl);
18855 if (classDeclaration != NULL)
18856 {
18857 // printf ("Found class declaration: classDeclaration = %p \n",classDeclaration);
18858 declaration = classDeclaration->get_definingDeclaration();
18859 // Liao, 12/09/2016.
18860 // In some cases, forward declaration of class types are used and sufficient, without providing defining declaration.
18861 // We should allow this.
18862 if (declaration != NULL)
18863 {
18864 // ROSE_ASSERT(declaration != NULL);
18865 addDeclaration(declaration);
18866 }
18867 else
18868 addDeclaration (classDeclaration); // we use the original forward declaration.
18869
18870 // Note that since types are shared in the AST, the declaration for a named type may be (is)
18871 // associated with the class declaration in the original file. However, we want to associated
18872 // class declaration in the current file, but since the AST copy mechanism work top-down, this
18873 // mapping form the declaration in the original file to the new declaration in the copied AST
18874 // is available in the SgCopyHelp map of copied IR nodes.
18875 // DQ (3/3/2009): Added support for symbol references to be saved (symbols in the original file).
18876 // these symbols will be mapped to their new symbols.
18877 ROSE_ASSERT(classDeclaration->hasAssociatedSymbol() == true);
18878 SgSymbol* classSymbol = classDeclaration->get_symbol_from_symbol_table();
18879 ROSE_ASSERT(classSymbol != NULL);
18880
18881 // printf ("Saving classSymbol = %p \n",classSymbol);
18882 symbolList.push_back(classSymbol);
18883 }
18884
18885 // handle Enum types
18886 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(named_decl);
18887 if (enum_decl != NULL)
18888 {
18889 declaration = enum_decl->get_definingDeclaration();
18890 ROSE_ASSERT(declaration != NULL);
18891 addDeclaration(declaration);
18892 ROSE_ASSERT(enum_decl->hasAssociatedSymbol() == true);
18893 // Liao 12/14/2012. use search_for_symbol_from_symbol_table() instead to avoid the defining/nondefing decl issue
18894 //SgSymbol* esymbol = enum_decl->get_symbol_from_symbol_table();
18895 SgSymbol* esymbol = enum_decl->search_for_symbol_from_symbol_table();
18896 ROSE_ASSERT(esymbol!= NULL);
18897 symbolList.push_back(esymbol);
18898 }
18899 } // end if namedType
18900#if 0
18901 printf ("Found reference to type = %p = %s strippedType = %p = %s \n",type,type->class_name().c_str(),strippedType,strippedType->class_name().c_str());
18902#endif
18903 }// end if (initializedname)
18904
18905 // 2) ------------------------------------------------------------------
18906 // Collect declarations associated with function calls.
18907 SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
18908 if (functionCallExp != NULL)
18909 {
18910 declaration = functionCallExp->getAssociatedFunctionDeclaration();
18911 //ROSE_ASSERT(declaration != NULL);
18912 // We allow a function pointer to have no specific declaration associated.
18913 if (declaration != NULL)
18914 addDeclaration(declaration);
18915
18916 // DQ (3/2/2009): Added support for symbol references to be saved (this can be a SgFunctionSymbol or a SgMemberFunctionSymbol).
18917 SgSymbol* functionSymbol = functionCallExp->getAssociatedFunctionSymbol();
18918 //ROSE_ASSERT(functionSymbol != NULL);
18919
18920 // printf ("Saving functionSymbol = %p \n",functionSymbol);
18921 if (functionSymbol)
18922 symbolList.push_back(functionSymbol);
18923 }
18924
18925 // 3) ------------------------------------------------------------------
18926 // Collect enumerate declarations associated with SgEnumVal
18927 SgEnumVal * eval = isSgEnumVal(astNode);
18928 if (eval != NULL)
18929 {
18930 declaration = eval->get_declaration();
18931 ROSE_ASSERT(declaration != NULL);
18932 addDeclaration(declaration);
18934 ROSE_ASSERT(symbol != NULL);
18935 symbolList.push_back(symbol);
18936 }
18937// addDeclaration(declaration); // do it in different cases individually
18938 }
18939
18940static std::map<const SgStatement*, bool> visitedDeclMap; // avoid infinite recursion
18941
18942
18944// Used to separate a function to a new source file and add necessary type declarations into the new file.
18945// NOTICE: each call to this function has to have call visitedDeclMap.clear() first!!
18946static void
18947getDependentDeclarations (SgStatement* stmt, vector<SgDeclarationStatement*> & declarationList, vector<SgSymbol*> & symbolList )
18948{
18949 // This function returns a list of the dependent declaration for any input statement.
18950 // Dependent declaration are functions called, types referenced in variable declarations, etc.
18951#if 0
18952 printf ("\n\n********************************************************** \n");
18953 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
18954 printf ("********************************************************** \n");
18955#endif
18956 visitedDeclMap[stmt]= true;
18958 t.traverse(stmt,preorder);
18959#if 0
18960 declarationList = t.declarationList;
18961 symbolList = t.symbolList;
18962#else
18963 // Merge to the parent level list
18964 copy(t.declarationList.begin(),t.declarationList.end(), back_inserter(declarationList));
18965 copy(t.symbolList.begin(),t.symbolList.end(), back_inserter(symbolList));
18966 // make their elements unique
18967 sort (declarationList.begin(), declarationList.end());
18968 vector<SgDeclarationStatement*>::iterator new_end = unique(declarationList.begin(), declarationList.end());
18969 declarationList.erase(new_end, declarationList.end());
18970
18971 sort (symbolList.begin(), symbolList.end());
18972 vector<SgSymbol*>::iterator end2 = unique(symbolList.begin(), symbolList.end());
18973 symbolList.erase(end2, symbolList.end());
18974
18975
18976 // Liao, 5/7/2009 recursively call itself to get dependent declarations' dependent declarations
18977 for (vector<SgDeclarationStatement*>::const_iterator iter = t.declarationList.begin();
18978 iter !=t.declarationList.end(); iter++)
18979 {
18980 SgDeclarationStatement* decl = *iter;
18981 SgType* base_type = NULL;
18982 SgStatement* body_stmt= NULL;
18983
18984 // grab base type for a declaration
18985 // For class declaration: grab their
18986 if (isSgClassDeclaration(decl))
18987 {
18988 base_type = isSgClassDeclaration(decl)->get_type();
18989 } else
18990 if (isSgTypedefDeclaration(decl))
18991 {
18992
18993 // we don't want to strip of nested typedef declarations
18994 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);
18995 }
18996
18997 //TODO variable declaration, function declaration: parameter list types,
18998 // multiple base_type then
18999
19000 // is the base type associated with a defining body?
19001 // TODO enum type
19002 if (isSgClassType(base_type))
19003 {
19004 SgClassDeclaration* class_decl = isSgClassDeclaration(isSgClassType(base_type)->get_declaration()->get_definingDeclaration());
19005 if (class_decl!=NULL)
19006 {
19007 body_stmt = class_decl->get_definition();
19008 }
19009 }
19010 // recursively collect dependent declarations for the body stmt
19011 if ((body_stmt!=NULL) &&(!visitedDeclMap[body_stmt]))
19012 { // avoid infinite recursion
19013 getDependentDeclarations(body_stmt, declarationList, symbolList);
19014 }
19015 }
19016#endif
19017} // end void getDependentDeclarations()
19018
19019
19020// Reorder a list of declaration statements based on their appearance order in source files
19021// This is essential to insert their copies into a new file in a right order
19022// Liao, 5/7/2009
19023vector<SgDeclarationStatement*>
19024SageInterface::sortSgNodeListBasedOnAppearanceOrderInSource(const vector<SgDeclarationStatement*>& nodevec)
19025{
19026 vector<SgDeclarationStatement*> sortedNode;
19027
19028 if (nodevec.size()==0 )
19029 return sortedNode;
19030 // no need to sort if there is only 1 element
19031 if (nodevec.size() ==1)
19032 return nodevec;
19033
19035 Rose_STL_Container<SgNode*> queryResult = NodeQuery::querySubTree(project,V_SgDeclarationStatement);
19036 for (Rose_STL_Container<SgNode*>::const_iterator iter = queryResult.begin();
19037 iter!= queryResult.end(); iter++)
19038 {
19039 // cerr<<"Trying to match:"<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19040 SgNode* cur_node = *iter;
19041 SgDeclarationStatement* cur_stmt = isSgDeclarationStatement(cur_node);
19042 ROSE_ASSERT(cur_stmt!=NULL);
19043 // Liao 12/14/2012. It is possible nodevec contains a first non-defining function declaration since the function is called in the outlined function
19044 // This is true even if the AST only has a defining function declaration.
19045 //
19046 // But that first non-defining function declaration is not traversable in AST due to it is hidden.
19047 // The solution here is to for each defining function decl traversed, convert it to the first nondefining one to do the match.
19048 SgFunctionDeclaration * func_decl = isSgFunctionDeclaration (cur_stmt);
19049 if (func_decl)
19050 {
19051 if (func_decl->get_definingDeclaration() == func_decl )
19052 {
19053 cur_stmt = func_decl->get_firstNondefiningDeclaration();
19054 ROSE_ASSERT (cur_stmt != func_decl);
19055 }
19056 }
19057 vector<SgDeclarationStatement*>::const_iterator i = find (nodevec.begin(), nodevec.end(), cur_stmt);
19058 if (i!=nodevec.end())
19059 {
19060 // It is possible we already visited a real prototype func decl before, now we see a prototype converted from a defining declaration.
19061 // We have to make sure only one copy is inserted.
19062 vector<SgDeclarationStatement*>::const_iterator j = find (sortedNode.begin(), sortedNode.end(), *i);
19063 if (j == sortedNode.end())
19064 sortedNode.push_back(*i);
19065 }
19066 }
19067
19068 if (nodevec.size() != sortedNode.size())
19069 {
19070 cerr<<"Fatal error in sortSgNodeListBasedOnAppearanceOrderInSource(): nodevec.size() != sortedNode.size()"<<endl;
19071 cerr<<"nodevec() have "<< nodevec.size()<<" elements. They are:"<<endl;
19072 for (vector<SgDeclarationStatement*>::const_iterator iter = nodevec.begin(); iter != nodevec.end(); iter++)
19073 {
19074 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19075 }
19076 cerr<<"sortedNode() have " << sortedNode.size() <<" elements. They are:"<<endl;
19077 for (vector<SgDeclarationStatement*>::const_iterator iter = sortedNode.begin(); iter != sortedNode.end(); iter++)
19078 {
19079 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19080 }
19081
19082 ROSE_ASSERT(nodevec.size() == sortedNode.size());
19083 }
19084 return sortedNode;
19085}
19086
19088// This function clears a history map transparently and return a sorted list of dependent declarations
19089std::vector<SgDeclarationStatement*>
19091 {
19092 // This function returns a list of the dependent declaration for any input statement.
19093 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19094#if 0
19095 printf ("\n\n********************************************************** \n");
19096 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19097 printf ("********************************************************** \n");
19098
19100 t.traverse(stmt,preorder);
19101
19102 return t.declarationList;
19103#else
19104 // share a single implementation for recursive lookup for dependent declaration
19105 visitedDeclMap.clear();
19106 vector<SgDeclarationStatement*> declarationList;
19107 vector<SgSymbol*> symbolList;
19108 getDependentDeclarations(stmt, declarationList, symbolList);
19109 declarationList = sortSgNodeListBasedOnAppearanceOrderInSource(declarationList);
19110#if 0
19111 printf ("\n\n ********************************************************** \n");
19112 cout<<"Found dependent decl: count="<<declarationList.size()<<endl;
19113 for ( vector<SgDeclarationStatement*>::const_iterator iter = declarationList.begin();
19114 iter != declarationList.end(); iter++)
19115 {
19116 cout<<"\t"<<(*iter)->class_name()<<" at line "<<(*iter)->get_file_info()->get_line()<<endl;
19117 if ((*iter)->variantT()== V_SgFunctionDeclaration)
19118 cout<<"func name is:"<<isSgFunctionDeclaration(*iter)->get_name().getString()<<endl;
19119 //<<(*iter)->unparseToString()<<endl; // unparseToString() won't work on outlined function
19120 }
19121 printf ("\n ********************************************************** \n");
19122#endif
19123
19124 return declarationList;
19125
19126#endif
19127 }
19128
19129
19130bool
19132 {
19133 bool returnValue = false;
19134
19135#if 0
19136 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());
19137#endif
19138
19139 if (functionName.is_null() == false)
19140 {
19141 // DQ (1/20/2019): Add operator~() to this list (see test2019_10.C).
19142 if ( functionName == "operator++" || functionName == "operator--" || functionName == "operator&" ||
19143 functionName == "operator!" || functionName == "operator*" || functionName == "operator+" ||
19144 functionName == "operator-" || functionName == "operator+" || functionName == "operator~")
19145 {
19146 returnValue = true;
19147 }
19148 }
19149
19150 return returnValue;
19151 }
19152
19153
19154// DQ (4/13/2013): We need these to support the unparing of operators defined by operator syntax or member function names.
19156bool
19158 {
19159 // DQ (4/21/2013): Reimplemented this function to support more of the prefix operators.
19160 // Also we now support when they are defined as member functions and non-member functions.
19161
19162 bool returnValue = false;
19163
19164 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(exp);
19165 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19166 // ROSE_ASSERT(memberFunctionRefExp != NULL);
19167
19168 SgName functionName;
19169 size_t numberOfOperands = 0;
19170
19171 if (memberFunctionRefExp != NULL)
19172 {
19173 ROSE_ASSERT(functionRefExp == NULL);
19174 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19175 if (memberFunctionDeclaration != NULL)
19176 {
19177 functionName = memberFunctionDeclaration->get_name();
19178 numberOfOperands = memberFunctionDeclaration->get_args().size();
19179 }
19180 }
19181 else
19182 {
19183 // This could be "friend bool operator!(const X & x);"
19184 if (functionRefExp != NULL)
19185 {
19186 SgFunctionDeclaration* functionDeclaration = functionRefExp->getAssociatedFunctionDeclaration();
19187 if (functionDeclaration != NULL)
19188 {
19189 functionName = functionDeclaration->get_name();
19190 numberOfOperands = functionDeclaration->get_args().size();
19191 }
19192 }
19193 else
19194 {
19195 // Note clear if this should be an error.
19196 printf ("In SageInterface::isPrefixOperator(): unknown case of exp = %p = %s \n",exp,exp->class_name().c_str());
19197 }
19198 }
19199
19200#if 0
19201 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);
19202#endif
19203
19204 if (isPrefixOperatorName(functionName) == true)
19205 {
19206 if (memberFunctionRefExp != NULL)
19207 {
19208 // This case is for member functions.
19209 ROSE_ASSERT(functionRefExp == NULL);
19210 if (numberOfOperands == 0)
19211 {
19212 // This is the C++ signature for the operator++() prefix operator.
19213 returnValue = true;
19214 }
19215 else
19216 {
19217 // This is the C++ signature for the operator++() postfix operator.
19218 returnValue = false;
19219 }
19220 }
19221 else
19222 {
19223 // This case is for non-member functions.
19224 ROSE_ASSERT(functionRefExp != NULL);
19225 ROSE_ASSERT(memberFunctionRefExp == NULL);
19226 if (numberOfOperands == 1)
19227 {
19228 // This is the C++ signature for the operator++() prefix operator.
19229 returnValue = true;
19230 }
19231 else
19232 {
19233 // This is the C++ signature for the operator++() postfix operator.
19234 ROSE_ASSERT(numberOfOperands == 2);
19235 returnValue = false;
19236 }
19237 }
19238 }
19239
19240#if 0
19241 printf ("Leaving SageInterface::isPrefixOperator(): returnValue = %s \n",returnValue ? "true" : "false");
19242#endif
19243
19244 return returnValue;
19245 }
19246
19247
19249bool
19251 {
19252 return ( (isPrefixOperator(exp) == false) && (isIndexOperator(exp) == false) );
19253 }
19254
19255
19257bool
19259 {
19260 bool returnValue = false;
19261 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19262 if (memberFunctionRefExp == NULL)
19263 return false;
19264
19265 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19266 if (memberFunctionDeclaration != NULL)
19267 {
19268 SgName functionName = memberFunctionDeclaration->get_name();
19269 if ( (functionName == "operator[]") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19270 {
19271 returnValue = true;
19272 }
19273 else
19274 {
19275 if ( (functionName == "operator()") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19276 {
19277 returnValue = true;
19278 }
19279 else
19280 {
19281 returnValue = false;
19282 }
19283 }
19284 }
19285
19286 return returnValue;
19287 }
19288
19289
19290// DQ (1/10/2014): Adding more general support for token based unparsing.
19292SageInterface::lastStatementOfScopeWithTokenInfo (SgScopeStatement* scope, std::map<SgNode*,TokenStreamSequenceToNodeMapping*> & tokenStreamSequenceMap)
19293 {
19294 // Return the last statement in the associated scope that has token information.
19295 SgStatement* lastStatement = NULL;
19296
19297 ROSE_ASSERT(scope != NULL);
19298
19299#if 0
19300 printf ("In SageInterface::lastStatementOfScopeWithTokenInfo(): scope = %p = %s \n",scope,scope->class_name().c_str());
19301#endif
19302
19303 SgIfStmt* ifStatement = isSgIfStmt(scope);
19304 if (ifStatement != NULL)
19305 {
19306 lastStatement = ifStatement->get_false_body();
19307 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19308 {
19309 lastStatement = ifStatement->get_true_body();
19310 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19311 {
19312 lastStatement = NULL;
19313 }
19314 }
19315
19316 printf ("Note: SgIfStmt scope in SageInterface::lastStatementOfScopeWithTokenInfo(): returning lastStatement = %p \n",lastStatement);
19317 if (lastStatement != NULL)
19318 {
19319 printf (" --- lastStatement = %p = %s \n",lastStatement,lastStatement->class_name().c_str());
19320 }
19321
19322 return lastStatement;
19323 }
19324
19325 SgStatementPtrList statementList = scope->generateStatementList();
19326 if (statementList.rbegin() != statementList.rend())
19327 {
19328 // Find the last statement with token stream information.
19329 SgStatementPtrList::reverse_iterator i = statementList.rbegin();
19330
19331 while (i != statementList.rend() && (tokenStreamSequenceMap.find(*i) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[*i] == NULL) )
19332 {
19333 i++;
19334 }
19335
19336 if (i == statementList.rend())
19337 {
19338 lastStatement = NULL;
19339 }
19340 else
19341 {
19342 lastStatement = *i;
19343 }
19344 }
19345
19346 return lastStatement;
19347 }
19348
19349
19350void
19352 {
19353 // DQ (8/12/2020): Check the access permissions of all defining and nodefining declarations (debugging support for Cxx_tests/test2020_28.C).
19354
19355 class DeclarationTraversal : public AstSimpleProcessing
19356 {
19357 public:
19358 // DeclarationTraversal() {}
19359
19360 void visit (SgNode* node)
19361 {
19362 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
19363 if (decl != NULL)
19364 {
19365 SgDeclarationStatement* definingDeclaration = isSgDeclarationStatement(decl->get_definingDeclaration());
19366 SgDeclarationStatement* firstNondefiningDeclaration = isSgDeclarationStatement(decl->get_firstNondefiningDeclaration());
19367 SgDeclarationStatement* otherDeclaration = NULL;
19368
19369 // Output access modifier information for each declaration.
19370 printf ("Found declaration = %p = %s name = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
19371 if (decl != definingDeclaration && decl != firstNondefiningDeclaration)
19372 {
19373 otherDeclaration = decl;
19374 }
19375
19376 if (definingDeclaration != NULL)
19377 {
19378 definingDeclaration->get_declarationModifier().get_accessModifier().display("definingDeclaration: accessModifier");
19379 }
19380
19381 if (firstNondefiningDeclaration != NULL)
19382 {
19383 firstNondefiningDeclaration->get_declarationModifier().get_accessModifier().display("firstNondefiningDeclaration: accessModifier");
19384 }
19385
19386 if (otherDeclaration != NULL)
19387 {
19388 otherDeclaration->get_declarationModifier().get_accessModifier().display("otherDeclaration: accessModifier");
19389 }
19390
19391 // Adding space for formatting.
19392 printf ("\n");
19393 }
19394 }
19395 };
19396
19397 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19398 DeclarationTraversal traversal;
19399 traversal.traverse(astNode, preorder);
19400 }
19401
19402
19403void
19405 {
19406 // DQ (8/14/2020): Check the symbol tables for specific scopes (debugging support).
19407
19408 class ScopeTraversal : public AstSimpleProcessing
19409 {
19410 public:
19411 void visit (SgNode* node)
19412 {
19413 SgScopeStatement* scope = isSgScopeStatement(node);
19414 if (scope != NULL)
19415 {
19416 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
19417 if (functionDefinition != NULL)
19418 {
19419 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
19420 ROSE_ASSERT(functionDeclaration != NULL);
19421
19422 string functionName = functionDeclaration->get_name();
19423
19424 printf ("functionName = %s \n",functionName.c_str());
19425
19426 if (functionName == "main")
19427 {
19428
19429 SgBasicBlock* functionBody = functionDefinition->get_body();
19430 ROSE_ASSERT(functionBody != NULL);
19431 SgSymbolTable* symbolTable = functionBody->get_symbol_table();
19432 ROSE_ASSERT(symbolTable != NULL);
19433
19434 // Print out the symbol table.
19435 symbolTable->print();
19436 }
19437 }
19438
19439 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
19440 if (namespaceDefinition != NULL)
19441 {
19442 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
19443 ROSE_ASSERT(namespaceDeclaration != NULL);
19444
19445 string namespaceName = namespaceDeclaration->get_name();
19446
19447 printf ("namespaceName = %s \n",namespaceName.c_str());
19448
19449 if (namespaceName == "B")
19450 {
19451 SgSymbolTable* symbolTable = namespaceDefinition->get_symbol_table();
19452 ROSE_ASSERT(symbolTable != NULL);
19453
19454 // Print out the symbol table.
19455 symbolTable->print();
19456 }
19457 }
19458 }
19459 }
19460 };
19461
19462 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19463 ScopeTraversal traversal;
19464 traversal.traverse(astNode, preorder);
19465 }
19466
19467//Jim Leek TODO (07/25/2023): After Dan merges his branch, please clean up all the #1f 0 stuff
19468void SageInterface::markNodeToBeUnparsed(SgNode* node, int physical_file_id)
19469 {
19470#if 0
19471 Sg_File_Info* fileInfo=node->get_file_info();
19472 if (fileInfo != NULL)
19473 {
19474 fileInfo->setTransformation();
19475 fileInfo->setOutputInCodeGeneration();
19476
19477 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19478 if (locatedNode != NULL)
19479 {
19480 // DQ (7/7/2015): Make the subtree as transformed.
19481 locatedNode->setTransformation();
19482 locatedNode->setOutputInCodeGeneration();
19483
19484 // DQ (7/8/2021): Added assertion.
19485 ROSE_ASSERT(locatedNode->get_file_info() != NULL);
19486#if 0
19487 printf ("In markNodeToBeUnparsed(): physical_file_id = %d \n",physical_file_id);
19488#endif
19489 // DQ (10/26/2020): Set the physical_file_id, required for ueader file unparsing (is it?).
19490 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19491#if 1
19492 printf ("Note: calling node markTransformationsForOutput(): node = %p = %s \n",node,node->class_name().c_str());
19493#endif
19494 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19495 // to call setTransformation() and setOutputInCodeGeneration().
19496 markTransformationsForOutput(node);
19497 }
19498 else
19499 {
19500#if 0
19501 printf ("Note: node is not a SgLocatedNode: node = %p = %s \n",node,node->class_name().c_str());
19502#endif
19503 }
19504 }
19505 else
19506 {
19507#if 0
19508 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19509#endif
19510 }
19511#else
19512 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19513 if (locatedNode != NULL)
19514 {
19515 locatedNode->setTransformation();
19516 locatedNode->setOutputInCodeGeneration();
19517
19518 // DQ (10/26/2020): Set the physical_file_id, required for header file unparsing (is it?).
19519 if (locatedNode->get_file_info() != NULL)
19520 {
19521#if 0
19522 printf ("In SageInterface::markNodeToBeUnparsed(): locatedNode = %p = %s calling set_physical_file_id(%d) \n",locatedNode,locatedNode->class_name().c_str(),physical_file_id);
19523#endif
19524 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19525 }
19526 else
19527 {
19528#if 1
19529 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19530#endif
19531 }
19532
19533 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19534 // to call setTransformation() and setOutputInCodeGeneration().
19535 // Jim Leek (07/25/2023) This doesn't seem to be redundant, it definately marks a bunch of the subtree as transformed
19536 // That otherwise isn't, but Reverse Type Dependence often fails to compile because too much gets unparsed.
19537 // markTransformationsForOutput(node);
19538 }
19539#endif
19540 }
19541
19542
19543
19544void SageInterface::markSubtreeToBeUnparsed(SgNode* root, int physical_file_id)
19545 {
19546 RoseAst ast(root);
19547 for (RoseAst::iterator i=ast.begin();i!=ast.end();++i)
19548 {
19549 markNodeToBeUnparsed(*i,physical_file_id);
19550 }
19551 }
19552
19553
19554
19556 {
19557 // DQ (7/13/2021): This function marks nodes in a subtree to be a transformation, but avoids marking subtrees of the SgCastExp.
19558 // This is important because currently the marking of an implicit cast will cause it to be unparsed, even though it is marked
19559 // as implicit. This detail of precedence of implicit flags over transformation flags needs to be fixed seperated.
19560 // This function has been implemented as part of debugging this issue.
19561
19562 class InheritedAttribute
19563 {
19564 public:
19565 int physical_file_id;
19566 bool isCastSubtree;
19567 InheritedAttribute(int file_id): physical_file_id(file_id), isCastSubtree(false) {}
19568 InheritedAttribute(const InheritedAttribute & X)
19569 {
19570 isCastSubtree = X.isCastSubtree;
19571 physical_file_id = X.physical_file_id;
19572 }
19573 };
19574
19575// DQ (7/21/21): This code construction does not work with the GNU 4.9.x compilers.
19576// #if !( ( (__GNUC__ == 4) && (__GNUC_MINOR__ <= 9) ) || (__GNUC__ < 4))
19577#if (__GNUC__ > 4)
19578
19579 class SubtreeTraversal : public SgTopDownProcessing<InheritedAttribute>
19580 {
19581 public:
19582 InheritedAttribute evaluateInheritedAttribute ( SgNode* node, InheritedAttribute inheritedAttribute)
19583 {
19584 InheritedAttribute returnAttribute(inheritedAttribute);
19585
19586 SgCastExp* castExpression = isSgCastExp(node);
19587 if (castExpression != NULL)
19588 {
19589 returnAttribute.isCastSubtree = true;
19590 }
19591
19592 if (returnAttribute.isCastSubtree == true)
19593 {
19594 // Nothing to do, unless we want to fixup the physical node id.
19595#if 0
19596 printf ("In markSubtreeToBeUnparsedTreeTraversal(): subtree of a SgCastExp: node = %p = %s physical_file_id = %d \n",
19597 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19598#endif
19599 }
19600 else
19601 {
19602#if 0
19603 printf ("In markSubtreeToBeUnparsedTreeTraversal(): Calling markNodeToBeUnparsed(): node = %p = %s physical_file_id = %d \n",
19604 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19605#endif
19606 // This logic will cause the SgCastExp node to NOT be marked as a transformation (not just its children).
19607 markNodeToBeUnparsed(node,inheritedAttribute.physical_file_id);
19608 }
19609
19610 return returnAttribute;
19611 }
19612 };
19613
19614 InheritedAttribute inheritedAttribute(physical_file_id);
19615
19616 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19617 SubtreeTraversal traversal;
19618
19619#if 0
19620 printf ("\nIn markSubtreeToBeUnparsedTreeTraversal(): calling traverse \n");
19621#endif
19622
19623 traversal.traverse(root, inheritedAttribute);
19624#else
19625 printf ("This function does not compile with GNU 4.9 or older compilers (part of ROSE used only with more modern compilers) \n");
19626#endif
19627
19628 }
19629
19630
19631
19632
19634vector<SgDeclarationStatement*>
19635generateCopiesOfDependentDeclarations (const vector<SgDeclarationStatement*>& dependentDeclarations, SgScopeStatement* targetScope)
19636//generateCopiesOfDependentDeclarations ( SgStatement* stmt, SgScopeStatement* targetScope )
19637 {
19638 // Liao suggests adding the target scope to the parameter list so that the constructed function
19639 // built using SageBuilder::buildNondefiningFunctionDeclaration() can be built to be in the
19640 // correct scope as soon as possible.
19641
19642 // This function uses the getDependentDeclarations() function to get the dependent declarations
19643 // and then returns a list of copies of each of them.
19644
19645#if 0
19646 printf ("\n\n********************************************************** \n");
19647 printf (" Inside of generateCopiesOfDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19648 printf ("********************************************************** \n");
19649#endif
19650
19651 vector<SgDeclarationStatement*> copiesOfDependentDeclarations;
19652 // avoiding call getDependentDeclarations() twice
19653// vector<SgDeclarationStatement*> dependentDeclarations = getDependentDeclarations(stmt);
19654
19655#if 0
19656 printf ("Output the dependentDeclarations: dependentDeclarations.size() = %" PRIuPTR " \n",dependentDeclarations.size());
19657 outputDeclarationList(dependentDeclarations);
19658#endif
19659#if 0
19660 printf ("************************************************ \n");
19661 printf ("*** Make all copies of dependentDeclarations *** \n");
19662 printf ("************************************************ \n");
19663#endif
19664
19665 // Should have a valid scope, so that symbol tables can be expected to be setup.
19666 ROSE_ASSERT(targetScope != NULL);
19667
19668 // DQ (2/25/2009): Initially this is always global scope so test this for now, at least.
19669 ROSE_ASSERT(isSgGlobal(targetScope) != NULL);
19670
19671 for (vector<SgDeclarationStatement*>::const_iterator i = dependentDeclarations.begin(); i != dependentDeclarations.end(); i++)
19672 {
19673#if 0
19674 printf ("Copying declaration = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
19675#endif
19676 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19677
19678 SgNode* copy_node = NULL;
19679 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
19680
19681 // For function declarations we don't want to do deep copies on defining declarations
19682 // since that would violate the One-time Definition Rule (ODR).
19683 if (functionDeclaration != NULL)
19684 {
19685 // the target scope may already have a declaration for this function.
19686 // This happens since SageInterface::appendStatementWithDependentDeclaration() is called in the end of outlining
19687 // and the original enclosing class of the outlined target has been changed already (replaced target with a call to OUT_xxx())
19688 // Also, getDependentDeclarations() recursively searches for declarations within the dependent class and hits OUT_xxx()
19689 // Liao, 5/8/2009
19690
19691 if ( SgProject::get_verbose() >= 1 )
19692 printf ("WARNING: In SageInterface -- generateCopiesOfDependentDeclarations(): I think this is the wrong lookup symbol function that is being used here! \n");
19693
19694 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
19695 // TV (2/4/2014): can be found in the project wide global scope...
19696 // So I removed it as we only build a nondef decl and it will only happen for function declared in global scope.`
19697#endif
19698#if 0
19699 printf ("In generateCopiesOfDependentDeclarations(): Copy mechanism appied to SgFunctionDeclaration functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19700
19701 printf ("functionDeclaration = %p \n",functionDeclaration);
19702 printf ("functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
19703 printf ("functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19704 printf ("functionDeclaration->get_scope() = %p \n",functionDeclaration->get_scope());
19705 printf ("targetScope = %p \n",targetScope);
19706#endif
19707 SgFunctionDeclaration* copy_functionDeclaration = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,targetScope);
19708 assert(copy_functionDeclaration != NULL);
19709
19710 copy_functionDeclaration->set_parent(targetScope);
19711
19712 assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != NULL);
19713
19714 // DQ (11/8/2020): This can not be asserted now that the buildSourceFile() has the
19715 // feature of clearing the symbol table used across multiple files.
19716 // assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != copy_functionDeclaration);
19717
19718 assert(copy_functionDeclaration->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table() != NULL);
19719
19720 assert(copy_functionDeclaration->get_scope() != NULL);
19721 assert(copy_functionDeclaration->get_scope() == targetScope);
19722 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19723 copy_functionDeclaration->get_type()) != NULL);
19724 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19725 copy_functionDeclaration->get_type())->get_symbol_basis() == copy_functionDeclaration->get_firstNondefiningDeclaration());
19726
19727 copy_node = copy_functionDeclaration;
19728#if 0
19729 printf ("In generateCopiesOfDependentDeclarations(): DONE: Copy mechanism appied to SgFunctionDeclaration \n");
19730 ROSE_ABORT();
19731#endif
19732 }
19733 else
19734 {
19735 // We only copy the non-defining declaration of a defining typedef declaration
19736 // since its defining body will be treated as a separate declaration and inserted to the new file.
19737 // This is also a workaround for an AST copy bug: losing defining body of a defining typedef declaration after copying.
19738 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(*i);
19739 if (tdecl)
19740 {
19741#if 0
19742 if (tdecl->get_definingDeclaration() == tdecl)
19743 cout<<"Copying a defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19744 else
19745 cout<<"Copying a non-defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19746#endif
19748 SgTypedefDeclaration* tdecl_copy = isSgTypedefDeclaration(copy_node);
19749 tdecl_copy->set_typedefBaseTypeContainsDefiningDeclaration (false); // explicit indicate this does not contain defining base type, Liao 12/14/2012
19750 }
19751 else
19752 copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19753
19754 // 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).
19755 SgDeclarationStatement* copy_declaration = isSgDeclarationStatement(copy_node);
19756 ROSE_ASSERT(copy_declaration != NULL);
19757
19758 // DQ (3/2/2009): This will be done later, but it is set above, so set it in this branch to be consistant.
19759 if (copy_declaration->hasExplicitScope() == true)
19760 copy_declaration->set_scope(targetScope);
19761 }
19762
19763 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19764 // Build a function prototype, but what scope should be used?
19765 // ROSE_ASSERT(functionDeclaration->get_scope() != NULL);
19766 // copy = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,functionDeclaration->get_scope());
19767
19768#if 0
19769 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());
19770#endif
19771
19772 ROSE_ASSERT(copy_node != NULL);
19773 ROSE_ASSERT(copy_node->get_file_info() != NULL);
19774
19775 // Note that the root of the does not have its file info set like its children.
19776 copy_node->get_file_info()->setTransformation();
19778 // copy_node->get_file_info()->display("CollectDependentDeclarationsTraversal::visit()");
19779
19780 SgDeclarationStatement* copy_definingDeclaration = isSgDeclarationStatement(copy_node);
19781 ROSE_ASSERT(copy_definingDeclaration != NULL);
19782
19783 ROSE_ASSERT( *i != NULL );
19784 ROSE_ASSERT(copy_definingDeclaration != NULL);
19785
19786 // DQ (2/26/2009): get_scope() will require a valid parent for some cases (see moreTest4.cpp).
19787 if (copy_definingDeclaration->get_parent() == NULL)
19788 {
19789 copy_definingDeclaration->set_parent(targetScope);
19790 }
19791 ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19792
19793#if 0
19794 printf ("DONE: Copying declaration: original scope = %p copied to scope = %p \n",(*i)->get_scope(),copy_definingDeclaration->get_scope());
19795#endif
19796
19797 // DQ (2/22/2009): I think we need to set these explicitly (it will be reset later).
19798 copy_definingDeclaration->set_parent(NULL);
19799
19800 // Now that we pass in the scope explicitly we can set the scope (above), so don't reset to NULL!
19801 // copy_definingDeclaration->set_scope(NULL);
19802
19803 // DQ (2/20/2009): Added assertion.
19804 ROSE_ASSERT(copy_definingDeclaration->get_parent() == NULL);
19805
19806#if 0
19807 // DQ (2/20/2009): Added assertion.
19808 // ROSE_ASSERT(copy_definingDeclaration->get_definingDeclaration() != NULL);
19809 if (copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL)
19810 {
19811 printf ("copy_definingDeclaration = %p \n",copy_definingDeclaration);
19812 printf ("copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL \n");
19813 printf ("copy_definingDeclaration->get_definingDeclaration() = %p \n",copy_definingDeclaration->get_definingDeclaration());
19814 }
19815#endif
19816
19817 // DQ (2/21/2009): Commented out as a test.
19818 if ((*i)->get_firstNondefiningDeclaration() != NULL)
19819 {
19820 ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
19821 }
19822
19823 // DQ (2/20/2009): Added asertion.
19824 // ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19825
19826 copiesOfDependentDeclarations.push_back(copy_definingDeclaration);
19827 }
19828
19829#if 0
19830 printf ("****************************************************** \n");
19831 printf ("*** DONE: Make all copies of dependentDeclarations *** \n");
19832 printf ("****************************************************** \n");
19833 printf ("copiesOfDependentDeclarations.size() = %" PRIuPTR " \n",copiesOfDependentDeclarations.size());
19834#endif
19835
19836 // The mapping of copies to original declarations should be 1-to-1.
19837 // Liao, not true anymore for getDependentDeclarations() using recursion: a depending class's body is searched for dependents also.
19838 // 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
19839 ROSE_ASSERT(copiesOfDependentDeclarations.size() <= dependentDeclarations.size());
19840
19841 return copiesOfDependentDeclarations;
19842 }
19843
19844
19845bool
19846declarationContainsDependentDeclarations( SgDeclarationStatement* decl, vector<SgDeclarationStatement*> & dependentDeclarationList )
19847 {
19848 // DQ (2/16/2009): This function finds the declarations in "decl" and checks if they match against those in dependentDeclarationList
19849 bool returnValue = false;
19850
19851#if 0
19852 printf ("\n\n********************************************************** \n");
19853 printf (" Inside of declarationContainsDependentDeclarations(decl = %p = %s) \n",decl,decl->class_name().c_str());
19854 printf ("********************************************************** \n");
19855#endif
19856
19857 vector<SgDeclarationStatement*> locallyDependentDeclarationList = SageInterface::getDependentDeclarations(decl);
19858
19859 // printf ("In declarationContainsDependentDeclarations(): locallyDependentDeclarationList: \n");
19860 // outputPreprocessingInfoList(locallyDependentDeclarationList);
19861
19862 for (size_t i = 0; i < locallyDependentDeclarationList.size(); i++)
19863 {
19864 SgDeclarationStatement* d = locallyDependentDeclarationList[i];
19865#if 0
19866 printf ("locallyDependentDeclarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
19867#endif
19868 vector<SgDeclarationStatement*>::iterator j = find(dependentDeclarationList.begin(),dependentDeclarationList.end(),d);
19869 if (j != dependentDeclarationList.end())
19870 {
19871 // These identified declaration must be output as members of the class when it is output in the separate header file.
19872 // infact ODR may require that the whole class be output! Actually I think we don't have any chioce here!
19873#if 0
19874 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());
19875#endif
19876 returnValue = true;
19877 }
19878 }
19879
19880#if 0
19881 printf ("**************************************************************************** \n");
19882 printf (" LEAVING: Inside of declarationContainsDependentDeclarations(decl = %p = %s) returnValue = %s \n",decl,decl->class_name().c_str(),returnValue ? "true" : "false");
19883 printf ("**************************************************************************** \n");
19884#endif
19885
19886 return returnValue;
19887 }
19890{
19891 ROSE_ASSERT (new_exp != NULL);
19892 ROSE_ASSERT (anchor_exp != NULL);
19893 ROSE_ASSERT (new_exp != anchor_exp);
19894
19895 SgNode* parent = anchor_exp->get_parent();
19896 ROSE_ASSERT (parent != NULL);
19897
19898 //TODO use deep copy may be a better way, avoid reusing the original anchor_exp
19899 SgCommaOpExp * result = buildCommaOpExp(new_exp, NULL);
19900 ROSE_ASSERT (result != NULL);
19901 replaceExpression (anchor_exp, result, true);
19902
19903 result->set_rhs_operand(anchor_exp);
19904 anchor_exp->set_parent(result);
19905 return result ;
19906}
19907
19908
19910SgCommaOpExp * SageInterface::insertAfterUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp, SgStatement** temp_decl /* = NULL */, SgVarRefExp** temp_ref /* = NULL */)
19911{
19912 ROSE_ASSERT (new_exp != NULL);
19913 ROSE_ASSERT (anchor_exp != NULL);
19914 ROSE_ASSERT (new_exp != anchor_exp);
19915
19916 SgNode* parent = anchor_exp->get_parent();
19917 ROSE_ASSERT (parent != NULL);
19918
19919 // insert TYPE T1; right before the enclosing statement of anchor_exp
19920 SgType * t = anchor_exp ->get_type();
19921 ROSE_ASSERT (t != NULL);
19922 SgStatement * enclosing_stmt = getEnclosingStatement(anchor_exp);
19923 ROSE_ASSERT (enclosing_stmt != NULL);
19924
19925 gensym_counter ++;
19926 string temp_name = "_t_"+ StringUtility::numberToString(gensym_counter);
19927 SgVariableDeclaration* t_decl = buildVariableDeclaration(temp_name, t, NULL, enclosing_stmt->get_scope());
19928 insertStatementBefore (enclosing_stmt, t_decl);
19929 SgVariableSymbol * temp_sym = getFirstVarSym (t_decl);
19930 ROSE_ASSERT (temp_sym != NULL);
19931 if (temp_decl)
19932 *temp_decl = t_decl;
19933
19934 // build ((T1 = anchor_exp, new_exp),T1) )
19935 SgVarRefExp * first_ref = buildVarRefExp(temp_sym);
19936 if (temp_ref)
19937 * temp_ref = first_ref;
19938 SgCommaOpExp * result = buildCommaOpExp ( buildCommaOpExp (buildAssignOp ( first_ref, deepCopy(anchor_exp)), new_exp) , buildVarRefExp(temp_sym));
19939 replaceExpression (anchor_exp, result, false);
19940
19941 return result;
19942}
19943
19944void
19946 {
19947 // Put out a message in the separate file to lable the dependent CPP directives.
19948 // --- PreprocessingInfo(DirectiveType, const std::string & inputString, const std::string & filenameString, int line_no, int col_no, int nol, RelativePositionType relPos );
19949 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
19950 string fileName = "separate-outlined-file";
19951 PreprocessingInfo* messageToUser = new PreprocessingInfo(PreprocessingInfo::C_StyleComment,message,fileName,0,0,1,PreprocessingInfo::before);
19952 // requiredDirectivesList.push_back(messageToUser);
19953 stmt->addToAttachedPreprocessingInfo(messageToUser,PreprocessingInfo::before);
19954
19955 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
19956 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
19957 // when multiple files are used on the command line.
19958 messageToUser->get_file_info()->setTransformation();
19959 }
19960
19961
19962// DQ (2/6/2009): Added function to support outlining into separate file.
19963// 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)
19964void
19966 {
19967 // New function to support outlining of functions into separate files (with their required declarations).
19968
19969#if 0
19970 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl = %p \n",decl);
19971 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_parent() = %p \n",decl->get_parent());
19972 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_scope() = %p \n",decl->get_scope());
19973 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): original_statement = %p \n",original_statement);
19974 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (decl) = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
19975 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_firstNondefiningDeclaration() = %p \n",decl->get_firstNondefiningDeclaration());
19976 if (decl->get_firstNondefiningDeclaration() != NULL)
19977 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
19978 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_definingDeclaration() = %p \n",decl->get_definingDeclaration());
19979 if (decl->get_definingDeclaration() != NULL)
19980 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_definingDeclaration())->getFileName().c_str());
19981#endif
19982
19983#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
19984 // Make sure that the input declaration (decl" is consistent in it's representation across more
19985 // than one file (only a significant test when outlining to a separate file; which is what this
19986 // function supports).
19987 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
19988 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
19989 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
19990
19991 // DQ (2/6/2009): I need to write this function to support the
19992 // insertion of the function into the specified scope. If the
19993 // file associated with the scope is marked as compiler generated
19994 // (or as a transformation) then the declarations referenced in the
19995 // function must be copied as well (those not in include files)
19996 // and the include files must be copies also. If the SgFile
19997 // is not compiler generated (or a transformation) then we just
19998 // append the function to the scope (trivial case).
19999
20000 // This code will be based on the work in:
20001 // developersScratchSpace/Dan/translator_tests/reverseTraversal.C
20002
20003 // To test this run: "rm moreTest2.o ; make moreTest2.o"
20004 // in directory: tests/nonsmoke/functional/roseTests/astOutliningTests
20005
20006 // ***** Also move different loop IR nodes into a common base class *****
20007
20008 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20009
20010 // DQ (3/2/2009): This now calls a newer function which returns a list of declarations and a list of symbols.
20011 // The declarations are sometimes outer declarations of nested references to dependent declaration in inner
20012 // scopes (see moreTest3.cpp). The Symbol list are the symbols in the old AST that will be mapped to newer
20013 // symbols generated in the copied AST.
20014 // Collect the declaration that the input declaration depends upon.
20015 vector<SgDeclarationStatement*> dependentDeclarationList_inOriginalFile;
20016
20017 dependentDeclarationList_inOriginalFile = getDependentDeclarations(decl);
20018
20019 // Generate the copies of all the dependent statements
20020// printf ("Fixme: this currently causes the getDependentDeclarations(decl) function to be called twice \n");
20021// vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(decl,scope);
20022 vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(dependentDeclarationList_inOriginalFile,scope);
20023 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20024
20025 // Make sure that the input declaration (decl" is consistent in it's representation across more
20026 // than one file (only a significant test when outlining to a separate file; which is what this
20027 // function supports).
20028 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20029 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20030 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20031
20032 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
20033 std::map<SgNode*, SgNode*> replacementMap;
20034
20035 // DQ (3/2/2009): Now use the collectDependentDeclarationsCopyType object to generate the mapping
20036 // from the symbols in the old AST to the new symbols in the new AST (generated as part of the AST
20037 // copy mechanism).
20038 SgCopyHelp::copiedNodeMapType copyNodeMap = collectDependentDeclarationsCopyType.get_copiedNodeMap();
20039 SgCopyHelp::copiedNodeMapType::iterator copyNodeMapItrator = copyNodeMap.begin();
20040 while (copyNodeMapItrator != copyNodeMap.end())
20041 {
20042 // Loop over all the nodes generated in the AST copy mechanism (accumulated result over multiple copies).
20043 // const SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20044 // SgNode* first = copyNodeMapItrator->first;
20045 SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20046 SgNode* second = copyNodeMapItrator->second;
20047#if 0
20048 printf ("copyNodeMapItrator.first = %p = %s second = %p = %s \n",first,first->class_name().c_str(),second,second->class_name().c_str());
20049#endif
20050 // Add the SgGlobal referenece to the replacementMap
20051 if (isSgSymbol(first) != NULL)
20052 {
20053#if 0
20054 printf ("Adding to replacementMap (first = %p = %s = %s , second = %p \n",first,first->class_name().c_str(),SageInterface::get_name(first).c_str(),second);
20055#endif
20056 replacementMap.insert(pair<SgNode*,SgNode*>(first,second));
20057 }
20058
20059 copyNodeMapItrator++;
20060 }
20061
20062#if 0
20063 printf ("Exiting after test of new functionality \n");
20064 ROSE_ABORT();
20065#endif
20066
20067 // DQ (2/22/2009): We need all the declarations! (moreTest3.cpp demonstrates this, since it drops
20068 // the "#define SIMPLE 1" which causes it to be treated a "0" (causing errors in the generated code).
20069 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(original_statement);
20070 vector<PreprocessingInfo*> requiredDirectivesList = collectCppDirectives(sourceFile);
20071
20072 SgFunctionDeclaration* outlinedFunctionDeclaration = isSgFunctionDeclaration(decl);
20073 ROSE_ASSERT(outlinedFunctionDeclaration != NULL);
20074 SgGlobal* originalFileGlobalScope = TransformationSupport::getGlobalScope(original_statement);
20075 ROSE_ASSERT(originalFileGlobalScope != NULL);
20076 if ( SgProject::get_verbose() >= 1 )
20077 printf ("WARNING: In SageInterface::appendStatementWithDependentDeclaration(): I think this is the wrong lookup symbol function that is being used here! \n");
20078
20079 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
20080 // SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name()));
20081 SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name(),NULL,NULL));
20082
20083 // SgSymbol* outlinedFunctionSymbolFromOutlinedFile = scope->lookup_symbol(outlinedFunctionDeclaration->get_name());
20084 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20085 SgFunctionSymbol* outlinedFunctionSymbolFromOutlinedFile = isSgFunctionSymbol(decl->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table());
20086#if 0
20087 printf ("outlinedFunctionSymbolFromOriginalFile = %p outlinedFunctionSymbolFromOutlinedFile = %p \n",outlinedFunctionSymbolFromOriginalFile,outlinedFunctionSymbolFromOutlinedFile);
20088
20089 printf ("TransformationSupport::getSourceFile(decl)->getFileName() = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20090 printf ("TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName() = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20091 printf ("TransformationSupport::getSourceFile(original_statement)->getFileName() = %s \n",TransformationSupport::getSourceFile(original_statement)->getFileName().c_str());
20092#endif
20093
20094 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile != NULL);
20095 ROSE_ASSERT(outlinedFunctionSymbolFromOutlinedFile != NULL);
20096
20097 // TV (07/24/2013): Symbol are unified across files through the project wide global scope
20098 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile == outlinedFunctionSymbolFromOutlinedFile);
20099
20100 // Add the SgGlobal referenece to the replacementMap
20101 replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
20102
20103 // Add the non-defining declarations of the outlined function to the replacementMap
20104 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOriginalFile = isSgFunctionDeclaration(outlinedFunctionSymbolFromOriginalFile->get_declaration());
20105 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOutlinedFile = isSgFunctionDeclaration(decl->get_firstNondefiningDeclaration());
20106 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOriginalFile != NULL);
20107 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOutlinedFile != NULL);
20108 replacementMap.insert(pair<SgNode*,SgNode*>(outlinedNondefiningFunctionDeclarationFromOriginalFile,outlinedNondefiningFunctionDeclarationFromOutlinedFile));
20109
20110
20111 // list<SgDeclarationStatement>::iterator i = declarationList.begin();
20112 // while (i != declarationList.end())
20113 // for (list<SgDeclarationStatement>::iterator i = declarationList.begin(); i != declarationList.end(); i++)
20114
20115// cout<<"\n*******************************************\n"<<endl;
20116// cout<<"Inserting dependent decls: count="<<dependentDeclarationList.size()<<endl;
20117 for (size_t i = 0; i < dependentDeclarationList.size(); i++)
20118 {
20119 SgDeclarationStatement* d = dependentDeclarationList[i]; // copies of dependent declarations
20120#if 0
20121 SgDeclarationStatement* originalDeclaration = dependentDeclarationList_inOriginalFile[i];
20122 printf ("declarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20123 printf ("originalDeclaration = %p \n",originalDeclaration);
20124
20125 d->get_file_info()->display("SageInterface::appendStatementWithDependentDeclaration()");
20126#endif
20127
20128 // DQ (2/20/2009): Added assertion.
20129 ROSE_ASSERT(d->get_parent() == NULL);
20130
20131 // scope->append_declaration(d);
20132 // scope->insert_statement (decl, d, /* bool inFront= */ true);
20133 ROSE_ASSERT(decl->get_scope() == scope);
20134 ROSE_ASSERT(find(scope->getDeclarationList().begin(),scope->getDeclarationList().end(),decl) != scope->getDeclarationList().end());
20135 scope->insert_statement (decl, d, /* bool inFront= */ true);
20136 d->set_parent (scope);
20137
20138#if 0
20139 printf ("Add the required symbol information to the symbol table: scope = %p = %s \n",scope,scope->class_name().c_str());
20140#endif
20141
20142 // For whatever type of declaration we add to the global scope in the new separate
20143 // file we have to add the required symbol information to the symbol table.
20144 switch(d->variantT())
20145 {
20146 case V_SgClassDeclaration:
20147 {
20148 if ( declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20149 printf ("Warning: This class contains dependent declarations (not implemented) \n");
20150 break;
20151 }
20152
20153 case V_SgMemberFunctionDeclaration:
20154 printf ("Sorry, support for dependent member function declarations not implemented! \n");
20155 ROSE_ABORT();
20156
20157 case V_SgTemplateInstantiationDecl:
20158 printf ("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration \n");
20159 d->get_file_info()->display("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration");
20160
20161 printf ("Case of SgTemplateInstantiationDecl not implemented. \n");
20162 ROSE_ABORT();
20163
20164 case V_SgNamespaceDeclarationStatement:
20165 if (declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20166 printf ("Warning: This namespace contains dependent declarations (not supported) \n");
20167 break;
20168
20169 case V_SgFunctionDeclaration:
20170 case V_SgTypedefDeclaration:
20171 case V_SgEnumDeclaration:
20172 break;
20173
20174 default:
20175 printf ("default case in SageInterface::appendStatementWithDependentDeclaration() (handling dependentDeclarationList) d = %p = %s \n",d,d->class_name().c_str());
20176 ROSE_ABORT();
20177 }
20178
20179
20180 // Collect include directives that are already attached to this dependent declaration.
20181 vector<PreprocessingInfo*> cppDirectivesAlreadyAttachedToDependentDeclarations = collectCppDirectives(d);
20182
20183#if 0
20184 printf ("directives BEFORE excluding those already present in dependent declarations \n");
20185 outputPreprocessingInfoList(requiredDirectivesList);
20186
20187 printf ("directives already attached to dependent declarations \n");
20188 outputPreprocessingInfoList(cppDirectivesAlreadyAttachedToDependentDeclarations);
20189#endif
20190
20191 // Remove these include directives from the requiredDirectivesList (to prevent redundant output in the generated file)
20192 vector<PreprocessingInfo*>::iterator j = cppDirectivesAlreadyAttachedToDependentDeclarations.begin();
20193 while ( j != cppDirectivesAlreadyAttachedToDependentDeclarations.end() )
20194 {
20195 // Remove this directive from the requiredDirectivesList (to avoid having them output redundently).
20196 vector<PreprocessingInfo*>::iterator entry = find(requiredDirectivesList.begin(),requiredDirectivesList.end(),*j);
20197 ROSE_ASSERT(entry != requiredDirectivesList.end());
20198
20199 requiredDirectivesList.erase(entry);
20200
20201 j++;
20202 }
20203
20204#if 0
20205 printf ("directives AFTER excluding those already present in dependent declarations \n");
20206 outputPreprocessingInfoList(requiredDirectivesList);
20207#endif
20208 }
20209
20210 // Add a message to the top of the outlined function that has been added
20211 addMessageStatement(decl,"/* OUTLINED FUNCTION */");
20212
20213 // Insert the dependent declarations ahead of the input "decl".
20214 SgStatement* firstStatmentInFile = NULL;
20215 if (dependentDeclarationList.empty() == true)
20216 {
20217 firstStatmentInFile = decl;
20218 }
20219 else
20220 {
20221 firstStatmentInFile = dependentDeclarationList[0];
20222 }
20223
20224 ROSE_ASSERT(firstStatmentInFile != NULL);
20225
20226 // Add a message to the top of the dependent declarations that have been added
20227 addMessageStatement(firstStatmentInFile,"/* REQUIRED DEPENDENT DECLARATIONS */");
20228
20229 // DQ (3/6/2009): Added support to permit exclusion of "#include<header.h>" files since they can make it
20230 // much more difficult for external tools. Later we will check if there are remaining unsatisfied dependent
20231 // declarations (which must be in the header file) so we can automate this step.
20232 if (excludeHeaderFiles == false)
20233 {
20234 // Include all the "#include<header.h>" cpp directives obtained from the original file.
20235 vector<PreprocessingInfo*>::reverse_iterator j = requiredDirectivesList.rbegin();
20236 while ( j != requiredDirectivesList.rend() )
20237 {
20238 firstStatmentInFile->addToAttachedPreprocessingInfo(*j,PreprocessingInfo::before);
20239 j++;
20240 }
20241 }
20242
20243 // Add a message to the top of the CPP directives that have been added
20244 addMessageStatement(firstStatmentInFile,"/* REQUIRED CPP DIRECTIVES */");
20245
20246 // ****************************************************************************
20247 // **************** Fixup AST to Reset References To IR nodes ***************
20248 // ****************************************************************************
20249 // This traversal of the replacement map modified the AST to reset pointers to subtrees that will be shared.
20250 // The whole AST is traversed (using the memory pool traversal) and the data member pointers to IR nodes that
20251 // are found in the replacement map are used to lookup the replacement values that are used to reset the
20252 // pointers in the AST. As the replacement is computed the pointer values that are marked in the replacement
20253 // list for update are added to the intermediateDeleteSet.
20254
20255 SgSourceFile* outlinedFile = TransformationSupport::getSourceFile(scope);
20256 ROSE_ASSERT(outlinedFile != NULL);
20257
20258 // This replacement will be done over the entire file (parts of it are redundant with what has already
20259 // been done by the AST copy (so this step need not do as much and may be reduced to just operating
20260 // on the outlined function, I think).
20261#if 0
20262 printf ("\n\n************************************************************\n");
20263 printf ("Calling Utils::edgePointerReplacement() \n");
20264#endif
20265
20266 Rose::AST::Utility::edgePointerReplacement(outlinedFile,replacementMap);
20267
20268#if 0
20269 printf ("Calling Utils::edgePointerReplacement(): DONE \n");
20270 printf ("************************************************************\n\n");
20271
20272 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
20273 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
20274#endif
20275
20276 // Repeated test from above
20277 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20278
20279// endif for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20280#endif
20281
20282#if 0
20283 // The replacementMap should include the symbols associated with the dependentDeclarationList
20284 // and the outlined function (so dependentDeclarationList.size() + 1).
20285 printf ("replacementMap.size() = %" PRIuPTR " dependentDeclarationList.size() = %" PRIuPTR " \n",replacementMap.size(),dependentDeclarationList.size());
20286 // ROSE_ASSERT(replacementMap.size() == dependentDeclarationList.size() + 1);
20287#endif
20288 }
20289
20290void
20292 {
20293//Tan, August/25/2010: //Re-implement DeleteAST function
20294
20295 //Use MemoryPoolTraversal to count the number of references to a certain symbol
20296 //This class defines the visitors for the MemoryPoolTraversal
20297
20298 class ClassicVisitor : public ROSE_VisitorPattern
20299 {
20300 private:
20301 int SgVariableSymbol_count;
20302 int SgFunctionSymbol_count;
20303 int SgClassDeclaration_count;
20304 int SgTypedefSymbol_count;
20305 int SgMemFuncSymbol_count;
20306 int SgTemplateSymbol_count;
20307 int SgEnumFieldSymbol_count;
20308
20309 SgVariableSymbol* SgVariableSymbolPtr;
20310 SgFunctionSymbol* SgFunctionSymbolPtr;
20311 SgClassSymbol * SgClassSymbolPtr;
20312 SgTypedefSymbol * SgTypedefPtr;
20313 SgEnumFieldSymbol * SgEnumFieldSymbolPtr;
20314 SgMemberFunctionSymbol * SgMemFuncSymbolPtr;
20315 SgTemplateSymbol * SgTemplateSymbolPtr;
20316 SgClassDeclaration * class_defining;
20317 SgTemplateDeclaration * template_defining;
20319 SgTypedefDeclaration * typedef_defining;
20320 SgFunctionDeclaration * function_decl;
20321 SgTemplateInstantiationDecl * templateInstantiate_defining;
20322
20323 public:
20324 ClassicVisitor(SgVariableSymbol* symbol){
20325 SgVariableSymbol_count = 0;
20326 SgVariableSymbolPtr = symbol;
20327 SgFunctionSymbolPtr =NULL;
20328 SgClassSymbolPtr =NULL;
20329 SgTypedefPtr = NULL;
20330 SgMemFuncSymbolPtr =NULL;
20331 class_defining = NULL;
20332 memFunc =NULL;
20333 typedef_defining =NULL;
20334 function_decl = NULL;
20335 SgTemplateSymbolPtr = NULL;
20336 template_defining = NULL;
20337 SgEnumFieldSymbolPtr = NULL;
20338 templateInstantiate_defining =NULL;
20339 }
20340
20341 ClassicVisitor(SgFunctionSymbol* symbol){
20342 SgFunctionSymbol_count = 0;
20343 SgFunctionSymbolPtr = symbol;
20344
20345 // DQ (5/2/2013): Added to fix test2013_141.C.
20346 SgMemFuncSymbol_count =0;
20347
20348 SgVariableSymbolPtr = NULL;
20349 SgClassSymbolPtr =NULL;
20350 SgTypedefPtr = NULL;
20351 SgMemFuncSymbolPtr =NULL;
20352 class_defining = NULL;
20353 memFunc =NULL;
20354 typedef_defining =NULL;
20355 function_decl = NULL;
20356 SgTemplateSymbolPtr = NULL;
20357 template_defining = NULL;
20358 SgEnumFieldSymbolPtr = NULL;
20359 templateInstantiate_defining =NULL;
20360 }
20361
20362 ClassicVisitor(SgClassSymbol* symbol){
20363 SgClassDeclaration_count = 0;
20364 SgClassSymbolPtr = symbol;
20365 SgFunctionSymbolPtr = NULL;
20366 SgVariableSymbolPtr = NULL;
20367 SgTypedefPtr = NULL;
20368 SgMemFuncSymbolPtr =NULL;
20369 class_defining = NULL;
20370 memFunc =NULL;
20371 typedef_defining =NULL;
20372 function_decl = NULL;
20373 SgTemplateSymbolPtr = NULL;
20374 template_defining = NULL;
20375 SgEnumFieldSymbolPtr = NULL;
20376 templateInstantiate_defining =NULL;
20377 }
20378
20379 ClassicVisitor(SgTypedefSymbol* symbol){
20380 SgTypedefSymbol_count =0;
20381 SgTypedefPtr = symbol;
20382 SgClassSymbolPtr = NULL;
20383 SgFunctionSymbolPtr = NULL;
20384 SgVariableSymbolPtr = NULL;
20385 SgMemFuncSymbolPtr =NULL;
20386 class_defining = NULL;
20387 memFunc =NULL;
20388 typedef_defining =NULL;
20389 function_decl = NULL;
20390 SgTemplateSymbolPtr = NULL;
20391 template_defining = NULL;
20392 SgEnumFieldSymbolPtr = NULL;
20393 templateInstantiate_defining =NULL;
20394 }
20395
20396 ClassicVisitor(SgMemberFunctionSymbol* symbol){
20397 SgMemFuncSymbolPtr = symbol;
20398 SgMemFuncSymbol_count =0;
20399 SgTypedefPtr = NULL;
20400 SgClassSymbolPtr = NULL;
20401 SgFunctionSymbolPtr = NULL;
20402 SgVariableSymbolPtr = NULL;
20403 class_defining = NULL;
20404 memFunc =NULL;
20405 typedef_defining =NULL;
20406 function_decl = NULL;
20407 SgTemplateSymbolPtr = NULL;
20408 template_defining = NULL;
20409 SgEnumFieldSymbolPtr = NULL;
20410 templateInstantiate_defining =NULL;
20411 }
20412
20413 ClassicVisitor(SgTemplateSymbol* symbol){
20414 SgTemplateSymbolPtr = symbol;
20415 SgTemplateSymbol_count =0;
20416 SgMemFuncSymbolPtr = NULL;
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 template_defining = NULL;
20426 SgEnumFieldSymbolPtr = NULL;
20427 templateInstantiate_defining =NULL;
20428 }
20429
20430 ClassicVisitor(SgEnumFieldSymbol* symbol){
20431 SgEnumFieldSymbolPtr = symbol;
20432 SgEnumFieldSymbol_count =0;
20433 SgTemplateSymbolPtr = NULL;
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 templateInstantiate_defining =NULL;
20445 }
20446
20447
20448 ClassicVisitor(SgClassDeclaration* node){
20449 class_defining = node;
20450 SgMemFuncSymbolPtr = NULL;
20451 SgTypedefPtr = NULL;
20452 SgClassSymbolPtr = NULL;
20453 SgFunctionSymbolPtr = NULL;
20454 SgVariableSymbolPtr = NULL;
20455 memFunc =NULL;
20456 typedef_defining =NULL;
20457 function_decl = NULL;
20458 SgTemplateSymbolPtr = NULL;
20459 template_defining = NULL;
20460 SgEnumFieldSymbolPtr = NULL;
20461 templateInstantiate_defining =NULL;
20462 }
20463
20464 ClassicVisitor(SgTemplateDeclaration* node){
20465 template_defining = node;
20466 class_defining = NULL;
20467 SgMemFuncSymbolPtr = NULL;
20468 SgTypedefPtr = NULL;
20469 SgClassSymbolPtr = NULL;
20470 SgFunctionSymbolPtr = NULL;
20471 SgVariableSymbolPtr = NULL;
20472 memFunc =NULL;
20473 typedef_defining =NULL;
20474 function_decl = NULL;
20475 SgTemplateSymbolPtr = NULL;
20476 SgEnumFieldSymbolPtr = NULL;
20477 templateInstantiate_defining =NULL;
20478 }
20479 ClassicVisitor(SgFunctionDeclaration* node){
20480 function_decl =node;
20481 class_defining = NULL;
20482 SgMemFuncSymbolPtr = NULL;
20483 SgTypedefPtr = NULL;
20484 SgClassSymbolPtr = NULL;
20485 SgFunctionSymbolPtr = NULL;
20486 SgVariableSymbolPtr = NULL;
20487 memFunc =NULL;
20488 typedef_defining =NULL;
20489 SgTemplateSymbolPtr = NULL;
20490 template_defining = NULL;
20491 SgEnumFieldSymbolPtr = NULL;
20492 templateInstantiate_defining =NULL;
20493 }
20494
20495 ClassicVisitor(SgMemberFunctionDeclaration* node){
20496 memFunc = node;
20497 function_decl =NULL;
20498 class_defining = NULL;
20499 SgMemFuncSymbolPtr = NULL;
20500 SgTypedefPtr = NULL;
20501 SgClassSymbolPtr = NULL;
20502 SgFunctionSymbolPtr = NULL;
20503 SgVariableSymbolPtr = NULL;
20504 typedef_defining =NULL;
20505 SgTemplateSymbolPtr = NULL;
20506 template_defining = NULL;
20507 SgEnumFieldSymbolPtr = NULL;
20508 templateInstantiate_defining =NULL;
20509 }
20510
20511 ClassicVisitor(SgTypedefDeclaration* node){
20512 typedef_defining = node;
20513 memFunc = NULL;
20514 function_decl =NULL;
20515 class_defining = NULL;
20516 SgMemFuncSymbolPtr = NULL;
20517 SgTypedefPtr = NULL;
20518 SgClassSymbolPtr = NULL;
20519 SgFunctionSymbolPtr = NULL;
20520 SgVariableSymbolPtr = NULL;
20521 SgTemplateSymbolPtr = NULL;
20522 template_defining = NULL;
20523 SgEnumFieldSymbolPtr = NULL;
20524 templateInstantiate_defining =NULL;
20525 }
20526
20527 ClassicVisitor(SgTemplateInstantiationDecl* node){
20528 templateInstantiate_defining =node;
20529 typedef_defining = NULL;
20530 memFunc = NULL;
20531 function_decl =NULL;
20532 class_defining = NULL;
20533 SgMemFuncSymbolPtr = NULL;
20534 SgTypedefPtr = NULL;
20535 SgClassSymbolPtr = NULL;
20536 SgFunctionSymbolPtr = NULL;
20537 SgVariableSymbolPtr = NULL;
20538 SgTemplateSymbolPtr = NULL;
20539 template_defining = NULL;
20540 SgEnumFieldSymbolPtr = NULL;
20541 }
20542
20543
20544 // SgVariableSymbol and SgEnumFieldSymbol
20545 void visit(SgInitializedName* node)
20546 {
20547 if(SgVariableSymbolPtr !=NULL)
20548 {
20549 if(node->get_scope()!=NULL)
20550 {
20551 // DQ (5/21/2013): We want to restrict access to the symbol table.
20552 if(node->get_scope()->get_symbol_table()!=NULL)
20553 {
20555 if (isSgVariableSymbol(s) == SgVariableSymbolPtr) SgVariableSymbol_count++;
20556 }
20557 }
20558 }
20559
20560 if(SgEnumFieldSymbolPtr !=NULL)
20561 {
20562 if(node->get_scope()!=NULL)
20563 {
20564 // DQ (5/21/2013): We want to restrict access to the symbol table.
20565 if(node->get_scope()->get_symbol_table()!=NULL)
20566 {
20568 if (isSgEnumFieldSymbol(s) == SgEnumFieldSymbolPtr) SgEnumFieldSymbol_count++;
20569 }
20570 }
20571 }
20572 }
20573
20574 void visit(SgVarRefExp* node)
20575 {
20576 if(SgVariableSymbolPtr !=NULL){
20577 SgVariableSymbol* s = node->get_symbol();
20578 if (s == SgVariableSymbolPtr) SgVariableSymbol_count++;
20579 }
20580 }
20581
20582 int get_num_variable_pointers(){return SgVariableSymbol_count;}
20583
20584 int get_num_EnumField_pointers(){return SgEnumFieldSymbol_count;}
20585
20586
20587 // SgFunctionSymbol
20588 void visit(SgFunctionDeclaration* node) {
20589 if(SgFunctionSymbolPtr !=NULL){
20590 if(node->get_scope()!=NULL){
20591 // DQ (5/21/2013): We want to restrict access to the symbol table.
20592 if(node->get_scope()->get_symbol_table()!=NULL)
20593 {
20595 if ((SgFunctionSymbol *)s == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20596 }
20597 }
20598 }
20599#if 0
20600 if(function_decl!=NULL){
20601 if(node->get_symbol_from_symbol_table() == NULL){
20604 if(node!=function_decl && (define==function_decl || first_nondefine==function_decl)) delete node;
20605 }
20606 }
20607#endif
20608 }
20609
20610 void visit(SgFunctionRefExp* node)
20611 {
20612#if 0
20613 printf ("In visit(SgFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20614#endif
20615 if (SgFunctionSymbolPtr !=NULL)
20616 {
20617 SgFunctionSymbol* s = node->get_symbol_i();
20618 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20619 {
20620 SgFunctionSymbol_count++;
20621#if 0
20622 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20623#endif
20624 }
20625 }
20626 }
20627
20628 // DQ (5/2/2013): Added support for SgMemberFunctionRefExp which is not derived from SgFunctionRefExp.
20629 void visit(SgMemberFunctionRefExp* node)
20630 {
20631#if 0
20632 printf ("In visit(SgMemberFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20633#endif
20634 if (SgFunctionSymbolPtr !=NULL)
20635 {
20636 SgFunctionSymbol* s = node->get_symbol_i();
20637 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20638 {
20639 SgFunctionSymbol_count++;
20640#if 0
20641 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20642#endif
20643 }
20644 }
20645 }
20646
20647 void visit(SgUserDefinedBinaryOp* node)
20648 {
20649 if (SgFunctionSymbolPtr !=NULL){
20650 SgFunctionSymbol* s = node->get_symbol();
20651 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20652 }
20653 }
20654
20655 int get_num_Function_pointers(){return SgFunctionSymbol_count;}
20656
20657 // SgClassSymbol
20658 void visit(SgClassDeclaration* node)
20659 {
20660 if(SgClassSymbolPtr !=NULL){
20661 if(node->get_scope()!=NULL){
20662 if(node->get_scope()->get_symbol_table()!=NULL)
20663 {
20665 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20666 }
20667 }
20668 }
20669
20670 if(class_defining!=NULL) {
20671 if(node->get_symbol_from_symbol_table() == NULL){
20674 if((class_decl==class_defining||class_decl1==class_defining) && node!=class_defining )
20675 delete node;
20676 }
20677 }
20678 }
20679
20680 void visit(SgTemplateInstantiationDecl* node)
20681 {
20682 if(SgClassSymbolPtr !=NULL){
20683 if(node->get_scope()!=NULL){
20684 if(node->get_scope()->get_symbol_table()!=NULL)
20685 {
20687 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20688 }
20689 }
20690 }
20691
20692 if(templateInstantiate_defining!=NULL) {
20693 if(node->get_scope()!=NULL){
20694 if(node->get_scope()->get_symbol_table()!=NULL)
20695 {
20696 if(node->get_symbol_from_symbol_table() == NULL){
20699 if((template_decl==templateInstantiate_defining||template_decl1==templateInstantiate_defining) && node!=templateInstantiate_defining){
20700 /*vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
20701 foreach (SgTemplateArgument* element, tempargs){
20702 SgTemplateArgument* temparg = isSgTemplateArgument(element);
20703 if(temparg){
20704 delete temparg;
20705 }
20706 printf("SgTemplateArg in Memory Pool traversal\n");
20707 }*/
20708 delete node;
20709 //printf("SgTemplateInstantiationDecl in Memory Pool traversal\n");
20710 }
20711 }
20712 }
20713 }
20714 }
20715 }
20716
20717 void visit(SgThisExp* node)
20718 {
20719 if (SgClassSymbolPtr !=NULL){
20720 SgSymbol* s = node->get_class_symbol();
20721 if (s == SgClassSymbolPtr) SgClassDeclaration_count++;
20722 }
20723 }
20724
20725 void visit(SgClassNameRefExp* node)
20726 {
20727 if (SgClassSymbolPtr !=NULL){
20728 SgSymbol* s = node->get_symbol();
20729 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20730 }
20731 }
20732
20733
20734 int get_num_Class_pointers(){return SgClassDeclaration_count;}
20735
20736
20737 // SgMemberFunctionSymbol
20738 void visit(SgCtorInitializerList* node)
20739 {
20740 if(memFunc !=NULL){
20742 if(func == memFunc){
20743 delete node;
20744 }
20745 }
20746 }
20747
20748
20749 void visit(SgMemberFunctionDeclaration* node)
20750 {
20751 if (SgMemFuncSymbolPtr !=NULL){
20752 if(node->get_scope()!=NULL){
20753 if(node->get_scope()->get_symbol_table()!=NULL)
20754 {
20755 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20756 if(symbol == SgMemFuncSymbolPtr){
20757 SgMemFuncSymbol_count++;
20758 }
20759 }
20760 }
20761 }
20762 }
20763
20765 {
20766 if (SgMemFuncSymbolPtr !=NULL){
20767 if(node->get_scope()!=NULL){
20768 if(node->get_scope()->get_symbol_table()!=NULL)
20769 {
20770 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
20771 if(symbol == SgMemFuncSymbolPtr){
20772 SgMemFuncSymbol_count++;
20773 }
20774 }
20775 }
20776 }
20777 }
20778
20779
20780
20781 int get_num_memFunc_pointers(){return SgMemFuncSymbol_count;}
20782
20783
20784 // SgTypedefSymbol
20785 void visit(SgTypedefDeclaration* node)
20786 {
20787 if(SgTypedefPtr!=NULL){
20788 if(node->get_scope()!=NULL){
20789 if(node->get_scope()->get_symbol_table()!=NULL)
20790 {
20792 if ((SgTypedefSymbol *)s == SgTypedefPtr) SgTypedefSymbol_count++;
20793 }
20794 }
20795 }
20796 if(typedef_defining!=NULL){
20798 if(typedef_define == typedef_defining && node != typedef_defining ) {
20799 delete node;
20800 }
20801 }
20802 }
20803
20804 int get_num_Typedef_pointers(){return SgTypedefSymbol_count;}
20805
20806
20807
20808 void visit(SgTemplateDeclaration* node)
20809 {
20810 if (SgTemplateSymbolPtr !=NULL){
20811 if(node->get_scope()!=NULL){
20812 if(node->get_scope()->get_symbol_table()!=NULL)
20813 {
20814 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
20815 if(symbol == SgTemplateSymbolPtr){
20816 SgTemplateSymbol_count++;
20817 }
20818 }
20819 }
20820 }
20821
20822 if(template_defining !=NULL) {
20823 if(node->get_scope()!=NULL){
20824 if(node->get_scope()->get_symbol_table()!=NULL)
20825 {
20826 if(node->get_symbol_from_symbol_table() == NULL){
20829 if((template_decl==template_defining||template_decl1==template_defining) && node!=template_defining) {
20830 delete node;
20831
20832 }
20833 }
20834 }
20835 }
20836 }
20837 }
20838
20839 int get_num_Template_pointers(){return SgTemplateSymbol_count;}
20840
20841 };
20842
20843
20844 //Tan August,25,2010 //Traverse AST in post order, delete nodes and their symbols if it's safe to do so
20845 class DeleteAST : public SgSimpleProcessing, ROSE_VisitTraversal
20846 {
20847 public:
20848
20849 void visit (SgNode* node)
20850 {
20851 //These nodes are manually deleted because they cannot be visited by the traversal
20853 //remove SgVariableDefinition, SgVariableSymbol and SgEnumFieldSymbol
20855#if 0
20856 printf ("In DeleteAST::visit(): node = %p = %s \n",node,node->class_name().c_str());
20857#endif
20858#if 0
20859 // DQ (3/2/2014): I think this might be a problem...
20860 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
20861 if (isSgScopeStatement(node) !=NULL)
20862 {
20863 SgScopeStatement* scope = isSgScopeStatement(node);
20864#if 1
20865 printf ("Deleting the scopes type table: scope->get_type_table() = %p \n",scope->get_type_table());
20866#endif
20867 delete scope->get_type_table();
20868 }
20869#endif
20870#if 0
20871 // DQ (3/2/2014): I think this might be a problem...
20872 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
20873 if (isSgTypeTable(node) !=NULL)
20874 {
20875 SgTypeTable* typeTable = isSgTypeTable(node);
20876#if 1
20877 printf ("Deleting the type table (SgSymbolTable): typeTable->get_type_table() = %p \n",typeTable->get_type_table());
20878#endif
20879 delete typeTable->get_type_table();
20880 }
20881#endif
20882 if(isSgInitializedName(node) !=NULL){
20883 //remove SgVariableDefinition
20884 SgDeclarationStatement* var_def;
20885 var_def = ((SgInitializedName *)node)->get_definition();
20886 if(isSgVariableDefinition(var_def) !=NULL){
20887 delete var_def;
20888 //printf("A SgVariableDefinition was deleted\n");
20889 }
20890
20891
20892 //remove SgVariableSymbol
20893 if(isSgInitializedName(node)->get_scope()!=NULL){
20894 if(isSgInitializedName(node)->get_scope()->get_symbol_table()!=NULL)
20895 {
20896 SgSymbol* symbol = ((SgInitializedName *)node)->get_symbol_from_symbol_table();
20897 if(isSgVariableSymbol(symbol) !=NULL){
20898 ClassicVisitor visitor((SgVariableSymbol*)symbol);
20899 traverseMemoryPoolVisitorPattern(visitor);
20900 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20901 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20902 delete symbol;
20903 //printf("A SgVariableSymbol was deleted\n");
20904 }
20905 }
20906
20907 if(isSgEnumFieldSymbol(symbol) !=NULL){
20908 ClassicVisitor visitor((SgEnumFieldSymbol*)symbol);
20909 traverseMemoryPoolVisitorPattern(visitor);
20910 if(visitor.get_num_EnumField_pointers()==1){
20911 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20912 delete symbol;
20913 //printf("A SgEnumFieldSymbol was deleted\n");
20914 }
20915 }
20916
20917 }
20918 }
20919 }
20920
20921 if(isSgVarRefExp(node) !=NULL){
20922 SgVariableSymbol *symbol = ((SgVarRefExp*)node)->get_symbol();
20923 ClassicVisitor visitor(symbol);
20924 traverseMemoryPoolVisitorPattern(visitor);
20925 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20926 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20927 delete symbol;
20928 //printf("A SgVariableSymbol was deleted\n");
20929 }
20930 }
20931
20932 /*////////////////////////////////////////////////
20933 /remove SgFunctionSymbol
20935
20936 {
20937 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(node);
20938 if (funcDecl != NULL){
20939 if (isSgMemberFunctionDeclaration(node) == NULL) {
20940 if (funcDecl->get_scope() != NULL) {
20941 if (funcDecl->get_scope()->get_symbol_table() != NULL) {
20942 SgSymbol* symbol = ((SgFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20943 ClassicVisitor visitor((SgFunctionSymbol *)symbol);
20944 traverseMemoryPoolVisitorPattern(visitor);
20945 if (visitor.get_num_Function_pointers()==1) { //only one reference to this FunctionSymbol => safe to delete
20946 ((SgFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
20947 delete symbol;
20948 //printf("A SgFunctionSymbol was deleted\n");
20949 }
20950 ClassicVisitor visitor1((SgFunctionDeclaration *)node);
20951 traverseMemoryPoolVisitorPattern(visitor1);
20952 }
20953 }
20954 }
20955 }
20956 }
20957
20958 if(isSgFunctionRefExp(node) !=NULL)
20959 {
20960#if 0
20961 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(node);
20962 ROSE_ASSERT(functionRefExp->get_symbol_i() != NULL);
20963 printf ("In DeleteAST::visit(): functionRefExp->get_symbol_i() = %p = %s \n",functionRefExp->get_symbol_i(),functionRefExp->get_symbol_i()->class_name().c_str());
20964#endif
20965 SgFunctionSymbol *symbol = ((SgFunctionRefExp*)node)->get_symbol_i();
20966 ClassicVisitor visitor(symbol);
20967 traverseMemoryPoolVisitorPattern(visitor);
20968 if(visitor.get_num_Function_pointers()==1)
20969 {
20970 // only one reference to this FunctionSymbol => safe to delete
20971 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20972 delete symbol;
20973 //printf("A SgFunctionSymbol was deleted\n");
20974 }
20975
20976 }
20977
20978 if(isSgUserDefinedBinaryOp(node) !=NULL){
20979 SgFunctionSymbol *symbol = ((SgUserDefinedBinaryOp*)node)->get_symbol();
20980 ClassicVisitor visitor(symbol);
20981 traverseMemoryPoolVisitorPattern(visitor);
20982 if(visitor.get_num_Function_pointers()==1){ //only one reference to this FunctionSymbol => safe to delete
20983 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20984 delete symbol;
20985 //printf("A SgFunctionSymbol was deleted\n");
20986 }
20987 }
20988
20989 /*/
20990 /remove SgTypedefSymbol
20992
20993 if(isSgTypedefDeclaration(node) !=NULL){
20994 if(((SgTypedefDeclaration*)node)->get_scope()!=NULL){
20995 if(((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
20996 {
20997 SgSymbol* symbol = ((SgTypedefDeclaration*)node)->get_symbol_from_symbol_table();
20998 if(isSgTypedefSymbol(symbol)){
20999 ClassicVisitor visitor((SgTypedefSymbol*) symbol);
21000 traverseMemoryPoolVisitorPattern(visitor);
21001 if(visitor.get_num_Typedef_pointers()==1){ //only one reference to this SgTypedefSymbol => safe to delete
21002 ((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21003 delete symbol;
21004 //printf("A SgTypedefSymbol was deleted\n");
21005 }
21006 }
21007 }
21008 }
21009
21010 if(node == isSgTypedefDeclaration(node)->get_definingDeclaration()){
21011 ClassicVisitor visitor1((SgTypedefDeclaration*) node);
21012 traverseMemoryPoolVisitorPattern(visitor1);
21013 }
21014 }
21015
21016 /*////////////////////////////////////////////////
21017 /remove SgNamespaceDeclarationSymbol
21019
21020 if(isSgNamespaceDeclarationStatement(node) !=NULL){
21021 if(((SgNamespaceDeclarationStatement*)node)->get_scope()!=NULL){
21022 if(((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21023 {
21024 SgSymbol* symbol = ((SgNamespaceDeclarationStatement*)node)->get_symbol_from_symbol_table();
21025 if(isSgNamespaceSymbol(symbol)){
21026 ((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21027 delete symbol;
21028 //printf("A SgNamespaceSymbol was deleted\n");
21029 }
21030 }
21031 }
21032 }
21033
21034
21035 if(isSgNamespaceAliasDeclarationStatement(node) !=NULL){
21036 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()!=NULL){
21037 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21038 {
21039 SgSymbol* symbol = ((SgNamespaceAliasDeclarationStatement*)node)->get_symbol_from_symbol_table();
21040 if(isSgNamespaceSymbol(symbol)){
21041 ((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21042 delete symbol;
21043 //printf("A SgNamespaceSymbol was deleted\n");
21044 }
21045 }
21046 }
21047 }
21048
21049
21050 /*/
21051 /remove SgLabelSymbol
21053
21054 if(isSgLabelStatement(node) !=NULL){
21055 if(((SgLabelStatement*)node)->get_scope()!=NULL){
21056 if(((SgLabelStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21057 {
21058 SgSymbol* symbol = ((SgLabelStatement*)node)->get_symbol_from_symbol_table();
21059 if(isSgLabelSymbol(symbol)){
21060 ((SgLabelStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21061 delete symbol;
21062 //printf("A SgLabelSymbol was deleted\n");
21063 }
21064 }
21065 }
21066 }
21067
21068 if(isSgLabelRefExp(node) !=NULL){
21069 SgLabelSymbol* symbol = ((SgLabelRefExp*)node)->get_symbol();
21070 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21071 delete symbol;
21072 //printf("A SgLabelSymbol was deleted\n");
21073 }
21074
21075
21076 /*////////////////////////////////////////////////
21077 /remove SgEnumSymbol
21079
21080 if(isSgEnumDeclaration(node) !=NULL){
21081 if(((SgEnumDeclaration*)node)->get_scope()!=NULL){
21082 if(((SgEnumDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21083 {
21084 SgSymbol* symbol = ((SgEnumDeclaration*)node)->get_symbol_from_symbol_table();
21085 if(isSgEnumSymbol(symbol) !=NULL){
21086 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21087 delete symbol;
21088 //printf("A SgEnumSymbol was deleted\n");
21089 }
21090 }
21091 }
21092 SgEnumType* type= ((SgEnumDeclaration*)node)->get_type();
21093 if(type !=NULL){
21094 delete type;
21095 //printf("A SgEnumType was deleted\n");
21096 }
21097 }
21098
21099
21100 /*/
21101 /remove SgClassSymbol
21103
21104 if(isSgClassDeclaration(node) !=NULL && isSgTemplateInstantiationDecl(node) ==NULL){
21105 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21106 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21107 {
21108 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21109 if(isSgClassSymbol(symbol) !=NULL){
21110 ClassicVisitor visitor((SgClassSymbol*)symbol);
21111 traverseMemoryPoolVisitorPattern(visitor);
21112 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21113 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21114 delete symbol;
21115 //printf("A SgClassSymbol was deleted\n");
21116 }
21117 }
21118 }
21119 }
21120
21121 ClassicVisitor visitor((SgClassDeclaration*) node );
21122 traverseMemoryPoolVisitorPattern(visitor);
21123
21124 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21125 if(type !=NULL){
21126 delete type;
21127 //printf("A SgClassType was deleted\n");
21128 }
21129 }
21130
21131 if(isSgThisExp(node) !=NULL){
21132 SgSymbol* symbol = ((SgThisExp*)node)->get_class_symbol();
21133 ClassicVisitor visitor((SgClassSymbol*)symbol);
21134 traverseMemoryPoolVisitorPattern(visitor);
21135 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21136 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21137 delete symbol;
21138 //printf("A SgClassSymbol was deleted\n");
21139 }
21140
21141 }
21142
21143 if(isSgClassNameRefExp(node) !=NULL){
21144 SgSymbol* symbol = ((SgClassNameRefExp*)node)->get_symbol();
21145 if(isSgClassSymbol(symbol) !=NULL)
21146 {
21147 ClassicVisitor visitor((SgClassSymbol*)symbol);
21148 traverseMemoryPoolVisitorPattern(visitor);
21149 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21150 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21151 delete symbol;
21152 //printf("A SgClassSymbol was deleted\n");
21153 }
21154 }
21155 }
21156
21157 /*////////////////////////////////////////////////
21158 /remove SgMemberFunctionSymbol
21160
21161
21162 if(isSgMemberFunctionDeclaration(node) !=NULL){
21163 if(((SgMemberFunctionDeclaration*)node)->get_scope()!=NULL){
21164 if(((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21165 {
21166 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21167 if(isSgMemberFunctionSymbol(symbol)){
21168 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21169 traverseMemoryPoolVisitorPattern(visitor);
21170 if(visitor.get_num_memFunc_pointers()==1){
21171 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21172 delete symbol;
21173 //printf("A SgMemberFunctionSymbol was deleted\n");
21174 }
21175 }
21176 }
21177 }
21178 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21179 traverseMemoryPoolVisitorPattern(visitor);
21180
21181 }
21182//Tan: I have no idea why the codes below cannot work. Perhaps it conflicts with some prior works
21183#if 0
21184 if(isSgMemberFunctionRefExp(node) !=NULL){
21185 SgMemberFunctionSymbol* symbol = ((SgMemberFunctionRefExp*)node)->get_symbol_i();
21186 ClassicVisitor visitor(symbol);
21187 traverseMemoryPoolVisitorPattern(visitor);
21188 if(visitor.get_num_memFunc_pointers()==1){ //only one reference to this symbol => safe to delete
21189 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21190 delete symbol;
21191 //printf("A SgClassSymbol was deleted\n");
21192 }
21193
21194 }
21195
21196 if(isSgFunctionType(node) !=NULL){
21197 SgSymbol* symbol = ((SgFunctionType*)node)->get_symbol_from_symbol_table();
21198 if(isSgFunctionTypeSymbol(symbol)){
21199 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21200 delete symbol;
21201 //printf("A SgFunctionTypeSymbol was deleted\n");
21202 }
21203 }
21204#endif
21205
21206 /*/
21209
21210 if(isSgInterfaceStatement(node) !=NULL){
21211 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21212 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21213 {
21214 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21215 if(isSgInterfaceSymbol(symbol)){
21216 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21217 delete symbol;
21218 //printf("A SgInterfaceSymbol was deleted\n");
21219 }
21220 }
21221 }
21222
21223 }
21224
21225
21226 if(isSgModuleStatement(node) !=NULL){
21227 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21228 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21229 {
21230 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21231 if(isSgModuleSymbol(symbol)){
21232 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21233 delete symbol;
21234 //printf("A SgModuleSymbol was deleted\n");
21235 }
21236 }
21237 }
21238
21239 }
21240
21241
21242//Tan: I got stuck in deleting the SgTemplateArgument
21243#if 0
21244 if(isSgTemplateInstantiationMemberFunctionDecl(node) !=NULL){
21245 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()!=NULL){
21246 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21247 {
21248 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
21249 if(isSgMemberFunctionSymbol(symbol)){
21250 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21251 traverseMemoryPoolVisitorPattern(visitor);
21252 if(visitor.get_num_memFunc_pointers()==1){
21253 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21254 delete symbol;
21255 //printf("A SgMemberFunctionSymbol was deleted\n");
21256 }
21257 }
21258 }
21259 }
21260 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21261 traverseMemoryPoolVisitorPattern(visitor);
21262 }
21263
21264 if(isSgTemplateDeclaration(node) !=NULL){
21265 if(((SgTemplateDeclaration*)node)->get_scope()!=NULL){
21266 if(((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21267 {
21268 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
21269 ClassicVisitor visitor((SgTemplateSymbol*)symbol);
21270 traverseMemoryPoolVisitorPattern(visitor);
21271 if(visitor.get_num_Template_pointers()==1){
21272 ((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21273 delete symbol;
21274 printf("A SgTemplateSymbol was deleted\n");
21275 }
21276 }
21277 }
21278 //if(isSgTemplateDeclaration(node) == ((SgTemplateDeclaration*)node)->get_firstNondefiningDeclaration()){
21279 ClassicVisitor visitor1((SgTemplateDeclaration*) node );
21280 traverseMemoryPoolVisitorPattern(visitor1);
21281 //}
21282
21283 }
21284
21285 if(isSgInterfaceStatement(node) !=NULL){
21286 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21287 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21288 {
21289 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21290 if(isSgInterfaceSymbol(symbol)){
21291 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21292 delete symbol;
21293 //printf("A SgInterfaceSymbol was deleted\n");
21294 }
21295 }
21296 }
21297
21298 }
21299
21300
21301 if(isSgModuleStatement(node) !=NULL){
21302 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21303 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21304 {
21305 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21306 if(isSgModuleSymbol(symbol)){
21307 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21308 delete symbol;
21309 //printf("A SgModuleSymbol was deleted\n");
21310 }
21311 }
21312 }
21313
21314 }
21315
21316 if(isSgTemplateInstantiationDecl(node) !=NULL){
21317 if(((SgTemplateInstantiationDecl*)node)->get_scope()!=NULL){
21318 if(((SgTemplateInstantiationDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21319 {
21320 SgSymbol* symbol = ((SgTemplateInstantiationDecl*)node)->get_symbol_from_symbol_table();
21321 if(isSgClassSymbol(symbol)){
21322 ClassicVisitor visitor((SgClassSymbol*)symbol);
21323 traverseMemoryPoolVisitorPattern(visitor);
21324 if(visitor.get_num_Class_pointers()==1){
21325 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21326 delete symbol;
21327 }
21328 }
21329 }
21330 }
21331 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21332 if(type !=NULL){
21333 delete type;
21334 //printf("A SgClassType was deleted\n");
21335 }
21336
21337 vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
21338 foreach (SgTemplateArgument* element, tempargs){
21339 SgTemplateArgument* temparg = isSgTemplateArgument(element);
21340 if(temparg){
21341 delete temparg;
21342 }
21343 printf("SgTemplateArg in normal traversal\n");
21344 }
21345 printf("SgTemplateInstantiationDecl in normal traversal\n");
21346
21347 ClassicVisitor visitor((SgTemplateInstantiationDecl*) node);
21348 traverseMemoryPoolVisitorPattern(visitor);
21349 }
21350
21351#endif
21352#if 0
21353 printf ("Deleting node = %p = %s = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
21354#endif
21355 // Normal nodes will be removed in a post-order way
21356 delete node;
21357#if 0
21358 printf ("After delete node: node = %p = %s \n",node,node->class_name().c_str());
21359#endif
21360 }
21361 };
21362
21363
21364 DeleteAST deleteTree;
21365
21366 // Deletion must happen in post-order to avoid traversal of (visiting) deleted IR nodes
21367 deleteTree.traverse(n,postorder);
21368
21369#if 0
21370 printf ("Leaving SageInterface::deleteAST(): n = %p = %s \n",n,n->class_name().c_str());
21371#endif
21372 }
21373
21374
21375
21376
21377#ifndef USE_ROSE
21378// DQ (9/25/2011): The deleteAST() function will not remove original expression trees behind constant folded expressions.
21379// These exist in the AST within the internal construction of the AST until they are simplified in the AST post-processing.
21380// In the post-processing either:
21381// 1) the constant folded values are kept and the original expression trees deleted (optional, controled by default parameter to function "frontend()", OR
21382// 2) the constant folded values are replaced by the original expression trees, and the constant folded values are deleted (default).
21383// Either way, after the AST post-processing the AST is simplified. Until then the expression trees can contain constant
21384// folded values and the values will have a pointer to the original expression tree. Before (9/16/2011) the original
21385// tree would also sometimes (not uniformally) be traversed as part of the AST. This was confusing (to people and
21386// to numerous forms of analysis), so this is being fixed to be uniform (using either of the methods defined above).
21387// However, the fact that until post-processing the AST has this complexity, and that the AST traversal does not
21388// traverse the original expression trees (now uniform); means that we need a special delete function for subtrees
21389// that are not use post-processed. This is the special purpose function that we need.
21390//
21391// NOTE: This function is called from the SgArrayType::createType() member function and in the constant folding AST post-processing.
21392//
21394 {
21395 struct Visitor: public AstSimpleProcessing
21396 {
21397 virtual void visit(SgNode* n)
21398 {
21399 SgExpression* expression = isSgExpression(n);
21400 if (expression != NULL)
21401 {
21402 Visitor().traverse(expression->get_originalExpressionTree(), postorder);
21403 }
21404
21405 delete (n);
21406 }
21407 };
21408
21409 Visitor().traverse(root, postorder);
21410 }
21411#endif
21412 // move symbol table from one scope to another
21413static void moveSymbolTableBetweenBlocks(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, std::vector <SgInitializedName*>& initname_vec)
21414{
21415 // Move the symbol table
21416 SgSymbolTable* s_table = sourceBlock->get_symbol_table();
21417 ASSERT_not_null(sourceBlock->get_symbol_table());
21418 // Liao, 11/26/2019 make sure the symbol table has symbols for init names before and after the move
21419 for (SgInitializedName* iname : initname_vec)
21420 {
21421 SgSymbol* symbol = s_table->find(iname);
21422 ASSERT_not_null(symbol);
21423 }
21424 // entirely move source block's symbol table to target block
21425 targetBlock->set_symbol_table(sourceBlock->get_symbol_table());
21426
21427 ASSERT_not_null(sourceBlock);
21428 ASSERT_not_null(targetBlock);
21429 ASSERT_not_null(targetBlock->get_symbol_table());
21430 ASSERT_not_null(sourceBlock->get_symbol_table());
21431 targetBlock->get_symbol_table()->set_parent(targetBlock);
21432
21433 ASSERT_not_null(sourceBlock->get_symbol_table());
21434 sourceBlock->set_symbol_table(nullptr);
21435
21436 // Reset with a valid symbol table
21437 sourceBlock->set_symbol_table(new SgSymbolTable());
21438 sourceBlock->get_symbol_table()->set_parent(sourceBlock);
21439
21440 ASSERT_require(targetBlock->get_symbol_table() == s_table);
21441 for (SgInitializedName* iname : initname_vec)
21442 {
21443 SgSymbol* symbol = s_table->find(iname);
21444 ASSERT_not_null(symbol);
21445 }
21446
21447 // Liao, 11/26/2019 make sure init names have symbols after the move.
21448 for (SgInitializedName* iname : initname_vec)
21449 {
21450 SgSymbol* symbol = iname->get_symbol_from_symbol_table();
21451 ASSERT_not_null(symbol);
21452 }
21453}
21454
21455// helper function to move a single statement or declaration from a block to another
21456static void moveOneStatement(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, SgStatement* stmt, std::vector <SgInitializedName*>& initname_vec)
21457{
21458 // append statement to the target block
21459 targetBlock->append_statement(stmt);
21460
21461 // Make sure that the parents are set.
21462 ASSERT_require(stmt->get_parent() == targetBlock);
21463 if (stmt->hasExplicitScope())
21464 {
21465 if (stmt->get_scope() != targetBlock)
21466 {
21467 if (SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt))
21468 {
21469 // why only move if it is a first nondefining declaration?
21470 // We have a case to move both defining and nondefining function declarations of Ada package body to namespace definition.
21471 // comment out the if condition for now. 1/20/2021
21472 //
21473 // A call to a undeclared function will introduce a hidden func prototype declaration in the enclosing scope .
21474 // The func declaration should be moved along with the call site.
21475 // The scope should be set to the new block also
21476 // Liao 1/14/2011
21477 func->set_scope(targetBlock);
21478 // This is needed to move functions in Ada package body into C++ namespace
21479 // We may have compiler generated first nondefining declaration. We need to move its scope also
21480 SgFunctionDeclaration* nondef_decl= isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
21481 if (func != nondef_decl)
21482 {
21483 ASSERT_not_null(nondef_decl);
21484 ASSERT_not_null(nondef_decl->get_file_info());
21485 if (nondef_decl->get_file_info()->isCompilerGenerated()) {
21486 nondef_decl->set_scope(targetBlock);
21487 }
21488 }
21489 }
21490 else if (auto labelStmt = isSgLabelStatement(stmt))
21491 {
21492 if (labelStmt->get_scope() == sourceBlock) {
21493 labelStmt->set_scope(targetBlock);
21494 // Make sure the labelStmt is in the enclosing function scope of targetBlock
21495 SageInterface::fixLabelStatement(labelStmt, targetBlock);
21496 }
21497 }
21498 else if (isSgJovialTableStatement(stmt) || isSgTypedefDeclaration(stmt) || isSgEnumDeclaration(stmt))
21499 {
21500 // Rasmussen 9/21/2020,10/27/2020,11/4/2020: Uncovered by issues RC-135 and RC-227.
21501 // The issues are fixed in the switch statement below but this test is needed
21502 // so that the warning message immediately below is not triggered.
21503 }
21504 else
21505 {
21506 mlog[Rose::Diagnostics::WARN] << "test failing stmt->get_scope() == targetBlock in SageInterface::moveStatementsBetweenBlocks(): class: "
21507 << stmt->class_name() << "\n";
21508 }
21509 }
21510 }
21511
21512 SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
21513 if (declaration != nullptr)
21514 {
21515 // Need to reset the scope from sourceBlock to targetBlock.
21516 switch(declaration->variantT())
21517 {
21518 // There will be other cases to handle, but likely not all declaration will be possible to support.
21519
21520 case V_SgVariableDeclaration:
21521 {
21522 // Reset the scopes on any SgInitializedName objects.
21523 SgVariableDeclaration* varDecl = isSgVariableDeclaration(declaration);
21524 SgInitializedNamePtrList & l = varDecl->get_variables();
21525 for (SgInitializedNamePtrList::iterator ii = l.begin(); ii != l.end(); ii++)
21526 {
21527 // reset the scope, but make sure it was set to sourceBlock to make sure.
21528 // This might be an issue for extern variable declaration that have a scope
21529 // in a separate namespace of a static class member defined external to
21530 // its class, etc. I don't want to worry about those cases right now.
21531
21532 SgInitializedName * init_name = (*ii);
21533
21534 // Rasmussen (3/16/2021): Use the base type in case type is modified (i.e., const)
21535 SgType* var_type = init_name->get_type();
21536 if (SgModifierType* mod_type = isSgModifierType(var_type))
21537 {
21538 var_type = mod_type->get_base_type();
21539 }
21540
21541 // Rasmussen (6/29/2020) and (10/19/2020): Variable declarations related to anonymous types are not
21542 // moved. This is fixed below. Note that SgJovialTableType derives from SgClassType, it may
21543 // be that class types are not moved correctly either.
21544 //
21545 if (isSgEnumType(var_type))
21546 {
21547 SgEnumType* enum_type = isSgEnumType(var_type);
21548 SgEnumDeclaration* decl = isSgEnumDeclaration(enum_type->get_declaration());
21549 SgEnumDeclaration* def_decl = isSgEnumDeclaration(decl->get_definingDeclaration());
21550 SgEnumDeclaration* nondef_decl = isSgEnumDeclaration(decl->get_firstNondefiningDeclaration());
21551
21552 if (decl->get_scope() == sourceBlock)
21553 {
21554 // Needs to be moved
21555 def_decl->set_scope(targetBlock);
21556 nondef_decl->set_scope(targetBlock);
21557 nondef_decl->set_parent(targetBlock);
21558
21559 // Move the scope of the enumerators to the new block as well
21560 for (SgInitializedName* enumerator : def_decl->get_enumerators())
21561 {
21562 enumerator->set_scope(targetBlock);
21563 }
21564 }
21565 }
21566 else if (isSgJovialTableType(var_type))
21567 {
21568 SgJovialTableType* table_type = isSgJovialTableType(var_type);
21569 SgDeclarationStatement* decl = table_type->get_declaration();
21570 if (decl->get_scope() == sourceBlock)
21571 {
21572 // Needs to be moved
21575 def_decl->set_scope(targetBlock);
21576 nondef_decl->set_scope(targetBlock);
21577 nondef_decl->set_parent(targetBlock);
21578 }
21579 }
21580
21581 // Must also move the symbol into the source block, Liao 2019/8/14
21582 SgVariableSymbol* var_sym = isSgVariableSymbol(init_name -> search_for_symbol_from_symbol_table ()) ;
21583 ASSERT_not_null(var_sym);
21584 SgScopeStatement * old_scope = var_sym -> get_scope();
21585#if 1 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21586 if (old_scope != sourceBlock)
21587 {
21588 old_scope->remove_symbol (var_sym);
21589 sourceBlock ->insert_symbol(init_name->get_name(), var_sym);
21590 }
21591#endif
21592 init_name->set_scope(targetBlock);
21593 initname_vec.push_back(init_name);
21594 }
21595 break;
21596 }
21597 case V_SgFunctionDeclaration: // Liao 1/15/2009, I don't think there is any extra things to do here
21598 {
21599 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(declaration);
21600 ASSERT_not_null(funcDecl);
21601#if 0 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21602 // move function symbols also: search_for_symbol_from_symbol_table()
21604 if (func_sym)
21605 {
21606 SgScopeStatement * old_scope = func_sym -> get_scope();
21607 if (old_scope != sourceBlock)
21608 {
21609 old_scope->remove_symbol (func_sym);
21610 sourceBlock ->insert_symbol(func_sym->get_name(), func_sym);
21611 }
21612 }
21613#endif
21614 break;
21615 }
21616 // needed to move Ada record into definition of C++ namespace
21617 case V_SgProgramHeaderStatement:
21618 case V_SgProcedureHeaderStatement:
21619 case V_SgClassDeclaration:
21620 case V_SgEnumDeclaration:
21621 {
21622 SgDeclarationStatement* nondef_decl = declaration->get_firstNondefiningDeclaration();
21623 ASSERT_not_null(nondef_decl);
21624
21625 nondef_decl->set_parent(targetBlock);
21626 nondef_decl->set_scope(targetBlock);
21627
21628 SgDeclarationStatement* def_decl = declaration->get_definingDeclaration();
21629 if (def_decl)
21630 {
21631 def_decl->set_parent(targetBlock);
21632 def_decl->set_scope(targetBlock);
21633 }
21634 else
21635 {
21636 // Set the scope of the function arguments
21637 if (auto proc = isSgProcedureHeaderStatement(nondef_decl)) {
21638 for (auto arg : proc->get_parameterList()->get_args()) {
21639 if (arg->get_scope() != proc->get_scope()) {
21640 // Note: arg (is an SgInitializedName) from the parameter list does not have
21641 // a symbol in the scope of the procedure declaration (proc). Should add
21642 // arg to initname_vec, which will check for missing symbols [GL-387, Rasmussen 7/22/2024].
21643 arg->set_scope(proc->get_scope());
21644 }
21645 }
21646 }
21647 }
21648
21649 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(stmt);
21650 if (enum_decl)
21651 {
21652 // Set the scope of the enumerators [Rasmussen 12/23/2020]
21653 for (SgInitializedName* name : enum_decl->get_enumerators())
21654 {
21655 name->set_scope(targetBlock);
21656 }
21657 }
21658 break;
21659 }
21660 case V_SgJovialTableStatement:
21661 {
21662 // [RC-135, Rasmussen 9/21/2020]
21663 SgJovialTableStatement* table = isSgJovialTableStatement(declaration);
21664 ROSE_ASSERT (table);
21665
21668 nondef_decl->set_parent(targetBlock);
21669 nondef_decl->set_scope(targetBlock);
21670 def_decl->set_scope(targetBlock);
21671 break;
21672 }
21673 case V_SgTypedefDeclaration:
21674 {
21675 // [RC-227, Rasmussen 10/19/2020]
21676 SgTypedefDeclaration* typedef_decl = isSgTypedefDeclaration(declaration);
21677 ASSERT_not_null(typedef_decl);
21678 typedef_decl->set_parent(targetBlock);
21679 typedef_decl->set_scope(targetBlock);
21680 break;
21681 }
21682 case V_SgAttributeSpecificationStatement:
21683 case V_SgEmptyDeclaration:
21684 case V_SgFortranIncludeLine:
21685 case V_SgImplicitStatement: // Rasmussen 5/13/2021: TODO: implicit statement with letter-list
21686 case V_SgJovialDefineDeclaration:
21687 case V_SgJovialDirectiveStatement:
21688 case V_SgJovialLabelDeclaration:
21689 case V_SgJovialOverlayDeclaration:
21690 case V_SgPragmaDeclaration:
21691 case V_SgAdaAttributeClause:
21692 break;
21693 default:
21694 {
21695 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());
21696 declaration->get_file_info()->display("file info");
21697 ROSE_ABORT();
21698 }
21699 }
21700 } // end if
21701}
21702
21703// different handling for scopes with declarations only
21704template <class T1, class T2>
21705void moveDeclarationsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21706{
21707 // This function moves statements from one block to another (used by the outliner).
21708 // printf ("***** Moving statements from sourceBlock %p to targetBlock %p ***** \n",sourceBlock,targetBlock);
21709 ROSE_ASSERT (sourceBlock && targetBlock);
21710 ROSE_ASSERT (sourceBlock->containsOnlyDeclarations() && targetBlock->containsOnlyDeclarations());
21711 if ((void*)sourceBlock == (void*)targetBlock)
21712 {
21713 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21714 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21715 return;
21716 }
21717
21718 SgDeclarationStatementPtrList& srcStmts = sourceBlock->get_declarations ();
21719 std::vector <SgInitializedName*> initname_vec;
21720
21721 for (auto stmt : srcStmts)
21722 {
21723 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21724 }
21725
21726 // Remove the statements in the sourceBlock
21727 srcStmts.clear();
21728 ROSE_ASSERT(srcStmts.empty() == true);
21729 ROSE_ASSERT(sourceBlock->get_declarations().empty() == true);
21730
21731 // move symbol table from one scope to another
21732 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21733
21734 // Liao 2/4/2009
21735 // Finally , move preprocessing information attached inside the source block to the target block
21736 // Outliner uses this function to move a code block to the outlined function.
21737 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21738 // to the target block to match #if (which is attached
21739 // before some statement moved to the target block)
21740 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21741}
21742
21743
21744// source and destination class, both are derived classes of scope statement but with support of get_statements()
21745template <class T1, class T2>
21746void moveStatementsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21747{
21748 // This function moves statements from one block to another (used by the outliner).
21749 ROSE_ASSERT (sourceBlock && targetBlock);
21750 if ((void*)sourceBlock == (void*)targetBlock)
21751 {
21752 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21753 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21754 return;
21755 }
21756
21757 SgStatementPtrList & srcStmts = sourceBlock->get_statements();
21758 std::vector <SgInitializedName*> initname_vec;
21759
21760 for (SgStatement* stmt : srcStmts)
21761 {
21762 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21763 }
21764
21765 // Remove the statements in the sourceBlock
21766 srcStmts.clear();
21767 ROSE_ASSERT(srcStmts.empty() == true);
21768 ROSE_ASSERT(sourceBlock->get_statements().empty() == true);
21769
21770 // move symbol table from one scope to another
21771 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21772
21773 // Liao 2/4/2009
21774 // Finally , move preprocessing information attached inside the source block to the target block
21775 // Outliner uses this function to move a code block to the outlined function.
21776 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21777 // to the target block to match #if (which is attached
21778 // before some statement moved to the target block)
21779 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21780
21781}
21782
21783static void createAliasSymbols (SgNamespaceDeclarationStatement* decl)
21784{
21785 ASSERT_not_null(decl);
21787 SgNamespaceDefinitionStatement* global_def = local_def->get_global_definition();
21788
21789 ASSERT_require(local_def && global_def && (local_def!=global_def));
21790
21791 for (auto symbol : local_def->get_symbol_table()->get_symbols())
21792 {
21793 SgSymbol *orig_sym = isSgSymbol(symbol);
21794 ASSERT_not_null(orig_sym);
21795 SgAliasSymbol* asym = new SgAliasSymbol (orig_sym);
21796 global_def->get_symbol_table()->insert (asym->get_name(), asym);
21797 }
21798}
21799
21800//TODO: now with more types, we need to use template functions
21802{
21803 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21804 //create alias symbols in its global definition
21805 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21806}
21807
21809{
21810 moveStatementsBetweenScopes(sourceBlock, targetBlock);
21811 //create alias symbols in its global definition
21812 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21813}
21814
21816{
21817 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21818}
21819
21820void
21822{
21823 moveStatementsBetweenScopes (sourceBlock, targetBlock);
21824}
21825
21827// TODO, expose to SageInterface namespace
21829{
21830 bool rt = false;
21831 ROSE_ASSERT (func != NULL);
21832 SgNode* p = func->get_parent();
21833 ROSE_ASSERT (p != NULL);
21834 SgLambdaExp* le = isSgLambdaExp (p);
21835 if (le && le->get_lambda_function() == func)
21836 rt = true;
21837 return rt;
21838}
21839
21840// check if a variable reference is this->a[i] inside of a lambda function
21841// SgArrowExp <SgThisExp, SgVarRefExp>, both are compiler generated nodes
21842// class symbol of ThisExp 's declaration is AutonomousDeclaration SgClassDeclaration
21843// its parent is SgLambdaExp, and lambda_closure_class points back to this class declaration
21845{
21846 bool rt = false;
21847#ifdef _MSC_VER
21848 #pragma message ("WARNING: MSVC does not handle isLambdaCapturedVariable() properly.")
21849#else
21850 ROSE_ASSERT (varRef!= NULL);
21851 SgNode* parent = varRef->get_parent();
21852 if (SgArrowExp *p = isSgArrowExp(parent))
21853 {
21854 SgThisExp* te = isSgThisExp(p->get_lhs_operand_i());
21855 if (te != NULL)
21856 {
21857 SgClassSymbol* csym = te->get_class_symbol();
21858 ROSE_ASSERT (csym!= NULL);
21859 SgClassDeclaration* xdecl = isSgClassDeclaration(csym->get_declaration());
21860 // each this exp should have a class decl
21861 ROSE_ASSERT (xdecl != NULL);
21862 SgLambdaExp* le = isSgLambdaExp(xdecl->get_parent());
21863 if (le != NULL)
21864 {
21865 if (le->get_lambda_closure_class() == xdecl ) // the class is a lambda closure class
21866 rt = true;
21867 }
21868 }
21869 }
21870#endif
21871 return rt;
21872}
21873
21876//TODO consult AstInterface::IsVarRef() for more cases
21878{
21879 SgInitializedName* name = NULL;
21880 SgExpression* nameExp = NULL;
21881 ROSE_ASSERT(current != NULL);
21882
21883 if (isSgInitializedName(current))
21884 {
21885 name = isSgInitializedName(current);
21886 }
21887 else if (isSgPntrArrRefExp(current) != NULL)
21888 {
21889 bool suc=false;
21890 SgExpression* exp = isSgExpression(current);
21891 ROSE_ASSERT(exp != NULL);
21892 suc = SageInterface::isArrayReference(exp,&nameExp);
21893 ROSE_ASSERT(suc == true);
21894 // has to resolve this recursively
21895 return convertRefToInitializedName(nameExp, coarseGrain);
21896 }
21897 else if (isSgVarRefExp(current) != NULL)
21898 {
21899 if (coarseGrain)
21900 {
21901 // Outliner needs coarse grain mem objects to work. Always returning fine grain objects will cause problems.
21902 SgNode* parent = current->get_parent();
21903 if (isSgDotExp(parent))
21904 {
21905 if (isSgDotExp(parent)->get_rhs_operand() == current)
21906 return convertRefToInitializedName(parent, coarseGrain);
21907 }
21908 // avoid backtracking to parent if this is part of lambda function
21909 else if(isSgArrowExp(parent) && ! isLambdaCapturedVariable ( isSgVarRefExp(current) ) )
21910 {
21911 if (isSgArrowExp(parent)->get_rhs_operand() == current)
21912 return convertRefToInitializedName(parent, coarseGrain);
21913 }
21914 }
21915 name = isSgVarRefExp(current)->get_symbol()->get_declaration();
21916 }
21917 else if (isSgFunctionRefExp(current) != NULL ||
21918 isSgTemplateFunctionRefExp(current) != NULL ||
21919 isSgMemberFunctionRefExp(current) != NULL ||
21920 isSgTemplateMemberFunctionRefExp(current) != NULL)
21921 {
21922 //If a function is here it's probably related to a function pointer, it can't be converted to an SgInitailizedName
21923 return NULL;
21924 }
21925 else if (isSgNonrealRefExp(current) != NULL)
21926 {
21927 //SgNonrealRefExp is not a reasonable thing to convert to an SgInitializedName (I think) -Jim Leek
21928 return NULL;
21929 }
21930 else if (isSgDotExp(current))
21931 {
21932 SgExpression* child = NULL;
21933 if (coarseGrain)
21934 child= isSgDotExp(current)->get_lhs_operand();
21935 else
21936 child= isSgDotExp(current)->get_rhs_operand();
21937 ROSE_ASSERT(child);
21938 // has to resolve this recursively
21939 return convertRefToInitializedName(child, coarseGrain);
21940 }
21941 else if (isSgArrowExp(current))
21942 {
21943 SgExpression* child = NULL;
21944 if (coarseGrain)
21945 {
21946 SgExpression* lhs = isSgArrowExp(current)->get_lhs_operand();
21947 ROSE_ASSERT(lhs);
21948 // Liao 9/12/2016, special handling for variables inside of C++11 lambda functions
21949 // They capture variables outside of the lambda function.
21950 // They are represented as a class variable of an anonymous class, this->a[i]
21951 // So, we have to recognize this pattern, and pass the rhs variable to obtain initialized name.
21952 // has to resolve this recursively
21954
21955 if (isLambdaFunction (efunc) )
21956 child= isSgArrowExp(current)->get_rhs_operand();
21957 else
21958 child = lhs;
21959 }
21960 else
21961 child = isSgArrowExp(current)->get_rhs_operand();
21962 ROSE_ASSERT(child);
21963 // has to resolve this recursively
21964
21965 return convertRefToInitializedName(child, coarseGrain);
21966 } // The following expression types are usually introduced by left hand operands of DotExp, ArrowExp
21967 else if (isSgThisExp(current))
21968 {
21969 //SgThisExp* texp = isSgThisExp(current);
21970 name = NULL; // inside a class, there is no initialized name at all!! what to do??
21971 }
21972 else if (isSgPointerDerefExp(current))
21973 {
21974 return convertRefToInitializedName(isSgPointerDerefExp(current)->get_operand(), coarseGrain);
21975 }
21976 else if(isSgUnaryOp(current)) { //Written for SgAddressOfOp, but seems generally aplicable to all Unary Ops (replace above?) -JL
21977 return convertRefToInitializedName(isSgUnaryOp(current)->get_operand(), coarseGrain);
21978 }
21979 else if (isSgCastExp(current))
21980 {
21981 return convertRefToInitializedName(isSgCastExp(current)->get_operand(), coarseGrain);
21982 }
21983 // Scientific applications often use *(address + offset) to access array elements
21984 // If a pointer dereferencing is applied to AddOp, we assume the left operand is the variable of our interests
21985 else if (isSgAddOp(current))
21986 {
21987 SgExpression* lhs = isSgAddOp(current)->get_lhs_operand();
21988 return convertRefToInitializedName(lhs, coarseGrain);
21989 }
21990 else if (isSgSubtractOp(current))
21991 {
21992 SgExpression* lhs = isSgSubtractOp(current)->get_lhs_operand();
21993 return convertRefToInitializedName(lhs, coarseGrain);
21994 }
21995 // operator->() may be called upon a class object.
21996 // e.g. we need to get the function: it a SgDotExp node, (lhs is the class object, rhs is its member function)
21997 else if (SgFunctionCallExp * func_call = isSgFunctionCallExp(current))
21998 {
21999 return convertRefToInitializedName(func_call->get_function(), coarseGrain);
22000 }
22001 else if (isSgIntVal(current))
22002 {
22003 //It is very rare, but sometimes a constant is treated as a
22004 //variable. In which case we don't need an SgInitializdName
22005 return NULL;
22006 }
22007
22008 else
22009 {
22010 // side effect analysis will return rhs of Class A a = A(); as a read ref exp. SgConstructorInitializer
22011 if (!isSgConstructorInitializer(current))
22012 {
22013 mlog[Sawyer::Message::Common::WARN] <<
22014 "convertRefToInitializedName: " <<
22015 current->get_file_info()->get_filename() << ":" <<
22016 current->get_file_info()->get_line() << "-" << current->get_file_info()->get_col()<<endl;
22017 cerr<<"In SageInterface::convertRefToInitializedName(): unhandled reference type:"<<current->class_name()<<endl;
22018 ROSE_ABORT();
22019 }
22020 }
22021 //ROSE_ASSERT(name != NULL);
22022 return name;
22023}
22024
22027{
22028#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22029 printf ("AbstractHandle support is disabled for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT \n");
22030 ROSE_ABORT();
22031#else
22033
22034 // trim off the possible leading handle for project: "Project<numbering,1>::"
22035 size_t pos = input_string.find("SourceFile<");
22036 ROSE_ASSERT (pos != string::npos);
22037 string trimed_string = input_string.substr(pos);
22038 AbstractHandle::abstract_handle * handle = new AbstractHandle::abstract_handle(project_handle, trimed_string);
22039 if (handle)
22040 {
22041 if (handle->getNode()!=NULL)
22042 {
22043#ifdef _MSC_VER
22044 // DQ (11/28/2009): This is related to the use of covariant return types (I think).
22045 SgNode* result = NULL; // (SgNode*)(handle->getNode()->getNode());
22046#pragma message ("WARNING: covariant return type for get_node() not supported in MSVC.")
22047 printf ("ERROR: covariant return type for get_node() not supported in MSVC. \n");
22048 ROSE_ABORT();
22049#else
22050 SgNode* result = (SgNode*)(handle->getNode()->getNode());
22051#endif
22052 // deallocate memory, should not do this!!
22053 // May corrupt the internal std maps used in abstract handle namespace
22054 //delete handle->getNode();
22055 //delete handle;
22056 return result;
22057 }
22058 }
22059#endif
22060
22061 return NULL;
22062}
22063
22064
22066// unparseToString() is too strict for debugging purpose
22067// we provide this instead.
22068void SageInterface::dumpInfo(SgNode* node, std::string desc/*=""*/)
22069{
22070 ROSE_ASSERT(node != NULL);
22071 cout<<desc<<endl;
22072 // base information for all SgNode:
22073 cout<<"///////////// begin of SageInterface::dumpInfo() ///////////////"<<endl;
22074 cout<<"--------------base info. for SgNode---------------"<<endl;
22075 cout<<node<<" "<<node->class_name()<<endl;
22076 SgLocatedNode* snode = isSgLocatedNode(node);
22077 if (snode)
22078 {
22079 // source file info. dump
22080 cout<<"--------------source location info. for SgNode---------------"<<endl;
22081 cout<<snode->get_file_info()->get_filename()
22082 << ":"<<snode->get_file_info()->get_line()<<"-"
22083 << snode->get_file_info()->get_col()<<endl;
22084 // preprocessing info dump
22085 AttachedPreprocessingInfoType *comments = snode->getAttachedPreprocessingInfo ();
22086 if (comments)
22087 {
22088 cout<<"--------------preprocessing info. for SgNode---------------"<<endl;
22089 AttachedPreprocessingInfoType::iterator i;
22090 cout<<"Total attached preprocessingInfo count="<<comments->size()<<endl;
22091 for (i = comments->begin (); i != comments->end (); i++)
22092 {
22093 PreprocessingInfo * pinfo = *i;
22094 pinfo->display("");
22095 }
22096 }
22097 cout<<"--------------name info. for SgNode---------------"<<endl;
22098 // print out namea for named nodes
22099 SgFunctionDeclaration * decl = isSgFunctionDeclaration(snode);
22100 if (decl)
22101 cout<<"\tqualified name="<<decl->get_qualified_name().getString()<<endl;
22102 SgVarRefExp * varRef = isSgVarRefExp(snode);
22103 if (varRef)
22104 cout<<"\treferenced variable name= "<<varRef->get_symbol()->get_name().getString()<<endl;
22105 }
22106 SgInitializedName * iname = isSgInitializedName(snode);
22107 if (iname)
22108 cout<<"\tvariable name= "<<iname->get_qualified_name().getString()<<endl;
22109
22110 cout<<endl;
22111 cout<<"///////////// end of SageInterface::dumpInfo() ///////////////"<<endl;
22112}
22113
22119bool
22120SageInterface::collectReadWriteRefs(SgStatement* stmt, std::vector<SgNode*>& readRefs, std::vector<SgNode*>& writeRefs, bool useCachedDefUse)
22121{ // The type cannot be SgExpression since variable declarations have SgInitializedName as the reference, not SgVarRefExp.
22122 bool retVal = true;
22123
22124 ROSE_ASSERT(stmt !=NULL);
22125
22126#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22127 // We should allow accumulate the effects for multiple statements
22128 // ROSE_ASSERT(readRefs.size() == 0);
22129 // ROSE_ASSERT(writeRefs.size() == 0);
22130
22131 // convert a request for a defining function declaration to its function body
22132 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(stmt);
22133 if (funcDecl != NULL)
22134 {
22135 funcDecl= isSgFunctionDeclaration(funcDecl->get_definingDeclaration ());
22136 if (funcDecl == NULL)
22137 {
22138 cerr<<"In collectReadWriteRefs(): cannot proceed without a function body!"<<endl;
22139 }
22140 else
22141 stmt = funcDecl->get_definition()->get_body();
22142 }
22143
22144 // get function level information
22145 SgFunctionDefinition* funcDef = isSgFunctionDefinition(stmt);
22146 if (!funcDef)
22148
22149 ROSE_ASSERT(funcDef != NULL);
22150 SgBasicBlock* funcBody = funcDef->get_body();
22151 ROSE_ASSERT(funcBody!= NULL);
22152
22153 // prepare Loop transformation environment
22154 AstInterfaceImpl faImpl(funcBody);
22155 AstInterface fa(&faImpl);
22156 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
22157 if( useCachedDefUse ){
22158 ArrayInterface* array_interface = ArrayInterface::get_inst(*annot, fa, funcDef, AstNodePtrImpl(funcDef));
22159 LoopTransformInterface::set_arrayInfo(array_interface);
22160 } else {
22161 ArrayInterface array_interface(*annot);
22162 // Alias analysis and value propagation are called in initialize(). Turn both off for now.
22163// array_interface.initialize(fa, AstNodePtrImpl(funcDef));
22164 array_interface.observe(fa);
22165 LoopTransformInterface::set_arrayInfo(&array_interface);
22166 }
22167 LoopTransformInterface::set_astInterface(fa);
22168 // Liao, 3/27/2015. connect to annotations for function side effect
22169 LoopTransformInterface::set_sideEffectInfo(annot);
22170
22171 // variables to store results
22172 DoublyLinkedListWrap<AstNodePtr> rRef1, wRef1;
22173 CollectDoublyLinkedList<AstNodePtr> crRef1(rRef1),cwRef1(wRef1);
22174 AstNodePtr s1 = AstNodePtrImpl(stmt);
22175
22176 // Actual side effect analysis
22177 if (!AnalyzeStmtRefs(fa, s1, cwRef1, crRef1))
22178 {
22179 //False returned here just means that the function called a
22180 //function that was not annotated with Qing's RWset annotation
22181 //method. This doesn't matter for my tool. -Jim Leek 03/21/2023
22182 mlog[Sawyer::Message::Common::DEBUG] << "Function: " << funcDef->get_declaration()->get_qualified_name() << " calls at least one function that has not been annotated." << endl;
22183 retVal = false;
22184 }
22185
22186 // transfer results into STL containers.
22187 for (DoublyLinkedEntryWrap<AstNodePtr>* p = rRef1.First(); p != 0; )
22188 {
22189 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22190 p = rRef1.Next(p);
22191 AstNodePtr cur = p1->GetEntry();
22192 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22193 ROSE_ASSERT(sgRef != NULL);
22194 readRefs.push_back(sgRef);
22195 //cout<<"read reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22196 // " sage type:"<< sgRef->class_name()<< endl;
22197 }
22198
22199 for (DoublyLinkedEntryWrap<AstNodePtr>* p = wRef1.First(); p != 0; )
22200 {
22201 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22202 p = wRef1.Next(p);
22203 AstNodePtr cur = p1->GetEntry();
22204 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22205 ROSE_ASSERT(sgRef != NULL);
22206 writeRefs.push_back(sgRef);
22207 // cout<<"write reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22208 // " sage type:"<< sgRef->class_name()<< endl;
22209 }
22210
22211#endif
22212
22213 return retVal;
22214}
22215#if 0
22216// The side effect analysis will report three references for a statement like this->x = ...
22217// 1.SgThisExp 2. SgArrowExp 3. SgVarRefExp
22218// We only need to keep SgVarRefExp and skip the other two.
22219static bool skipSomeRefs(SgNode* n)
22220{
22221 ROSE_ASSERT (n);
22222 return (isSgThisExp(n)||isSgArrowExp(n)||isSgDotExp(n));
22223}
22224#endif
22226bool SageInterface::collectReadWriteVariables(SgStatement* stmt, set<SgInitializedName*>& readVars, set<SgInitializedName*>& writeVars, bool coarseGrain/*=true*/)
22227{
22228 ROSE_ASSERT(stmt != NULL);
22229 vector <SgNode* > readRefs, writeRefs;
22230
22231 bool retVal = collectReadWriteRefs(stmt, readRefs, writeRefs);
22232 // process read references
22233 vector<SgNode*>::iterator iter = readRefs.begin();
22234 for (; iter!=readRefs.end();iter++)
22235 {
22236 SgNode* current = *iter;
22237 //if (skipSomeRefs(current)) continue;
22238
22239 ROSE_ASSERT (current != NULL);
22240 SgInitializedName* name= convertRefToInitializedName(current, coarseGrain);
22241 //ROSE_ASSERT (name); // this pointer will return NULL
22242 if (!name) continue;
22243 // Only insert unique ones
22244 // We use std::set to ensure uniqueness now
22245 readVars.insert(name);
22246 }
22247 // process write references
22248 vector<SgNode*>::iterator iterw = writeRefs.begin();
22249 for (; iterw!=writeRefs.end();iterw++)
22250 {
22251 SgNode* current = *iterw;
22252 ROSE_ASSERT (current != NULL);
22253 SgInitializedName* name = convertRefToInitializedName(current, coarseGrain);
22254 if (!name) continue;
22255 //ROSE_ASSERT (name); // this pointer will return NULL
22256 // Only insert unique ones
22257 // We use std::set to ensure uniqueness now
22258 writeVars.insert(name);
22259 }
22260 return retVal;
22261}
22262
22264void SageInterface::collectReadOnlyVariables(SgStatement* stmt, std::set<SgInitializedName*>& readOnlyVars, bool coarseGrain/*=true*/)
22265{
22266 ROSE_ASSERT(stmt != NULL);
22267 set<SgInitializedName*> readVars, writeVars;
22268 // Only collect read only variables if collectReadWriteVariables() succeeded.
22269 if (collectReadWriteVariables(stmt, readVars, writeVars, coarseGrain))
22270 {
22271 // read only = read - write
22272 set_difference(readVars.begin(), readVars.end(),
22273 writeVars.begin(), writeVars.end(),
22274 std::inserter(readOnlyVars, readOnlyVars.begin()));
22275 }
22276 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
22277 {
22278 RoseAst ast(stmt);
22279
22280 for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
22281 if (SgVarRefExp* v_ref = isSgVarRefExp(*i))
22282 {
22283 if (isConstType(v_ref->get_type()))
22284 readOnlyVars.insert (v_ref->get_symbol()->get_declaration());
22285 }
22286 } // end for
22287 } // end else
22288}
22289
22290
22292void SageInterface::collectReadOnlySymbols(SgStatement* stmt, std::set<SgVariableSymbol*>& readOnlySymbols, bool coarseGrain/*=true*/)
22293{
22294 set<SgInitializedName*> temp;
22295 collectReadOnlyVariables(stmt, temp, coarseGrain);
22296
22297 for (set<SgInitializedName*>::const_iterator iter = temp.begin();
22298 iter!=temp.end(); iter++)
22299 {
22300 SgSymbol* symbol = (*iter)->get_symbol_from_symbol_table () ;
22301 ROSE_ASSERT(symbol != NULL );
22302 ROSE_ASSERT(isSgVariableSymbol(symbol));
22303 readOnlySymbols.insert(isSgVariableSymbol(symbol));
22304 }
22305
22306}
22307
22310{
22311 bool result = false;
22312 ROSE_ASSERT(ref != NULL);
22313 ROSE_ASSERT(ref->get_parent() != NULL);
22314 // case 1: ref is used as an operator for & (SgAddressofOp)
22315 // TODO tolerate possible type casting operations in between ?
22316 if (isSgAddressOfOp(ref->get_parent()))
22317 {
22318 result = true;
22319 }
22320 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22321 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22322 {
22323 SgNode* grandparent = ref->get_parent()->get_parent();
22324 ROSE_ASSERT(grandparent);
22325 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22326 {
22327 // find which parameter ref is in SgExpressionPtrList
22328
22329 // DQ (8/12/2020): This is a compiler warning where it is used below in comparision between signed and unsigned types.
22330 // int param_index = 0;
22331 size_t param_index = 0;
22332
22333 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22334 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22335 for (; iter!=expList.end(); iter++)
22336 {
22337 if (*iter == ref)
22338 break;
22339 else
22340 param_index++;
22341 }
22342 // find the parameter type of the corresponding function declaration
22343 SgExpression* func_exp = isSgFunctionCallExp(grandparent)->get_function();
22344 ROSE_ASSERT (func_exp);
22345 SgFunctionRefExp * funcRef = isSgFunctionRefExp(func_exp);
22346 if (funcRef) // regular functions
22347 {
22348 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22349 SgInitializedNamePtrList nameList = funcDecl->get_args();
22350 //TODO tolerate typedef chains
22351 // printf() has only two arguments to express variable arguments.
22352 // The third argument index ==2 will be out of bounds for nameList[index]
22353 // So we must check the bound first.
22354 if (param_index >= nameList.size() ||isSgTypeEllipse(nameList[param_index]->get_type()) )
22355 {
22356 if (isSgReferenceType(ref))
22357 result = true;
22358 }
22359 else // now within the bound: two situations,
22360 if (isSgReferenceType(nameList[param_index]->get_type()))
22361 {
22362 result = true;
22363 }
22364 } //It also could be a dot or arrow expression where its right hand operand is a SgMemberFunctionRefExp
22365 else if (isSgDotExp (func_exp) || isSgArrowExp(func_exp)) // ArrowExp TODO
22366 {
22367 SgBinaryOp* binOp = isSgBinaryOp(func_exp);
22368 ROSE_ASSERT (binOp);
22369 SgMemberFunctionRefExp* mfuncRef = isSgMemberFunctionRefExp(binOp->get_rhs_operand_i());
22370 ROSE_ASSERT (mfuncRef);
22371 SgMemberFunctionDeclaration * mfuncDecl = isSgMemberFunctionSymbol (mfuncRef->get_symbol())->get_declaration();
22372 ROSE_ASSERT (mfuncDecl);
22373 SgInitializedNamePtrList nameList = mfuncDecl->get_args();
22374 //TODO tolerate typedef chains
22375 if (isSgReferenceType(nameList[param_index]->get_type()))
22376 {
22377 result = true;
22378 }
22379 }
22380
22381 }
22382 }
22383 return result;
22384}
22385
22386
22388void SageInterface::collectUseByAddressVariableRefs (const SgStatement* s, std::set<SgVarRefExp* >& varSetB)
22389{
22390 Rose_STL_Container <SgNode*> var_refs = NodeQuery::querySubTree (const_cast<SgStatement *> (s), V_SgVarRefExp);
22391
22392 Rose_STL_Container<SgNode*>::iterator iter = var_refs.begin();
22393 for (; iter!=var_refs.end(); iter++)
22394 {
22395 SgVarRefExp* ref = isSgVarRefExp(*iter);
22396 ROSE_ASSERT(ref != NULL);
22397 ROSE_ASSERT(ref->get_parent() != NULL);
22398#if 0
22399 // case 1: ref is used as an operator for & (SgAddressofOp)
22400 // TODO tolerate possible type casting operations in between ?
22401 if (isSgAddressOfOp(ref->get_parent()))
22402 {
22403 varSetB.insert(ref);
22404 }
22405 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22406 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22407 {
22408 SgNode* grandparent = ref->get_parent()->get_parent();
22409 ROSE_ASSERT(grandparent);
22410 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22411 {
22412 // find which parameter ref is in SgExpressionPtrList
22413 int param_index =0;
22414 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22415 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22416 for (; iter!=expList.end(); iter++)
22417 {
22418 if (*iter == ref)
22419 break;
22420 else
22421 param_index++;
22422 }
22423 // find the parameter type of the corresponding function declaration
22424 SgFunctionRefExp * funcRef = isSgFunctionRefExp(isSgFunctionCallExp(grandparent)->get_function());
22425 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22426 SgInitializedNamePtrList nameList = funcDecl->get_args();
22427 //TODO tolerate typedef chains
22428 if (isSgReferenceType(nameList[param_index]->get_type()))
22429 {
22430 varSetB.insert(ref);
22431 }
22432 }
22433 }
22434#endif
22436 varSetB.insert(ref);
22437 }
22438}
22439
22440#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22442LivenessAnalysis * SageInterface::call_liveness_analysis(SgProject* project, bool debug/*=false*/)
22443{
22444 // We expect this function to be called multiple times but always return the result generated from the first execution.
22445 static LivenessAnalysis* liv = NULL; // one instance
22446 if (liv!=NULL)
22447 return liv;
22448
22449 static DFAnalysis * defuse = NULL; // only one instance
22450 // Prepare def-use analysis
22451 if (defuse==NULL)
22452 {
22453 ROSE_ASSERT(project != NULL);
22454 defuse = new DefUseAnalysis(project);
22455 }
22456
22457 ROSE_ASSERT(defuse != NULL);
22458 defuse->run(debug);
22459
22460 if (debug)
22461 defuse->dfaToDOT();
22462
22463 //Prepare variable liveness analysis
22464 liv = new LivenessAnalysis(debug,(DefUseAnalysis*)defuse);
22465 ROSE_ASSERT(liv != NULL);
22466
22467 std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions;
22468 NodeQuerySynthesizedAttributeType vars =
22469 NodeQuery::querySubTree(project, V_SgFunctionDefinition);
22470 NodeQuerySynthesizedAttributeType::const_iterator i;
22471 bool abortme=false;
22472 // run liveness analysis on each function body
22473 for (i= vars.begin(); i!=vars.end();++i)
22474 {
22475 SgFunctionDefinition* func = isSgFunctionDefinition(*i);
22476 ROSE_ASSERT(func != NULL);
22477 if (debug)
22478 {
22479 std::string name = func->class_name();
22480 string funcName = func->get_declaration()->get_qualified_name().str();
22481 cout<< " .. running liveness analysis for function: " << funcName << endl;
22482 }
22483 FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
22484 // propagate results to statement level
22485 liv->fixupStatementsINOUT(func);
22486 if (rem_source.getNode()!=NULL)
22487 dfaFunctions.push_back(rem_source);
22488 if (abortme)
22489 break;
22490 } // end for ()
22491 if(debug)
22492 {
22493 cout << "Writing out liveness analysis results into var.dot... " << endl;
22494 std::ofstream f2("var.dot");
22495 dfaToDot(f2, string("var"), dfaFunctions, (DefUseAnalysis*)defuse, liv);
22496 f2.close();
22497 }
22498 if (abortme) {
22499 cerr<<"Error: Liveness analysis is ABORTING ." << endl;
22500 ROSE_ABORT();
22501 }
22502 return liv;
22503 //return !abortme;
22504}
22505#endif
22506
22507#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22509void SageInterface::getLiveVariables(LivenessAnalysis * liv, SgForStatement* loop, std::set<SgInitializedName*>& liveIns, std::set<SgInitializedName*> & liveOuts)
22510{
22511 ROSE_ASSERT(liv != NULL);
22512 ROSE_ASSERT(loop != NULL);
22513 SgForStatement *forstmt = loop;
22514 std::vector<SgInitializedName*> liveIns0, liveOuts0; // store the original one
22515
22516 // Jeremiah's hidden constructor parameter value '2' to grab the node for forStmt's
22517 // Several CFG nodes are used for the same SgForStatement, only one of the is needed.
22518 // We have to check the full control flow graph to find all SgForStatement's nodes,
22519 // check the index numbers from 0 , find the one with two out edges (true, false)
22520 // The CFG node should have a caption like" <SgForStatement> @ 8: 1",
22521 // which means this is a CFG node for a for statement at source line 8, with an index 1.
22522 // For SgForStatement, there are 5 cfg nodes, 0 and 4 are for begin and end CFG nodes
22523 // 1: after init statement, 2: after test expression (the remaining one after filtering), 3: before increment
22524 CFGNode cfgnode(forstmt,2);
22525 FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (cfgnode);
22526 // This one does not return the one we want even its getNode returns the
22527 // right for statement
22528 //FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (forstmt->cfgForBeginning());
22529 ROSE_ASSERT(filternode.getNode()==forstmt);
22530
22531 // Check out edges
22532 vector<FilteredCFGEdge < IsDFAFilter > > out_edges = filternode.outEdges();
22533 ROSE_ASSERT(out_edges.size()==2);
22534 vector<FilteredCFGEdge < IsDFAFilter > >::iterator iter= out_edges.begin();
22535
22536 for (; iter!=out_edges.end();iter++)
22537 {
22538 FilteredCFGEdge < IsDFAFilter > edge= *iter;
22539 //SgForStatement should have two outgoing edges based on the loop condition
22540 // one true(going into the loop body) and one false (going out the loop)
22541 //x. Live-in (loop) = live-in (first-stmt-in-loop)
22542 if (edge.condition()==eckTrue)
22543 {
22544 SgNode* firstnode= edge.target().getNode();
22545 liveIns0 = liv->getIn(firstnode);
22546 // cout<<"Live-in variables for loop:"<<endl;
22547 for (std::vector<SgInitializedName*>::iterator iter = liveIns0.begin();
22548 iter!=liveIns0.end(); iter++)
22549 {
22550 // SgInitializedName* name = *iter;
22551 liveIns.insert(*iter);
22552 // cout<< name->get_qualified_name().getString()<<endl;
22553 }
22554 }
22555 //x. live-out(loop) = live-in (first-stmt-after-loop)
22556 else if (edge.condition()==eckFalse)
22557 {
22558 SgNode* firstnode= edge.target().getNode();
22559 liveOuts0 = liv->getIn(firstnode);
22560 // cout<<"Live-out variables for loop:"<<endl;
22561 for (std::vector<SgInitializedName*>::iterator iter = liveOuts0.begin();
22562 iter!=liveOuts0.end(); iter++)
22563 {
22564 // SgInitializedName* name = *iter;
22565 // cout<< name->get_qualified_name().getString()<<endl;
22566 liveOuts.insert(*iter);
22567 }
22568 }
22569 else
22570 {
22571 cerr<<"Unexpected CFG out edge type for SgForStmt!"<<endl;
22572 ROSE_ABORT();
22573 }
22574 } // end for (edges)
22575
22576}
22577#endif
22578
22579//Check if two references form an idiom like: x= x op expr, x = expr op x (except for subtraction)
22580static bool isAssignReduction (SgVarRefExp* ref_exp1, SgVarRefExp* ref_exp2, OmpSupport::omp_construct_enum& optype)
22581{
22582 bool isReduction = false;
22583 // Sanity check
22584 ROSE_ASSERT (ref_exp1!= NULL);
22585 ROSE_ASSERT (ref_exp2!= NULL);
22586 ROSE_ASSERT (ref_exp1-> get_symbol() == ref_exp2-> get_symbol());
22587 // must be scalar type
22588 ROSE_ASSERT (SageInterface::isScalarType(ref_exp1-> get_symbol()->get_type() ) );
22589
22592 if (stmt != stmt2) return false; // early return false;
22593
22594 // must be assignment statement using
22595 // x= x op expr, x = expr op x (except for subtraction)
22596 // one reference on left hand, the other on the right hand of assignment expression
22597 // the right hand uses associative operators +, *, -, &, ^ ,|, &&, ||
22598 SgExprStatement* exp_stmt = isSgExprStatement(stmt);
22599 if (exp_stmt && isSgAssignOp(exp_stmt->get_expression()))
22600 {
22601 SgExpression* assign_lhs=NULL, * assign_rhs =NULL;
22602 assign_lhs = isSgAssignOp(exp_stmt->get_expression())->get_lhs_operand();
22603 assign_rhs = isSgAssignOp(exp_stmt->get_expression())->get_rhs_operand();
22604 ROSE_ASSERT(assign_lhs && assign_rhs);
22605 // x must show up in both lhs and rhs in any order:
22606 // e.g.: ref1 = ref2 op exp or ref2 = ref1 op exp
22607 if (((assign_lhs==ref_exp1)&&SageInterface::isAncestor(assign_rhs,ref_exp2))
22608 ||((assign_lhs==ref_exp2)&&SageInterface::isAncestor(assign_rhs,ref_exp1)))
22609 {
22610 // assignment's rhs must match the associative binary operations
22611 // +, *, -, &, ^ ,|, &&, ||
22612 SgBinaryOp * binop = isSgBinaryOp(assign_rhs);
22613 if (binop!=NULL){
22614 SgExpression* op_lhs = binop->get_lhs_operand();
22615 SgExpression* op_rhs = binop->get_rhs_operand();
22616
22617 // double check that the binary expression has either ref1 or ref2 as one operand
22618 if( !((op_lhs==ref_exp1)||(op_lhs==ref_exp2))
22619 && !((op_rhs==ref_exp1)||(op_rhs==ref_exp2)))
22620 return false; // early return false;
22621
22622 bool isOnLeft = false; // true if it has form (refx op exp), instead (exp or refx)
22623 if ((op_lhs==ref_exp1)|| // TODO might have in between !!
22624 (op_lhs==ref_exp2))
22625 isOnLeft = true;
22626 switch (binop->variantT())
22627 {
22628 case V_SgAddOp:
22629 {
22630 optype = OmpSupport::e_reduction_plus;
22631 isReduction = true;
22632 break;
22633 }
22634 case V_SgMultiplyOp:
22635 {
22636 optype = OmpSupport::e_reduction_mul;
22637 isReduction = true;
22638 break;
22639 }
22640 case V_SgSubtractOp: // special handle here!!
22641 {
22642 optype = OmpSupport::e_reduction_minus;
22643 if (isOnLeft) // cannot allow (exp - x)a
22644 {
22645 isReduction = true;
22646 }
22647 break;
22648 }
22649 case V_SgBitAndOp:
22650 {
22651 optype = OmpSupport::e_reduction_bitand ;
22652 isReduction = true;
22653 break;
22654 }
22655 case V_SgBitXorOp:
22656 {
22657 optype = OmpSupport::e_reduction_bitxor;
22658 isReduction = true;
22659 break;
22660 }
22661 case V_SgBitOrOp:
22662 {
22663 optype = OmpSupport::e_reduction_bitor;
22664 isReduction = true;
22665 break;
22666 }
22667 case V_SgAndOp:
22668 {
22669 optype = OmpSupport::e_reduction_logand;
22670 isReduction = true;
22671 break;
22672 }
22673 case V_SgOrOp:
22674 {
22675 optype = OmpSupport::e_reduction_logor;
22676 isReduction = true;
22677 break;
22678 }
22679 default:
22680 break;
22681 }
22682 } // end matching associative operations
22683 }
22684 } // end if assignop
22685 return isReduction;
22686}
22687// A helper function for reduction recognition
22688// check if two references to the same variable form a reduction idiom using if-statement
22689// example 1: if (array[i]> maxV) maxV = array[i]
22690// example 2: if (array[i]< minV) minV = array[i]
22691// If it matches, return true and the reduction operator type
22692static bool isIfReduction(SgVarRefExp* ref1, SgVarRefExp* ref2, OmpSupport::omp_construct_enum& optype)
22693{
22694 bool matchStmt1 = false;
22695 bool matchStmt2 = false;
22696
22697 //TODO: ensure ref1, ref2 are ordered as pre-order manner in AST
22698 // SgExpression* reduction_var_ref = NULL;
22699 // SgExpression* source_var_ref = NULL; //array[i] is the source var ref
22700
22701 // Sanity check
22702 ROSE_ASSERT (ref1 != NULL);
22703 ROSE_ASSERT (ref2 != NULL);
22704 ROSE_ASSERT (ref1-> get_symbol() == ref2-> get_symbol());
22705 // must be scalar type
22706 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22707
22710
22711 //early return if the same stmt
22712 if (stmt1 == stmt2) return false;
22713
22714 // check stmt2 first. It is easier.
22715 // stmt2 should be an assignment stmt like:
22716 // reduction_variable = else;
22717 // minV = array[i];
22718 SgExpression* lhs2 = NULL;
22719 SgExpression* rhs2 = NULL;
22720 if (SageInterface::isAssignmentStatement (stmt2, &lhs2, &rhs2 ))
22721 {
22722 // lhs2 must be ref2
22723 if (lhs2 == ref2 )
22724 {
22725 matchStmt2 = true;
22726 // reduction_var_ref = lhs2;
22727 // source_var_ref= rhs2;
22728 }
22729 } // end assignment stmt
22730
22731 // stmt1 should be a if-stmt's conditional expression stmt
22732 // and its body should be stmt2
22733 if (SgExprStatement* if_cond_stmt = isSgExprStatement(stmt1))
22734 {
22735 bool matchBody = false;
22736 bool matchCondition= false;
22737 if (SgIfStmt * if_stmt = isSgIfStmt (if_cond_stmt->get_parent()) )
22738 {
22739 if (SgStatement* body = if_stmt->get_true_body())
22740 {
22741 if (SgBasicBlock* block = isSgBasicBlock (body))
22742 {
22743 // stmt2 must be the only child of the if true body
22744 ROSE_ASSERT(stmt2 != NULL);
22745 if ( ((block->get_statements()).size() == 1) && stmt2->get_scope() == block )
22746 matchBody = true;
22747 }
22748 else
22749 {
22750 if (body == stmt2)
22751 matchBody = true;
22752 }
22753 } // body match test
22754
22755 // match condition SgExprStatement ref1 SgLessThanOp source_var
22756 if (SgExprStatement* cond_exp_stmt = isSgExprStatement (if_stmt->get_conditional()) )
22757 {
22758 SgExpression* cond_exp = cond_exp_stmt->get_expression();
22759 if (SgBinaryOp * binop = isSgBinaryOp (cond_exp))
22760 {
22761 if (ref1 == binop->get_lhs_operand_i())
22762 {
22763 // minV > array[i] ;
22764 if (isSgLessThanOp (binop))
22765 {
22766 optype = OmpSupport::e_reduction_max;
22767 matchCondition= true;
22768 }
22769 else if (isSgGreaterThanOp(binop))
22770 {
22771 optype = OmpSupport::e_reduction_min;
22772 matchCondition= true;
22773 }
22774 }
22775 else if ( ref1 == binop->get_rhs_operand_i() )
22776 {
22777 // array[i] < minV
22778 if (isSgLessThanOp (binop))
22779 {
22780 optype = OmpSupport::e_reduction_min;
22781 matchCondition= true;
22782 }
22783 else if (isSgGreaterThanOp(binop))
22784 {
22785 optype = OmpSupport::e_reduction_max;
22786 matchCondition= true;
22787 }
22788 }
22789 } // end if binary op
22790 // TODO the source_var should match the source_var from stmt2
22791 }
22792 }
22793 matchStmt1 = matchBody && matchCondition;
22794 } // end if-stmt
22795
22796
22797 return (matchStmt2 && matchStmt1);
22798}
22799
22800// check if a var ref is a form of
22801// --x, x--, ++x, x++
22802// x+= .., x-= ..., etc.
22803// The reduction variable appears only once in the reduction idiom.
22804static bool isSingleAppearanceReduction(SgVarRefExp* ref1, OmpSupport::omp_construct_enum& optype )
22805{
22806 bool isReduction = false;
22807
22808 ROSE_ASSERT (ref1 != NULL);
22809 // must be scalar type
22810 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22811
22813
22814 if (isSgExprStatement(stmt))
22815 {
22816 SgExpression* exp = isSgExprStatement(stmt)->get_expression();
22817 SgExpression* binop = isSgBinaryOp(exp);
22818 if (isSgPlusPlusOp(exp)) // x++ or ++x
22819 { // Could have multiple reduction clause with different operators!!
22820 // So the variable list is associated with each kind of operator
22821 optype = OmpSupport::e_reduction_plus;
22822 isReduction = true;
22823 }
22824 else if (isSgMinusMinusOp(exp)) // x-- or --x
22825 {
22826 optype = OmpSupport::e_reduction_minus;
22827 isReduction = true;
22828 }
22829 else
22830 // x binop= expr where binop is one of + * - & ^ |
22831 // x must be on the left hand side
22832 if (binop!=NULL) {
22833 SgExpression* lhs= isSgBinaryOp(exp)->get_lhs_operand ();
22834 if (lhs==ref1)
22835 {
22836 switch (exp->variantT())
22837 {
22838 case V_SgPlusAssignOp:
22839 {
22840 optype = OmpSupport::e_reduction_plus;
22841 isReduction = true;
22842 break;
22843 }
22844 case V_SgMultAssignOp:
22845 {
22846 optype = OmpSupport::e_reduction_mul;
22847 isReduction = true;
22848 break;
22849 }
22850 case V_SgMinusAssignOp:
22851 {
22852 optype = OmpSupport::e_reduction_minus;
22853 isReduction = true;
22854 break;
22855 }
22856 case V_SgAndAssignOp:
22857 {
22858 optype = OmpSupport::e_reduction_bitand;
22859 isReduction = true;
22860 break;
22861 }
22862 case V_SgXorAssignOp:
22863 {
22864 optype = OmpSupport::e_reduction_bitxor;
22865 isReduction = true;
22866 break;
22867 }
22868 case V_SgIorAssignOp:
22869 {
22870 optype = OmpSupport::e_reduction_bitor;
22871 isReduction = true;
22872 break;
22873 }
22874 default:
22875 break;
22876 } // end
22877 }// end if on left side
22878 }
22879 }
22880 return isReduction;
22881}
22882
22884/* This code is refactored from project/autoParallelization/autoParSupport.C
22885 std::vector<SgInitializedName*>
22886 RecognizeReduction(SgNode *loop, OmpSupport::OmpAttribute* attribute, std::vector<SgInitializedName*>& candidateVars/)
22887 * Algorithms:
22888 * for each scalar candidate which are both live-in and live-out for the loop body
22889 * (We don't use liveness analysis here for simplicity)
22890 * and which is not the loop invariant variable (loop index).
22891 * Consider those with only 1 or 2 references
22892 * 1 reference
22893 * the operation is one of x++, ++x, x--, --x, x binop= expr
22894 * 2 references belonging to the same operation
22895 * operations: one of x= x op expr, x = expr op x (except for subtraction)
22896 * The reduction description from the OpenMP 3.0 specification.
22897 * x is not referenced in exp
22898 * expr has scalar type (no array, objects etc)
22899 * x: scalar only, aggregate types (including arrays), pointer types and reference types may not appear in a reduction clause.
22900 * op is not an overloaded operator, but +, *, -, &, ^ ,|, &&, ||
22901 * binop is not an overloaded operator, but: +, *, -, &, ^ ,|
22902 */
22903void SageInterface::ReductionRecognition(SgForStatement* loop, std::set< std::pair <SgInitializedName*, OmpSupport::omp_construct_enum > > & results)
22904{
22905 //x. Collect variable references of scalar types as candidates, excluding loop index
22906 SgInitializedName* loopindex;
22907 if (!(isCanonicalForLoop(loop, &loopindex)))
22908 {
22909// cerr<<"Skip reduction recognition for non-canonical for loop"<<endl;
22910 return;
22911 }
22912 std::set<SgInitializedName*> candidateVars; // scalar variables used within the loop
22913 //Store the references for each scalar variable
22914 std::map <SgInitializedName*, vector<SgVarRefExp* > > var_references;
22915
22916 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(loop, V_SgVarRefExp);
22917 SgStatement* lbody= loop->get_loop_body();
22918 ROSE_ASSERT(lbody != NULL);
22919 Rose_STL_Container<SgNode*>::iterator iter = reflist.begin();
22920 for (; iter!=reflist.end(); iter++)
22921 {
22922 SgVarRefExp* ref_exp = isSgVarRefExp(*iter);
22923 SgInitializedName* initname= ref_exp->get_symbol()->get_declaration();
22924 // candidates are of scalar types and are not the loop index variable
22925 // And also should be live-in:
22926 // not declared locally (var_scope equal or lower than loop body )
22927 // or redefined (captured by ref count)
22928 SgScopeStatement* var_scope = initname->get_scope();
22929 ROSE_ASSERT(var_scope != NULL);
22930 if ((isScalarType(initname->get_type())) &&(initname !=loopindex)
22931 && !(SageInterface::isAncestor(lbody, var_scope)||(lbody==var_scope)))
22932 {
22933 candidateVars.insert(initname);
22934 var_references[initname].push_back(ref_exp);
22935 }
22936 }
22937
22938 //Consider variables referenced at most twice
22939 std::set<SgInitializedName*>::iterator niter=candidateVars.begin();
22940 for (; niter!=candidateVars.end(); niter++)
22941 {
22942 SgInitializedName* initname = *niter;
22943 bool isReduction = false;
22944 OmpSupport::omp_construct_enum optype;
22945 // referenced once only
22946 if (var_references[initname].size()==1)
22947 {
22948 mlog[Sawyer::Message::Common::DEBUG] << "Debug: SageInterface::ReductionRecognition() A candidate used once:"<<initname->get_name().getString()<<endl;
22949 SgVarRefExp* ref_exp = *(var_references[initname].begin());
22950 if (isSingleAppearanceReduction (ref_exp, optype))
22951 isReduction = true;
22952 }
22953 // referenced twice within a same statement
22954 else if (var_references[initname].size()==2)
22955 {
22956 mlog[Sawyer::Message::Common::DEBUG] << "Debug: A candidate used twice:"<<initname->get_name().getString()<<endl;
22957 SgVarRefExp* ref_exp1 = *(var_references[initname].begin());
22958 SgVarRefExp* ref_exp2 = *(++var_references[initname].begin());
22959 // TODO: recognize maxV = array[i]>maxV? array[i]:maxV // this can be normalized to if () stmt
22960 // TODO: recognize maxV = max (maxV, array[i])
22961 if (isAssignReduction (ref_exp1, ref_exp2, optype) || isIfReduction (ref_exp1, ref_exp2, optype) )
22962 {
22963 isReduction = true;
22964 }
22965
22966 }// end referenced twice
22967
22968 if (isReduction)
22969 results.insert(make_pair(initname,optype));
22970 }// end for ()
22971}
22972
22975{
22976 ROSE_ASSERT(r!=NULL);
22977#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22978 ConstantFolding::constantFoldingOptimization(r,false);
22979#endif
22980}
22981
22984{
22986 {
22987 public:
22988 virtual void visit (SgNode * n)
22989 {
22990 SgExpression* exp = isSgExpression(n);
22991 if (exp)
22992 {
22993 string u_name = generateUniqueName(exp,false)+"-"+exp->class_name();
22994 AstAttribute * name_attribute = new UniqueNameAttribute(u_name);
22995 ROSE_ASSERT (name_attribute != NULL);
22996 exp->addNewAttribute("UniqueNameAttribute",name_attribute);
22997 }
22998 }
22999 };
23000 visitorTraversal exampleTraversal;
23001 //Sriram FIX: should traverse using the traverse function
23002 // exampleTraversal.traverseInputFiles(project,preorder);
23003 exampleTraversal.traverse(project, preorder);
23004}
23005
23006
23007 //
23008 // wrap free-standing function body in another function
23009
23011 {
23012 ROSE_ASSERT(vardecl.get_variables().size());
23013
23014 return *vardecl.get_variables().front();
23015 }
23016
23017#if 0
23018 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23019 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23020
23028 static
23030 cloneParameterList(const SgFunctionParameterList& params, SgFunctionDefinition* fundef = NULL)
23031 {
23032 namespace SB = SageBuilder;
23033
23034 SgFunctionParameterList& copy = *SB::buildFunctionParameterList();
23035 const SgInitializedNamePtrList& orig_decls = params.get_args();
23036
23037 std::transform( orig_decls.begin(), orig_decls.end(), sg::sage_inserter(copy), sg::InitNameCloner(copy, fundef) );
23038
23039 return copy;
23040 }
23041#endif
23042
23043#if 0
23044 // DQ (2/16/2017): This is a static function that is defined but not used in this file (compiler waring).
23045
23047 static
23048 void swapDefiningElements(SgFunctionDeclaration& ll, SgFunctionDeclaration& rr)
23049 {
23050 // swap definitions
23051 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_definition, &SgFunctionDeclaration::set_definition);
23052 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_parameterList, &SgFunctionDeclaration::set_parameterList);
23053
23054 // \todo do we need to swap also exception spec, decorator_list, etc. ?
23055 }
23056#endif
23057
23058#if 0
23059 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23060 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23061
23062 std::pair<SgStatement*, SgInitializedName*>
23063 SageInterface::wrapFunction(SgFunctionDeclaration& definingDeclaration, SgName newName)
23064 {
23065 namespace SB = SageBuilder;
23066
23067 // handles freestanding functions only
23068 ROSE_ASSERT(typeid(SgFunctionDeclaration) == typeid(definingDeclaration));
23069 ROSE_ASSERT(definingDeclaration.get_definingDeclaration() == &definingDeclaration);
23070
23071 // clone function parameter list
23072 SgFunctionParameterList& param_list = cloneParameterList(*definingDeclaration.get_parameterList());
23073
23074 // create new function definition/declaration in the same scope
23075 SgScopeStatement* containing_scope = definingDeclaration.get_scope();
23076 SgType* result_type = definingDeclaration.get_type()->get_return_type();
23077 SgExprListExp* decorators = deepCopy( definingDeclaration.get_decoratorList() );
23078
23079 // DQ (4/9/2015): Suggested fix for this function.
23080 // SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope, decorators);
23081 SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope);
23082
23083 SgFunctionDefinition* wrapperdef = wrapperfn->get_definition();
23084 ROSE_ASSERT(wrapperdef);
23085
23086 // copy the exception specification
23087 wrapperfn->set_exceptionSpecification(definingDeclaration.get_exceptionSpecification());
23088
23089 // swap the original's function definition w/ the clone's function def
23090 // and the original's func parameter list w/ the clone's parameters
23091 swapDefiningElements(definingDeclaration, *wrapperfn);
23092
23093 // call original function from within the defining decl's body
23094 SgBasicBlock* body = wrapperdef->get_body();
23095 SgExprListExp* args = SB::buildExprListExp();
23096 SgInitializedNamePtrList& param_decls = param_list.get_args();
23097
23098 std::transform( param_decls.begin(), param_decls.end(), sg::sage_inserter(*args), sg::VarRefBuilder(*wrapperdef) );
23099
23100 SgFunctionCallExp* callWrapped = SB::buildFunctionCallExp( newName, result_type, args, body );
23101 SgInitializedName* resultName = NULL;
23102 SgStatement* callStatement = NULL;
23103
23104 // \todo skip legal qualifiers that could be on top of void
23105 if (!isSgTypeVoid(result_type))
23106 {
23107 // add call to original function and assign result to variable
23108 SgVariableDeclaration* res = SB::buildVariableDeclaration( "res", result_type, SB::buildAssignInitializer(callWrapped), body );
23109 SgVarRefExp* resref = SB::buildVarRefExp( res );
23110
23111 appendStatement(res, body);
23112
23113 // add return statement, returning result
23114 resultName = &getFirstVariable(*res);
23115 callStatement = res;
23116
23117 appendStatement(SB::buildReturnStmt(resref), body);
23118 }
23119 else
23120 {
23121 // add function call statement to original function
23122 callStatement = SB::buildExprStatement(callWrapped);
23123 appendStatement(callStatement, body);
23124 }
23125
23126 ROSE_ASSERT(callStatement);
23127
23128 // create non defining declaration
23129 SgExprListExp* decorator_proto = deepCopy( decorators );
23130 SgFunctionDeclaration* wrapperfn_proto = SB::buildNondefiningFunctionDeclaration(wrapperfn, containing_scope, decorator_proto);
23131
23132 // add the new functions at the proper location of the surrounding scope
23133 insertStatementBefore(&definingDeclaration, wrapperfn_proto);
23134 insertStatementAfter (&definingDeclaration, wrapperfn);
23135
23136 return std::make_pair(callStatement, resultName);
23137 }
23138#endif
23139
23140 //
23141 // flatten C/C++ array dimensions
23142 namespace
23143 {
23144 struct VarrefBuilder
23145 {
23146 virtual SgVarRefExp* get() const = 0;
23147
23148 static
23149 SgVarRefExp* build(const SgVarRefExp& n)
23150 {
23151 return SageInterface::deepCopy(&n);
23152 }
23153
23154 static
23156 {
23157 SgScopeStatement* scope = sg::ancestor<SgStatement>(n).get_scope();
23158
23159 return SageBuilder::buildVarRefExp(&n, scope);
23160 }
23161 };
23162
23163 template <class AstNode>
23164 struct VarrefCreator : VarrefBuilder
23165 {
23166 AstNode& origin;
23167
23168 explicit
23169 VarrefCreator(AstNode& orig)
23170 : origin(orig)
23171 {}
23172
23173 SgVarRefExp* get() const { return VarrefBuilder::build(origin); }
23174 };
23175
23176 template <class AstNode>
23177 VarrefCreator<AstNode>
23178 varrefCreator(AstNode& n)
23179 {
23180 return VarrefCreator<AstNode>(n);
23181 }
23182
23183 SgExpression* create_mulop(SgExpression* lhs, const SgExpression* rhs)
23184 {
23185 namespace SB = SageBuilder;
23186 namespace SI = SageInterface;
23187
23188 // we own the lhs (intermediate result),
23189 // but we do not own the rhs (another top-level expression)
23190 return SB::buildMultiplyOp(lhs, SI::deepCopy(rhs));
23191 }
23192
23193 std::pair<std::vector<SgExpression*>, SgType*>
23194 get_C_array_dimensions_aux(const SgArrayType& arr_type)
23195 {
23196 namespace SB = SageBuilder;
23197 namespace SI = SageInterface;
23198
23199 const SgArrayType* arrtype = &arr_type;
23200 std::vector<SgExpression*> indices;
23201 SgType* undertype = NULL;
23202
23203 // \todo when get_index() does not return a nullptr anymore
23204 // the condition can be removed
23205 if (arrtype->get_index() == NULL)
23206 {
23207 indices.push_back(SB::buildNullExpression());
23208 undertype = arrtype->get_base_type();
23209 arrtype = isSgArrayType(undertype);
23210 }
23211
23212 while (arrtype)
23213 {
23214 SgExpression* indexexpr = arrtype->get_index();
23215 ROSE_ASSERT(indexexpr);
23216
23217 indices.push_back(SI::deepCopy(indexexpr));
23218 undertype = arrtype->get_base_type();
23219 arrtype = isSgArrayType(undertype);
23220 }
23221
23222 ROSE_ASSERT((!indices.empty()) && undertype);
23223 return std::make_pair(indices, undertype);
23224 }
23225
23227 std::vector<SgExpression*>
23228 get_C_array_dimensions_aux(const SgArrayType& arrtype, const VarrefBuilder& varrefBuilder)
23229 {
23230 namespace SB = SageBuilder;
23231
23232 std::pair<std::vector<SgExpression*>, SgType*> res = get_C_array_dimensions_aux(arrtype);
23233 const std::vector<SgExpression*>::iterator first = res.first.begin();
23234
23235 // if the first dimension was open, create the expression for it
23236 if (isSgNullExpression(*first))
23237 {
23238 // handle implicit first dimension for array initializers
23239 // for something like
23240 // int p[][2][3] = {{{ 1, 2, 3 }, { 4, 5, 6 }}}
23241 // we can calculate the first dimension as
23242 // sizeof( p ) / ( sizeof( int ) * 2 * 3 )
23243
23244 const std::vector<SgExpression*>::iterator aa = first+1;
23245 const std::vector<SgExpression*>::iterator zz = res.first.end();
23246
23247 SgExpression* sz_undertype = SB::buildSizeOfOp(res.second);
23248 SgExpression* denominator = std::accumulate(aa, zz, sz_undertype, create_mulop);
23249 SgSizeOfOp* sz_var = SB::buildSizeOfOp(varrefBuilder.get());
23250 SgExpression* sz = SB::buildDivideOp(sz_var, denominator);
23251
23252 std::swap(*first, sz);
23253 delete sz;
23254 }
23255
23256 return res.first;
23257 }
23258 }
23259
23260 std::vector<SgExpression*>
23262 {
23263 return get_C_array_dimensions_aux(arrtype).first;
23264 }
23265
23266 std::vector<SgExpression*>
23268 {
23269 return get_C_array_dimensions_aux(arrtype, varrefCreator(varref));
23270 }
23271
23272 std::vector<SgExpression*>
23274 {
23275 return get_C_array_dimensions_aux(arrtype, varrefCreator(initname));
23276 }
23277
23278// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23280 {
23281 public:
23282 set<unsigned int> sourceSequenceSet;
23283
23284 void visit ( SgNode* astNode );
23285 };
23286
23287// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23288void
23290 {
23291 Sg_File_Info* fileInfo = astNode->get_file_info();
23292 if (fileInfo != NULL)
23293 {
23294 unsigned int source_sequence_number = fileInfo->get_source_sequence_number();
23295#if 0
23296 printf ("In CollectSourceSequenceNumbers::visit(): source_sequence_number = %" PRIuPTR " \n",source_sequence_number);
23297#endif
23298 sourceSequenceSet.insert(source_sequence_number);
23299 }
23300 }
23301
23302// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23303set<unsigned int>
23305 {
23307
23308 traversal.traverse(astNode,preorder);
23309
23310 return traversal.sourceSequenceSet;
23311
23312 }
23313
23314/*Winnie, loop collapse, collapse nested for loops into one large for loop
23315 * return a SgExprListExp *, which will contain a list of SgVarRefExp * to variables newly created, inserted outside of the
23316 * loop scope, and used inside the loop scope.
23317 * If the target_loop comes with omp target directive, these variables should be added in map in clause in
23318 * transOmpCollpase(..) function in omp_lowering.cpp.
23319 *
23320 * The input loop pointer is changed to the generated collapsed loop after the transformation.
23321 *
23322 *
23323 * Loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
23324 *
23325 * to collapse two level of loops:
23326 * iteration_count_one= (ub1-lb1+1)%step1 ==0?(ub1-lb1+1)/step1: (ub1-lb1+1)/step1+1
23327 * iteration_count_two= (ub2-lb2+1)%step2 ==0?(ub2-lb2+1)/step2: (ub2-lb2+1)/step2+1
23328 * total_iteration_count = iteration_count_one * iteration_count_two
23329 *
23330 * Decide incremental/decremental loop by checking operator of test statement(ub), <=/>=, this is done in isCanonicalForLoop()
23331 *
23332 * Example 1:
23333 * for (int i=lb2;i<ub2;i+=inc2) //incremental
23334 * {
23335 * for (int j=lb1;j>ub1;i+=inc1) //decremental
23336 * {
23337 * for (int l=lb2;l<ub2;l+=inc2) //incremental
23338 * {
23339 * a[i][j][l]=i+j+l;
23340 * }
23341 * }
23342 * }
23343 *
23344 *==> translated output code ==>
23345 * int i_nom_1_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23346 * 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;
23347 * int l_nom_3_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23348 * int final_total_iters = 1 * i_nom_1_total_iters* j_nom_2_total_iters* l_nom_3_total_iters;
23349 * int i_nom_1_interval = j_nom_2_total_iters * (l_nom_3_total_iters* 1);
23350 * int j_nom_2_interval = l_nom_3_total_iters * 1;
23351 * int l_nom_3_interval = 1;
23352 *
23353 * for (int new_index = 0; new_index <= final_total_iters- 1; new_index += 1) {
23354 * i_nom_1 = new_index / i_nom_1_interval* inc2 + lb2;
23355 * int i_nom_1_remainder = new_index % i_nom_1_interval;
23356 * j_nom_2 = -(i_nom_1_remainder / j_nom_2_interval* (inc1 * -1)) + lb1;
23357 * l_nom_3 = i_nom_1_remainder % j_nom_2_interval* inc2 + lb2;
23358 * a[i_nom_1][j_nom_2][l_nom_3] = i_nom_1 + j_nom_2 + l_nom_3;
23359 * }
23360 *
23361 * Example 2 with concrete numbers:
23362 *
23363 * // collapse the following two level of for loops:
23364 * for (i=1; i<=9; i+=1) //incremental for loop
23365 * {
23366 * for(j=10; j>=1; j+=-2) //decremental for loop
23367 * {
23368 * a[i][j]=i+j;
23369 * }
23370 * }
23371 * // it becomes
23372 * // total iteration count = ((9 - 1 + 1)/1) * ((10 - 1 + 1)/2) = 45
23373 * // ub = 45
23374 * // lb = 0
23375 *
23376 * int i_nom_1_total_iters = 9;
23377 * int j_nom_1_total_iters = 5; // 10 % (-2 * -1) == 0 ? 10 / (-2 * -1) : 10 /(-2 * -1) + 1;
23378 * int final_total_iters = 45; // i_nom_1_total_iters * j_nom_2_total_iters;
23379 *
23380 * int i_nom_1_interval = 5;
23381 *
23382 * for (z=0; z<=44; z+=1)
23383 * {
23384 * i_nom_1 = z / 5 + 1;
23385 * j_nom_2 = -(z % 5 * 2) + 10;
23386 * a[i_nom_1][j_nom_2]=i_nom_1 + j_nom_2;
23387 * }
23388 * // for the generated loop, a few compiler generated variables are introduced
23389 * final_total_iters for the collapsed loop
23390 * i_interval for each of the n-1 loops
23391 **
23392*/
23393
23394#ifndef USE_ROSE
23396{
23397#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23398 //Handle 0 and 1, which means no collapsing at all
23399 if (collapsing_factor <= 1)
23400 return NULL;
23401
23402 SgExprListExp * new_var_list = buildExprListExp(); //expression list contains all the SgVarRefExp * to variables that need to be added in the mapin clause
23403
23404 /*
23405 *step 1: grab the target loops' header information
23406 */
23407 SgForStatement *& target_loop = loop;
23408
23409 // we use global scope to help generate unique variable name later
23410 // local scope-based unique names may cause conflicts if the declarations are moved around (in OpenMP target data promotion)
23411 SgGlobal* global_scope = getGlobalScope (loop);
23412 ROSE_ASSERT (global_scope != NULL);
23413 SgInitializedName** ivar = new SgInitializedName*[collapsing_factor];
23414 SgExpression** lb = new SgExpression*[collapsing_factor];
23415 SgExpression** ub = new SgExpression*[collapsing_factor];
23416 SgExpression** step = new SgExpression*[collapsing_factor];
23417 SgStatement** orig_body = new SgStatement*[collapsing_factor];
23418
23419 SgExpression** total_iters = new SgExpression*[collapsing_factor]; //Winnie, the real iteration counter in each loop level
23420 SgExpression** interval = new SgExpression*[collapsing_factor]; //Winnie, this will be used to calculate i_nom_1_remainder
23421 bool *isPlus = new bool[collapsing_factor]; //Winnie, a flag indicates incremental or decremental for loop
23422
23423
23424 //Winnie, get loops info first
23425 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(target_loop,V_SgForStatement);
23426 ROSE_ASSERT(loops.size()>=collapsing_factor);
23427
23428 SgForStatement* temp_target_loop = NULL;
23429 SgExpression* temp_range_exp = NULL; //Raw iteration range
23430 SgExpression* temp_range_d_step_exp = NULL; //temp_range_exp / step[i]
23431 SgExpression* temp_condition_1 = NULL; //Check whether temp_range_exp % step[i] == 0
23432 SgExpression* temp_total_iter = NULL;
23433 SgExpression* ub_exp = buildIntVal(1); //Winnie, upbound
23434
23435 /*
23436 * get lb, ub, step information for each level of the loops
23437 * ub_exp is the final iterantion range(starting from 0) after loop collapsing
23438 * total_iters[i], = (ub[i] - lb[i] + 1)/step[i] is the total iter num in each level of loop before loop collapsing
23439 */
23440
23441 SgStatement* parent = isSgStatement(getScope(target_loop)->get_parent()); //Winnie, the scope that include target_loop
23442 ROSE_ASSERT(getScope(target_loop)->get_parent()!= NULL);
23443
23444 SgScopeStatement* scope = isSgScopeStatement(parent); //Winnie, the scope that include target_loop
23445
23446 while(scope == NULL)
23447 {
23448 parent = isSgStatement(parent->get_parent());
23449 scope = isSgScopeStatement(parent);
23450 }
23451
23452 SgStatement* insert_target = findLastDeclarationStatement(scope);
23453 if (insert_target != NULL)
23454 insert_target = getNextStatement(insert_target);
23455 else
23456 insert_target = getFirstStatement(scope);
23457
23458 ROSE_ASSERT(scope != NULL);
23459
23460
23461 for(size_t i = 0; i < collapsing_factor; i ++)
23462 {
23463 temp_target_loop = loops[i];
23464
23465 // normalize the target loop first // adjust to numbering starting from 0
23466 forLoopNormalization(temp_target_loop);
23467
23468 if (!isCanonicalForLoop(temp_target_loop, &ivar[i], &lb[i], &ub[i], &step[i], &orig_body[i], &isPlus[i]))
23469 {
23470 cerr<<"Error in SageInterface::loopCollapsing(): target loop is not canonical."<<endl;
23471 dumpInfo(target_loop);
23472
23473 // release memory
23474 delete[] ivar;
23475 delete[] lb;
23476 delete[] ub;
23477 delete[] step;
23478 delete[] orig_body;
23479 delete[] total_iters;
23480 delete[] interval;
23481 delete[] isPlus;
23482
23483 return NULL;
23484 }
23485
23486 ROSE_ASSERT(ivar[i]&& lb[i] && ub[i] && step[i]);
23487
23488
23489//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]
23490 if(isPlus[i] == true)
23491 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(ub[i]), copyExpression(lb[i])), buildIntVal(1));
23492 else{
23493 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(lb[i]), copyExpression(ub[i])), buildIntVal(1));
23494 step[i] = buildMultiplyOp(step[i], buildIntVal(-1));
23495 }
23496 temp_range_d_step_exp = buildDivideOp(temp_range_exp,copyExpression(step[i]));//(ub[i]-lb[i]+1)/step[i]
23497
23498 temp_condition_1 = buildEqualityOp(buildModOp(copyExpression(temp_range_exp),copyExpression(step[i])),buildIntVal(0)); //(ub[i]-lb[i]+1)%step[i] ==0
23499
23500 temp_total_iter = buildConditionalExp(temp_condition_1,temp_range_d_step_exp, buildAddOp(copyExpression(temp_range_d_step_exp),buildIntVal(1)));
23501
23502 //build variables to store iteration numbers in each loop, simplify the calculation of "final_total_iters"
23503 //insert the new variable (store real iteration number of each level of the loop) before the target loop
23504 string iter_var_name= "_total_iters";
23505 //iter_var_name = ivar[i]->get_name().getString() + iter_var_name + generateUniqueName(temp_total_iter, false);
23506 iter_var_name = "__"+ivar[i]->get_name().getString() + iter_var_name+ generateUniqueVariableName (global_scope,"");
23507 SgVariableDeclaration* total_iter = buildVariableDeclaration(iter_var_name, buildIntType(), buildAssignInitializer(temp_total_iter, buildIntType()), scope);
23508 insertStatementBefore(insert_target, total_iter);
23509 constantFolding (total_iter);
23510 total_iters[i] = buildVarRefExp(iter_var_name, scope);
23511 ub_exp = buildMultiplyOp(ub_exp, total_iters[i]); //Winnie, build up the final iteration range
23512 }
23513
23514
23515 /*
23516 * step 2: build new variables (new_index, final_total_iters, remainders...) for the new loop
23517 */
23518
23519 /*Winnie, build another variable to store final total iteration counter of the loop after collapsing*/
23520 //string final_iter_counter_name = "final_total_iters" + generateUniqueName(ub_exp, false);
23521 string final_iter_counter_name = "__final_total_iters" + generateUniqueVariableName(global_scope,"");
23522 SgVariableDeclaration * final_total_iter = buildVariableDeclaration(final_iter_counter_name, buildIntType(), buildAssignInitializer(copyExpression(ub_exp), buildIntType()), scope);
23523 insertStatementBefore(insert_target, final_total_iter);
23524 ub_exp = buildVarRefExp(final_iter_counter_name, scope);
23525 new_var_list->append_expression(isSgVarRefExp(ub_exp));
23526
23527 /*Winnie, interval[i] will make the calculation of remainders simpler*/
23528 for(unsigned int i = 0; i < collapsing_factor; i++)
23529 {
23530 interval[i] = buildIntVal(1);
23531 for(unsigned int j = collapsing_factor - 1; j > i; j--)
23532 {
23533 interval[i] = buildMultiplyOp(total_iters[j], interval[i]);
23534 }
23535 //string interval_name = ivar[i]->get_name().getString() + "_interval" + generateUniqueName(interval[i], false);
23536 string interval_name = "__"+ ivar[i]->get_name().getString() + "_interval" + generateUniqueVariableName (global_scope,"");
23537 SgVariableDeclaration* temp_interval = buildVariableDeclaration(interval_name, buildIntType(), buildAssignInitializer(copyExpression(interval[i]), buildIntType()), scope);
23538 insertStatementBefore(insert_target, temp_interval);
23539 interval[i] = buildVarRefExp(interval_name, scope);
23540 new_var_list->append_expression(isSgVarRefExp(interval[i]));
23541 }
23542
23543
23544 //Winnie, starting from here, we are dealing with variables inside loop, update scope
23545 scope = getScope(target_loop);
23546
23547 //Winnie, init statement of the loop header, copy the lower bound, we are dealing with a range, the lower bound should always be "0"
23548 //Winnie, declare a brand new var as the new index
23549 string ivar_name = "__collapsed_index"+ generateUniqueVariableName (global_scope,"");
23550 ROSE_ASSERT(insert_target != NULL);
23551 SgVariableDeclaration* new_index_decl = buildVariableDeclaration(ivar_name, buildIntType(), NULL, insert_target->get_scope());
23552 SgVariableSymbol * collapsed_index_symbol = getFirstVarSym (new_index_decl);
23553 insertStatementBefore(insert_target, new_index_decl);
23554 SgVarRefExp * clps_index_ref = buildVarRefExp(collapsed_index_symbol);
23555 new_var_list->append_expression(clps_index_ref);
23556
23557// SgVariableDeclaration* init_stmt = buildVariableDeclaration(ivar_name, buildIntType(), buildAssignInitializer(buildIntVal(0), buildIntType()), scope);
23558
23559
23560 SgBasicBlock* body = isSgBasicBlock(deepCopy(temp_target_loop->get_loop_body())); // normalized loop has a BB body
23561 ROSE_ASSERT(body != NULL);
23562 SgExpression* new_exp = NULL;
23563 SgExpression* remain_exp_temp = buildVarRefExp(ivar_name, scope);
23564 std::vector<SgStatement*> new_stmt_list;
23565
23566 SgExprStatement* assign_stmt = NULL;
23567
23568 /* Winnie
23569 * express old iterator variables (i_norm, j_norm ...) with new_index,
23570 * new_exp, create new expression for each of the iterators
23571 * i_nom_1 = (_new_index / interval[0])*step[0] + lb[0]
23572 * i_nom_1_remain_value = (_new_index % interval[0])*step[0] + lb[0], create a new var to store remain value
23573 * create a new var to store total_iters[i]
23574 */
23575 for(unsigned int i = 0; i < collapsing_factor - 1; i ++)
23576 {
23577 if(isPlus[i] == true)
23578 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]
23579 else
23580 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
23581
23582 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[i], scope), copyExpression(new_exp));
23583 new_stmt_list.push_back(assign_stmt);
23584 remain_exp_temp = buildModOp((remain_exp_temp), copyExpression(interval[i]));
23585
23586 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
23587 string remain_var_name= "_remainder";
23588 remain_var_name = "__"+ ivar[i]->get_name().getString() + remain_var_name;
23589 SgVariableDeclaration* loop_index_decl = buildVariableDeclaration(remain_var_name, buildIntType(), buildAssignInitializer(remain_exp_temp, buildIntType()), scope);
23590 remain_exp_temp = buildVarRefExp(remain_var_name, scope);
23591 new_stmt_list.push_back(loop_index_decl);
23592 }
23593 new_exp = NULL;
23594 }
23595
23596//Winnie, the inner most loop, iter
23597 if(isPlus[collapsing_factor - 1] == true)
23598 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1]), lb[collapsing_factor - 1]));
23599 else
23600 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMinusOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1])), lb[collapsing_factor - 1]));
23601 new_stmt_list.push_back(assign_stmt);
23602 prependStatementList(new_stmt_list, body);
23603
23604 /*
23605 * step 3: build the new loop, new step is always 1, disregard value of step[i]
23606 */
23607 SgExpression* incr_exp = buildPlusAssignOp(buildVarRefExp(ivar_name, scope), buildIntVal(1));
23608
23609 //Winnie, build the new conditional expression/ub
23610 SgExprStatement* cond_stmt = NULL;
23611 ub_exp = buildSubtractOp(ub_exp, buildIntVal(1));
23612 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar_name,scope),copyExpression(ub_exp)));
23613 ROSE_ASSERT(cond_stmt != NULL);
23614
23615 SgForStatement* new_loop = buildForStatement(buildAssignStatement(clps_index_ref, buildIntVal(0)), cond_stmt,incr_exp, body); //Winnie, add in the new block!
23616 new_loop->set_parent(scope); //TODO: what's the correct parent?
23617
23618 replaceStatement(target_loop, new_loop);
23619
23620 target_loop = new_loop; //Winnie, so that transOmpLoop() can work on the collapsed loop
23621 // constant folding for the transformed AST
23622 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
23623
23624 delete [] ivar;
23625 delete [] lb;
23626 delete [] ub;
23627 delete [] step;
23628 delete [] orig_body;
23629 delete [] total_iters;
23630 delete [] interval;
23631 delete [] isPlus;
23632
23633 #endif
23634
23635 return new_var_list;
23636}
23637
23638
23639
23640bool
23642 {
23643 // DQ (3/4/2014): Added support for testing two trees for equivalents using the AST iterators.
23644
23645#ifndef USE_CMAKEx
23646 // DQ (3/8/2014): Make this conditionally compiled based on when CMake is not used because the libraries are not configured yet.
23647
23648 // This is AST container for the ROSE AST that will provide an iterator.
23649 // We want two iterators (one for the copy of the snippet and one for the
23650 // original snippet so that we can query the original snippet's AST
23651 // as we process each IR node of the AST for the copy of the snippet.
23652 // Only the copy of the snippet is inserted into the target AST.
23653 RoseAst ast_of_copy(tree1);
23654 RoseAst ast_of_original(tree2);
23655
23656 // printf ("ast_of_copy.size() = %" PRIuPTR " \n",ast_of_copy.size());
23657
23658 // Build the iterators so that we can increment thorugh both ASTs one IR node at a time.
23659 RoseAst::iterator i_copy = ast_of_copy.begin();
23660 RoseAst::iterator i_original = ast_of_original.begin();
23661
23662 // Iterate of the copy of the snippet's AST.
23663 while (i_copy != ast_of_copy.end())
23664 {
23665#if 0
23666 printf ("*i_copy = %p = %s \n",*i_copy,(*i_copy)->class_name().c_str());
23667 printf ("*i_original = %p = %s \n",*i_original,(*i_original)->class_name().c_str());
23668#endif
23669 // DQ (2/28/2014): This is a problem for some of the test codes (TEST store/load heap string [test7a] and [test7a])
23670 // ROSE_ASSERT((*i_copy)->variantT() == (*i_original)->variantT());
23671 if ((*i_copy)->variantT() != (*i_original)->variantT())
23672 {
23673#if 0
23674 printf ("ERROR: return from SageInterface::isStructurallyEquivalentAST(): (*i_copy)->variantT() != (*i_original)->variantT() \n");
23675#endif
23676#if 0
23677 printf ("Making this an error! \n");
23678 ROSE_ABORT();
23679#endif
23680 return false;
23681 }
23682
23683 i_copy++;
23684
23685 // Verify that we have not reached the end of the ast for the original (both the
23686 // copy and the original are the same structurally, and thus the same size).
23687 ROSE_ASSERT(i_original != ast_of_original.end());
23688 i_original++;
23689 }
23690
23691 // We have reached the end of both ASTs.
23692 ROSE_ASSERT(i_copy == ast_of_copy.end() && i_original == ast_of_original.end());
23693#endif
23694
23695 return true;
23696 }
23697
23698
23699#endif
23700
23702 SgForStatement * for_loop,
23703 SgVariableSymbol * & iterator,
23704 SgExpression * & lower_bound,
23705 SgExpression * & upper_bound,
23706 SgExpression * & stride
23707) {
23710
23711 iterator = NULL;
23712 lower_bound = NULL;
23713 upper_bound = NULL;
23714 stride = NULL;
23715
23716 SgForInitStatement * for_init_stmt = for_loop->get_for_init_stmt();
23717 const std::vector<SgStatement *> & init_stmts = for_init_stmt->get_init_stmt();
23718 assert(init_stmts.size() == 1);
23719 SgExprStatement * init_stmt = isSgExprStatement(init_stmts[0]);
23720 assert(init_stmt != NULL);
23721 SgExpression * init = init_stmt->get_expression();
23722
23723 SgAssignOp * assign_init = isSgAssignOp(init);
23724 assert(assign_init != NULL);
23725 SgVarRefExp * iterator_init_ref = isSgVarRefExp(assign_init->get_lhs_operand_i());
23726 assert(iterator_init_ref != NULL);
23727 iterator = iterator_init_ref->get_symbol();
23728 assert(iterator != NULL);
23729 lower_bound = assign_init->get_rhs_operand_i();
23730
23731 SgExprStatement * test_stmt = isSgExprStatement(for_loop->get_test());
23732 assert(test_stmt != NULL);
23733 SgExpression * test = test_stmt->get_expression();
23734 SgBinaryOp * bin_test = isSgBinaryOp(test);
23735 assert(bin_test);
23736
23737 SgExpression * lhs_exp = bin_test->get_lhs_operand_i();
23738 while (isSgCastExp(lhs_exp)) lhs_exp = ((SgCastExp *)lhs_exp)->get_operand_i();
23739 SgVarRefExp * lhs_var_ref = isSgVarRefExp(lhs_exp);
23740 bool lhs_it = (lhs_var_ref != NULL) && (lhs_var_ref->get_symbol() == iterator);
23741
23742 SgExpression * rhs_exp = bin_test->get_rhs_operand_i();
23743 while (isSgCastExp(rhs_exp)) rhs_exp = ((SgCastExp *)rhs_exp)->get_operand_i();
23744 SgVarRefExp * rhs_var_ref = isSgVarRefExp(rhs_exp);
23745#ifndef NDEBUG
23746 bool rhs_it = (rhs_var_ref != NULL) && (rhs_var_ref->get_symbol() == iterator);
23747
23748// DQ (4/21/2016): Replacing use of bitwise xor with something more approriate for logical types.
23749// Note that the xor logica operator does not exist in C/C++ and that this is a case of using the
23750// bitwise xor operator on boolean values (not a great idea). Note that logical "a xor b" is
23751// equivalent to "!a != !b" the use of "!" only make sure that the "!=" is applied to a boolean
23752// value. Since these are boolean typed values we can use "a != b", directly.
23753// assert(lhs_it xor rhs_it);
23754 assert(lhs_it != rhs_it);
23755#endif
23756
23757 upper_bound = lhs_it ? bin_test->get_rhs_operand_i() : bin_test->get_lhs_operand_i();
23758
23759 bool inclusive;
23760 bool reversed;
23761
23762 switch (test->variantT()) {
23763 case V_SgGreaterOrEqualOp:
23764 inclusive = lhs_it;
23765 reversed = lhs_it;
23766 break;
23767 case V_SgGreaterThanOp:
23768 inclusive = !lhs_it;
23769 reversed = lhs_it;
23770 break;
23771 case V_SgLessOrEqualOp:
23772 inclusive = lhs_it;
23773 reversed = !lhs_it;
23774 break;
23775 case V_SgLessThanOp:
23776 inclusive = !lhs_it;
23777 reversed = !lhs_it;
23778 break;
23779 case V_SgEqualityOp:
23780 case V_SgNotEqualOp:
23781 default:
23782 ROSE_ABORT();
23783 }
23784
23785 SgExpression * increment = for_loop->get_increment();
23786 switch (increment->variantT()) {
23787 case V_SgPlusPlusOp:
23788 assert(!reversed);
23789 stride = SageBuilder::buildIntVal(1);
23790 break;
23791 case V_SgMinusMinusOp:
23792 assert(reversed);
23793 stride = SageBuilder::buildIntVal(-1);
23794 break;
23795 case V_SgPlusAssignOp:
23796 {
23797 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23798#ifndef NDEBUG
23799 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23800 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23801#endif
23802 stride = bin_op->get_rhs_operand_i();
23803 break;
23804 }
23805 case V_SgMinusAssignOp:
23806 {
23807 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23808#ifndef NDEBUG
23809 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23810 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23811#endif
23812 stride = bin_op->get_rhs_operand_i();
23813 break;
23814 }
23815 case V_SgAssignOp:
23816 {
23817 SgAssignOp * assign_op = (SgAssignOp *)increment;
23818#ifndef NDEBUG
23819 SgVarRefExp * inc_assign_lhs = isSgVarRefExp(assign_op->get_lhs_operand_i());
23820 assert(inc_assign_lhs != NULL && inc_assign_lhs->get_symbol() == iterator);
23821#endif
23822 SgBinaryOp * inc_assign_rhs = isSgBinaryOp(assign_op->get_rhs_operand_i());
23823 assert(inc_assign_rhs != NULL);
23824 SgVarRefExp * inc_assign_rhs_lhs = isSgVarRefExp(inc_assign_rhs->get_lhs_operand_i());
23825 if (inc_assign_rhs_lhs != NULL && inc_assign_rhs_lhs->get_symbol() == iterator)
23826 stride = inc_assign_rhs->get_rhs_operand_i();
23827 SgVarRefExp * inc_assign_rhs_rhs = isSgVarRefExp(inc_assign_rhs->get_rhs_operand_i());
23828 if (inc_assign_rhs_rhs != NULL && inc_assign_rhs_rhs->get_symbol() == iterator)
23829 stride = inc_assign_rhs->get_lhs_operand_i();
23830 break;
23831 }
23832 default:
23833 ROSE_ABORT();
23834 }
23835
23836 // DQ (7/19/2015): Added braces to avoid compiler warning about ambigious "else" case.
23837 if (!inclusive)
23838 {
23839 if (reversed)
23840 upper_bound = SageBuilder::buildAddOp(upper_bound, SageBuilder::buildIntVal(1));
23841 else
23842 upper_bound = SageBuilder::buildSubtractOp(upper_bound, SageBuilder::buildIntVal(1));
23843 }
23844
23845 return true;
23846}
23847
23848//------------------------------------------------------------------------------
23849#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
23850//------------------------------------------------------------------------------
23851
23856 jstring temp_directory = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(::currentJavaTraversalClass, Rose::Frontend::Java::Ecj::getTempDirectoryMethod);
23857
23858 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_directory, NULL);
23859 ROSE_ASSERT(utf8);
23860 string directory_name = utf8;
23861 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_directory, utf8);
23862
23863 list<string> sourcepath = project -> get_Java_sourcepath();
23864 sourcepath.push_back(directory_name); // push it in the back because it should have lower priority
23865 project -> set_Java_sourcepath(sourcepath);
23866
23867 return directory_name;
23868}
23869
23870
23874void SageInterface::destroyTempDirectory(string directory_name) {
23875 string command = string("rm -fr ") + directory_name;
23876 int status = system(command.c_str());
23877 ROSE_ASSERT(status == 0);
23878}
23879
23880
23884SgFile* SageInterface::processFile(SgProject *project, string filename, bool unparse /* = false */) {
23885 //
23886 // Set up the new source file for processing "a la Rose".
23887 //
23888 project -> get_sourceFileNameList().push_back(filename);
23889 Rose_STL_Container<std::string> arg_list = project -> get_originalCommandLineArgumentList();
23890 arg_list.push_back(filename);
23891 Rose_STL_Container<string> fileList = CommandlineProcessing::generateSourceFilenames(arg_list, false);
23892 CommandlineProcessing::removeAllFileNamesExcept(arg_list, fileList, filename);
23893 int error_code = 0; // need this because determineFileType takes a reference "error_code" argument.
23894 SgFile *file = determineFileType(arg_list, error_code, project);
23895 SgSourceFile *sourcefile = isSgSourceFile(file);
23896 ROSE_ASSERT(sourcefile);
23897 sourcefile -> set_parent(project);
23898
23899 //
23900 // Insert the file into the list of files in the project.
23901 //
23902 project -> get_fileList_ptr() -> get_listOfFiles().push_back(sourcefile);
23903 ROSE_ASSERT(sourcefile == isSgSourceFile((*project)[filename]));
23904
23905 sourcefile -> build_Java_AST(arg_list, project -> get_originalCommandLineArgumentList());
23906
23907 if (! unparse) { // if we are not supposed to unparse this file,
23908 project -> get_fileList_ptr() -> get_listOfFiles().pop_back(); // remove it from the list of files in the project
23909 ROSE_ASSERT(sourcefile != isSgSourceFile((*project)[filename]));
23910 }
23911
23912 // DQ (7/2/2020): Added assertion (fails for snippet tests).
23913 ROSE_ASSERT(file->get_preprocessorDirectivesAndCommentsList() != NULL);
23914
23915 return file;
23916}
23917
23918
23923string SageInterface::preprocessPackage(SgProject *project, string package_name) {
23924 string command = "package " + package_name + ";";
23925
23926 //
23927 // Call the Java side to create an input file with the relevant package statement; translate the file and return the file name.
23928 //
23929 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23930 Rose::Frontend::Java::Ecj::createTempFileMethod,
23931 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23932
23933 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23934 ROSE_ASSERT(utf8);
23935 string filename = (string) utf8;
23936 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23937
23938 processFile(project, filename); // translate the file
23939
23940 return package_name;
23941}
23942
23943
23948string SageInterface::preprocessImport(SgProject *project, string import_string) {
23949 string command = "import " + import_string + ";";
23950
23951 //
23952 // Call the Java side to create an input file with the relevant import statement.
23953 //
23954 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23955 Rose::Frontend::Java::Ecj::createTempFileMethod,
23956 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23957
23958 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23959 ROSE_ASSERT(utf8);
23960 string filename = (string) utf8;
23961 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23962
23963 processFile(project, filename); // translate the file
23964
23965 return import_string;
23966}
23967
23968
23973SgFile* SageInterface::preprocessCompilationUnit(SgProject *project, string file_name, string file_content, bool unparse /* true */) {
23974 //
23975 // Call the Java side to create an input file with the relevant import statement.
23976 //
23977 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23978 Rose::Frontend::Java::Ecj::createTempNamedFileMethod,
23979 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_name.c_str()),
23980 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_content.c_str()));
23981
23982 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23983 ROSE_ASSERT(utf8);
23984 string filename = (string) utf8;
23985 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23986
23987 return processFile(project, filename, unparse); // translate the file and unparse it, if requested (unparse=true is the default).
23988}
23989
23990
23995 ROSE_ASSERT(scope);
23996 SgClassDefinition *package_definition = NULL;
23997 for (int index = 0, length = package_name.size(); index < length; index++) {
23998 int n;
23999 for (n = index; n < length; n++) {
24000 if (package_name[n] == '.') {
24001 break;
24002 }
24003 }
24004 string name = package_name.substr(index, n - index);
24005
24006 SgClassSymbol *package_symbol = scope -> lookup_class_symbol(name);
24007 if (package_symbol == NULL) { // package not found?
24008 return NULL;
24009 }
24010
24011 SgJavaPackageDeclaration *package_declaration = isSgJavaPackageDeclaration(package_symbol -> get_declaration() -> get_definingDeclaration());
24012 ROSE_ASSERT(package_declaration);
24013 package_definition = package_declaration -> get_definition();
24014 ROSE_ASSERT(package_definition);
24015 scope = package_definition;
24016
24017 index = n;
24018 }
24019
24020 return package_definition;
24021}
24022
24023
24027SgClassDefinition *SageInterface::findOrInsertJavaPackage(SgProject *project, string package_name, bool create_directory /* = false */) {
24028 SgGlobal *global_scope = project -> get_globalScopeAcrossFiles();
24029 SgClassDefinition *package_definition = findJavaPackage(global_scope, package_name);
24030 if (package_definition == NULL) { // try again after loading the package
24031 preprocessPackage(project, package_name);
24032
24033 //
24034 // If requested, Create the directory associated with this package_name.
24035 //
24036 if (create_directory) {
24037 Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24038 Rose::Frontend::Java::Ecj::createTempNamedDirectoryMethod,
24039 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(package_name.c_str()));
24040 }
24041
24042 package_definition = findJavaPackage(global_scope, package_name);
24043 }
24044
24045 return package_definition;
24046}
24047
24052 ROSE_ASSERT(package_definition);
24053 SgClassSymbol *class_symbol = package_definition -> lookup_class_symbol(class_name);
24054 SgClassDeclaration *class_declaration = (class_symbol == NULL
24055 ? NULL
24056 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24057 if ((! class_declaration) || (! class_declaration -> attributeExists("complete"))) { // class not available in the scope
24058 string qualified_name = package_definition -> get_qualified_name().getString() + "." + class_name;
24059 preprocessImport(project, qualified_name);
24060 class_symbol = package_definition -> lookup_class_symbol(class_name);
24061 }
24062
24063 class_declaration = (class_symbol == NULL
24064 ? NULL
24065 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24066
24067 return class_declaration;
24068}
24069
24070
24074SgClassDeclaration *SageInterface::findOrImportJavaClass(SgProject *project, string package_name, string class_name) {
24075 return findOrImportJavaClass(project, findOrInsertJavaPackage(project, package_name, false), class_name);
24076}
24077
24078
24083 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24084 ROSE_ASSERT(class_declaration);
24085 SgClassDefinition *scope = isSgClassDefinition(class_declaration -> get_scope());
24086 while (scope && (! isSgJavaPackageDeclaration(scope -> get_parent()))) {
24087 class_declaration = isSgClassDeclaration(scope -> get_parent());
24088 ROSE_ASSERT(class_declaration);
24089 scope = isSgClassDefinition(class_declaration -> get_scope());
24090 }
24091
24092 if (! scope) { // a local type !!!
24093 return NULL;
24094 }
24095
24096 string class_name = class_declaration -> get_name().getString();
24097 return findOrImportJavaClass(project, scope, class_name);
24098}
24099
24100
24105 ROSE_ASSERT(class_definition);
24107 ROSE_ASSERT(type_list);
24108 SgArrayType *string_array_type = getUniqueJavaArrayType(Rose::Frontend::Java::StringClassType, 1);
24109 ROSE_ASSERT(string_array_type);
24110 type_list -> append_argument(string_array_type);
24111
24112 // DQ (1/11/2020): Fixing support for C++11 l-value and r-value reference modifiers for member functions.
24113 // SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, 0);
24114 SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, /* mfunc_specifier */ 0);
24115
24116 SgFunctionSymbol *method_symbol = class_definition -> lookup_function_symbol("main", member_function_type);
24117 delete type_list;
24118 return (method_symbol == NULL ? NULL : isSgMemberFunctionDeclaration(method_symbol -> get_declaration()));
24119}
24120
24121
24126 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24127 ROSE_ASSERT(class_declaration);
24128 SgClassDefinition *class_definition = class_declaration -> get_definition();
24129 return findJavaMain(class_definition);
24130}
24131
24132//------------------------------------------------------------------------------
24133#endif // ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
24134//------------------------------------------------------------------------------
24135
24137// Essentially replace variable a with b.
24139{
24140 ROSE_ASSERT (old_sym != NULL);
24141 ROSE_ASSERT (new_sym != NULL);
24142 ROSE_ASSERT (old_sym != new_sym);
24143 ROSE_ASSERT (scope != NULL);
24144
24145 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVarRefExp);
24146 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
24147 {
24148 SgVarRefExp *vRef = isSgVarRefExp(*i);
24149 if (vRef->get_symbol() == old_sym)
24150 vRef->set_symbol(new_sym);
24151 }
24152}
24153
24154
24155// 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.
24160bool
24162 {
24163 bool result = true;
24164
24165 bool includingSelf = false;
24166 SgSourceFile* sourceFile = getEnclosingSourceFile(stmt,includingSelf);
24167
24168 if (sourceFile == NULL)
24169 {
24170 printf ("In SageInterface::statementCanBeTransformed(): sourceFile not found \n");
24171 }
24172
24173 // I think we can assert this!
24174 ROSE_ASSERT(sourceFile != NULL);
24175
24176 if (sourceFile != NULL && sourceFile->get_unparse_tokens() == true && sourceFile->get_unparseHeaderFiles() == true)
24177 {
24178 // Need to look up the source file name, find the SgIncludeFile, and check if statements from this file can be transformed.
24179 // 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.
24180 string source_filename = stmt->getFilenameString();
24181#if 0
24182 printf ("In SageInterface::statementCanBeTransformed(): source_filename = %s \n",source_filename.c_str());
24183 printf (" --- Rose::includeFileMapForUnparsing.size() = %zu \n",Rose::includeFileMapForUnparsing.size());
24184#endif
24185
24186 // DQ (11/5/2019): Using the edg_include_file_map instead (constructed in EDG/ROSE translation).
24187 if (EDG_ROSE_Translation::edg_include_file_map.find(source_filename) != EDG_ROSE_Translation::edg_include_file_map.end())
24188 {
24189 SgIncludeFile* include_file = EDG_ROSE_Translation::edg_include_file_map[source_filename];
24190 ROSE_ASSERT(include_file != NULL);
24191#if 0
24192 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");
24193#endif
24194 if (include_file->get_can_be_supported_using_token_based_unparsing() == false)
24195 {
24196#if 0
24197 printf ("NOTE: Transformations of this statement cannot be supported using the header file unparsing with token unparsing options! \n");
24198#endif
24199 result = false;
24200 }
24201 }
24202 else
24203 {
24204 // DQ (5/13/2021): I think that the default (returing true) will work well.
24205 // This is likely just the original input source file (not a header file).
24206#if 0
24207 printf ("Not found in Rose::includeFileMapForUnparsing: source_filename = %s \n",source_filename.c_str());
24208#endif
24209#if 0
24210 printf ("Exiting as a test! \n");
24211 ROSE_ABORT();
24212#endif
24213 }
24214
24215#if 0
24216 printf ("Error: In statementCanBeTransformed(): this might be an issue! \n");
24217 ROSE_ABORT();
24218#endif
24219 }
24220
24221 return result;
24222 }
24223
24224
24225//Note: this function is no longer used by decl move tool: we use copy and insert instead to support moving to multiple scopes
24228{
24229 ROSE_ASSERT (decl!= NULL);
24230 ROSE_ASSERT (target_scope != NULL);
24231 ROSE_ASSERT (target_scope != decl->get_scope());
24232
24233#if 0 // at this stage, we focus on legal move only, any scope adjustment should be done earlier!
24234 // Special handling for If-Stmt, may need to climb up one level of scope when:
24235 // two bodies of if uses the same variable, but cannot be pushed down into each body.
24236 // If-stmt will be the innermost common scope for the variable.
24237 // But we should not move the declaration to if-stmt. We can only move it to the parent scope of if-stmt.
24238 if (isSgIfStmt (target_scope))
24239 {
24240 target_scope = SageInterface::getEnclosingScope (target_scope, false);
24241 if (target_scope == )
24242 }
24243# endif
24244
24245 // Move the declaration
24246 //TODO: consider another way: copy the declaration, insert the copy, replace varRefExp, and remove (delete) the original declaration
24248
24249 switch (target_scope->variantT())
24250 {
24251 case V_SgBasicBlock:
24252 {
24253 SageInterface::prependStatement (decl, target_scope);
24254 break;
24255 }
24256#if 0 // this check should be done earlier before any side effects can happen
24257 case V_SgIfStmt:
24258 {
24259 // adjust to parent scope of if-stmt
24260 break;
24261 }
24262#endif
24263 case V_SgForStatement:
24264 {
24265 // we move int i; to be for (int i=0; ...);
24266 SgForStatement* stmt = isSgForStatement (target_scope);
24267 ROSE_ASSERT(stmt != NULL);
24268 SgStatementPtrList& stmt_list = stmt->get_init_stmt();
24269 // Try to match a pattern like for (i=0; ...) here
24270 // assuming there is only one assignment like i=0
24271 // We don't yet handle more complex cases
24272 if (stmt_list.size() !=1)
24273 {
24274 cerr<<"Error in moveVariableDeclaration(): only single init statement is handled for SgForStatement now."<<endl;
24275 ROSE_ASSERT (stmt_list.size() ==1);
24276 }
24277 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
24278 ROSE_ASSERT (exp_stmt != NULL);
24279 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
24280 ROSE_ASSERT (assign_op != NULL);
24281
24282 // remove the existing i=0; preserve its right hand operand
24284 stmt_list.clear();
24285 SageInterface::deepDelete (exp_stmt);
24286
24287 // modify the decl's rhs to be the new one
24290 if (init_name->get_initptr() != NULL)
24291 SageInterface::deepDelete (init_name->get_initptr());
24292 init_name->set_initptr(initor);
24293 initor->set_parent(init_name);
24294
24295 stmt_list.insert (stmt_list.begin(), decl );
24296 break;
24297 }
24298
24299 default:
24300 {
24301 cerr<<"Error. Unhandled target scope type:"<<target_scope->class_name()<<endl;
24302 ROSE_ASSERT (false);
24303 }
24304 }
24305
24306 //make sure the symbol is moved also since prependStatement() (in fact fixVariableDeclaration()) does not handle this detail.
24308 ROSE_ASSERT(sym != NULL);
24309 SgScopeStatement* orig_scope = sym->get_scope();
24310 if (orig_scope != target_scope)
24311 {
24312 // SageInterface::fixVariableDeclaration() cannot switch the scope for init name.
24313 // it somehow always reuses previously associated scope.
24315 init_name->set_scope(target_scope);
24316 SgName sname = sym->get_name();
24317 orig_scope->remove_symbol(sym);
24318 target_scope->insert_symbol(sname, sym);
24319 }
24320 // This is difficult since C++ variables have namespaces
24321 // Details are in SageInterface::fixVariableDeclaration()
24322 ROSE_ASSERT (target_scope->symbol_exists(sym));
24323}
24324
24325class SimpleExpressionEvaluator: public AstBottomUpProcessing <struct SageInterface::const_int_expr_t> {
24326 public:
24328 }
24329
24330 struct SageInterface::const_int_expr_t getValueExpressionValue(SgValueExp *valExp) {
24331 struct SageInterface::const_int_expr_t subtreeVal;
24332 subtreeVal.hasValue_ = true;
24333
24334 if (isSgIntVal(valExp)) {
24335 subtreeVal.value_ = isSgIntVal(valExp)->get_value();
24336 } else if (isSgLongIntVal(valExp)) {
24337 subtreeVal.value_ = isSgLongIntVal(valExp)->get_value();
24338 } else if (isSgLongLongIntVal(valExp)) {
24339 subtreeVal.value_ = isSgLongLongIntVal(valExp)->get_value();
24340 } else if (isSgShortVal(valExp)) {
24341 subtreeVal.value_ = isSgShortVal(valExp)->get_value();
24342 } else if (isSgUnsignedIntVal(valExp)) {
24343 subtreeVal.value_ = isSgUnsignedIntVal(valExp)->get_value();
24344 } else if (isSgUnsignedLongVal(valExp)) {
24345 subtreeVal.value_ = isSgUnsignedLongVal(valExp)->get_value();
24346 } else if (isSgUnsignedLongLongIntVal(valExp)) {
24347 subtreeVal.value_ = isSgUnsignedLongLongIntVal(valExp)->get_value();
24348 } else if (isSgUnsignedShortVal(valExp)) {
24349 subtreeVal.value_ = isSgUnsignedShortVal(valExp)->get_value();
24350 }
24351 return subtreeVal;
24352 }
24353
24354 struct SageInterface::const_int_expr_t evaluateVariableReference(SgVarRefExp *vRef) {
24355 if (isSgModifierType(vRef->get_type()) == NULL) {
24357 val.value_ = -1;
24358 val.hasValue_ = false;
24359 return val;
24360 }
24361 if (isSgModifierType(vRef->get_type())->get_typeModifier().get_constVolatileModifier().isConst()) {
24362 // We know that the var value is const, so get the initialized name and evaluate it
24363 SgVariableSymbol *sym = vRef->get_symbol();
24364 SgInitializedName *iName = sym->get_declaration();
24365 SgInitializer *ini = iName->get_initializer();
24366
24367 if (isSgAssignInitializer(ini)) {
24368 SgAssignInitializer *initializer = isSgAssignInitializer(ini);
24369 SgExpression *rhs = initializer->get_operand();
24370 SimpleExpressionEvaluator variableEval;
24371
24372 return variableEval.traverse(rhs);
24373 }
24374 }
24376 val.hasValue_ = false;
24377 val.value_ = -1;
24378 return val;
24379 }
24380
24381 struct SageInterface::const_int_expr_t evaluateSynthesizedAttribute(SgNode *node, SynthesizedAttributesList synList) {
24382 if (isSgExpression(node) != NULL) {
24383 SgValueExp* valueExp = isSgValueExp(node);
24384 if (valueExp != NULL) {
24385 return this->getValueExpressionValue(valueExp);
24386 }
24387
24388 SgVarRefExp* varRefExp = isSgVarRefExp(node);
24389 if (varRefExp != NULL) {
24390 // std::cout << "Hit variable reference expression!" << std::endl;
24391 return evaluateVariableReference(varRefExp);
24392 }
24393 // Early break out for assign initializer // other possibility?
24394 if (isSgAssignInitializer(node)) {
24395 if(synList.at(0).hasValue_){
24396 return synList.at(0);
24397 } else {
24399 val.value_ = -1;
24400 val.hasValue_ = false;
24401 return val;
24402 }
24403 }
24404 struct SageInterface::const_int_expr_t evaluatedValue;
24405 evaluatedValue.hasValue_ = false;
24406 evaluatedValue.value_ = -1;
24407#if 0
24408 if(synList.size() != 2){
24409 for(SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it){
24410 std::cout << "Node: " << node->unparseToString() << "\n" << (*it).value_ << std::endl;
24411 std::cout << "Parent: " << node->get_parent()->unparseToString() << std::endl;
24412 std::cout << "Parent, Parent: " << node->get_parent()->get_parent()->unparseToString() << std::endl;
24413 }
24414 }
24415#endif
24416 for (SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it) {
24417 if((*it).hasValue_){
24418 if (isSgAddOp(node)) {
24419 assert(synList.size() == 2);
24420 evaluatedValue.value_ = synList[0].value_ + synList[1].value_ ;
24421 evaluatedValue.hasValue_ = true;
24422 } else if (isSgSubtractOp(node)) {
24423 assert(synList.size() == 2);
24424 evaluatedValue.value_ = synList[0].value_ - synList[1].value_ ;
24425 evaluatedValue.hasValue_ = true;
24426 } else if (isSgMultiplyOp(node)) {
24427 assert(synList.size() == 2);
24428 evaluatedValue.value_ = synList[0].value_ * synList[1].value_ ;
24429 evaluatedValue.hasValue_ = true;
24430 } else if (isSgDivideOp(node)) {
24431 assert(synList.size() == 2);
24432 evaluatedValue.value_ = synList[0].value_ / synList[1].value_ ;
24433 evaluatedValue.hasValue_ = true;
24434 } else if (isSgModOp(node)) {
24435 assert(synList.size() == 2);
24436 evaluatedValue.value_ = synList[0].value_ % synList[1].value_ ;
24437 evaluatedValue.hasValue_ = true;
24438 }
24439 } else {
24440 std::cerr << "Expression is not evaluatable" << std::endl;
24441 evaluatedValue.hasValue_ = false;
24442 evaluatedValue.value_ = -1;
24443 return evaluatedValue;
24444 }
24445 }
24446 evaluatedValue.hasValue_ = true;
24447 return evaluatedValue;
24448 }
24449 struct SageInterface::const_int_expr_t evaluatedValue;
24450 evaluatedValue.hasValue_ = false;
24451 evaluatedValue.value_ = -1;
24452 return evaluatedValue;
24453 }
24454};
24455
24459 return eval.traverse(expr);
24460}
24461
24462bool
24464
24465 class TypeEquivalenceChecker {
24466 public:
24467 TypeEquivalenceChecker(bool profile, bool useSemanticEquivalence)
24468 : profile_(profile), useSemanticEquivalence_(useSemanticEquivalence),
24469 namedType_(0), pointerType_(0), arrayType_(0), functionType_(0)
24470 {
24471 }
24472
24473 SgNode * getBasetypeIfApplicable(SgNode *t){
24474 SgNode * node = t;
24475 if (isSgTypedefType(t)) {
24476// std::cout << "This is a typedef nodeT1. We strip everything away and compare the hidden types." << std::endl;
24477 node = isSgTypedefType(t)->stripType(SgType::STRIP_TYPEDEF_TYPE);
24478 }
24479 if(useSemanticEquivalence_){
24480 if(isSgModifierType(t)){
24481 SgModifierType *modType = isSgModifierType(t);
24482 ROSE_ASSERT(modType != NULL);
24483 // We need to check for Volatile/Restrict types. These are modelled as ModifierTypes, but are equal (in some cases)
24484 // volatile seems to make no difference for basic (built in) types like int, bool etc. But it has an impact on types
24485 // like classes
24486 // restrict seems to have no impact on the type itself.
24487 if(SageInterface::isVolatileType(modType)){
24488 // handle volatile case
24489 std::cout << "Hit volatile type, stripping of modifier type" << std::endl;
24490 node = modType->get_base_type();
24491 }
24492 if(SageInterface::isRestrictType(modType)){
24493 // handle restrict case
24494 std::cout << "Hit restrict type, stripping of modifier type" << std::endl;
24495 node = modType->get_base_type();
24496 }
24497 }
24498 }
24499 ROSE_ASSERT(node != NULL);
24500 return node;
24501}
24502
24503bool typesAreEqual(SgType *t1, SgType *t2) {
24504 bool equal = false;
24505 if(t1 == NULL || t2 == NULL){
24506 std::string wasNull;
24507 if(t1 == NULL){
24508 wasNull = "t1";
24509 } else {
24510 wasNull = "t2";
24511 }
24512 std::cerr << "ERROR: " << wasNull << " was NULL" << std::endl;
24513 return equal;
24514 }
24515 // if both pointers point to same location the types MUST be equal!
24516 if(t1 == t2){
24517// std::cout << "Pointers are equal, returning true" << std::endl;
24518 return true;
24519 }
24520#ifndef USE_CMAKEx
24521 RoseAst subT1(t1);
24522 RoseAst subT2(t2);
24523
24524 for (RoseAst::iterator i = subT1.begin(), j = subT2.begin();
24525 i != subT1.end() && j != subT2.end(); ++i, ++j) {
24526 SgNode *nodeT1 = *i;
24527 SgNode *nodeT2 = *j;
24528
24529// std::cout << "nodeT1: " << nodeT1->class_name() << " nodeT2: " << nodeT2->class_name() << std::endl;
24530 nodeT1 = getBasetypeIfApplicable(nodeT1);
24531 nodeT2 = getBasetypeIfApplicable(nodeT2);
24532
24533 if (nodeT1->variantT() == nodeT2->variantT()) {
24534// std::cout << "variantT is the same" << std::endl;
24535 if(isSgModifierType(nodeT1)){
24536 // we need to check whether the modifier is the same or not
24537 SgTypeModifier modT1 = isSgModifierType(nodeT1)->get_typeModifier();
24538 SgTypeModifier modT2 = isSgModifierType(nodeT2)->get_typeModifier();
24539 if(modT1.get_constVolatileModifier().isConst() != modT2.get_constVolatileModifier().isConst()){
24540 return false;
24541 }
24542 if(modT1.get_constVolatileModifier().isVolatile() != modT2.get_constVolatileModifier().isVolatile()){
24543 return false;
24544 }
24545 } else if (isSgNamedType(nodeT1)) { // Two different names -> Must be two different things
24546 if (profile_) {
24547 namedType_++;
24548 }
24549 i.skipChildrenOnForward();
24550 j.skipChildrenOnForward();
24551 SgNamedType *c1 = isSgNamedType(nodeT1);
24552 SgNamedType *c2 = isSgNamedType(nodeT2);
24553
24554 // XXX A function to check whether a named type is anonymous or not would speed
24555 // up this check, since we could get rid of this string compare.
24556 if(!c1->get_autonomous_declaration()){
24557 return false;
24558 }
24559 if (!c2->get_autonomous_declaration()){
24560 return false;
24561 }
24562 if (c1->get_qualified_name() == c2->get_qualified_name()) {
24563 return true;
24564 } else {
24565 return false;
24566 }
24567
24568 } else if (isSgPointerType(nodeT1)) {
24569 if (profile_) {
24570 pointerType_++;
24571 }
24572 SgPointerType *t1 = isSgPointerType(nodeT1);
24573 SgPointerType *t2 = isSgPointerType(nodeT2);
24574
24575 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24576
24577 } else if(isSgReferenceType(nodeT1)){
24578 SgReferenceType *t1 = isSgReferenceType(nodeT1);
24579 SgReferenceType *t2 = isSgReferenceType(nodeT2);
24580
24581 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24582 } else if (isSgArrayType(nodeT1)) {
24583 if (profile_) {
24584 arrayType_++;
24585 }
24586 SgArrayType *a1 = isSgArrayType(nodeT1);
24587 SgArrayType *a2 = isSgArrayType(nodeT2);
24588
24589 bool arrayBaseIsEqual = typesAreEqual(a1->get_base_type(), a2->get_base_type());
24590
24593 bool arrayIndexExpressionIsEquivalent = false;
24594 if(t1Index.hasValue_ && t2Index.hasValue_){
24595 if(t1Index.value_ == t2Index.value_){
24596 arrayIndexExpressionIsEquivalent = true;
24597 }
24598 }
24599 bool arraysAreEqual = (arrayBaseIsEqual && arrayIndexExpressionIsEquivalent);
24600 return arraysAreEqual;
24601 } else if (isSgFunctionType(nodeT1)) {
24602 if(profile_) {
24603 functionType_++;
24604 }
24605 SgFunctionType *funcTypeA = isSgFunctionType(nodeT1);
24606 SgFunctionType *funcTypeB = isSgFunctionType(nodeT2);
24607// std::cout << "Inside SgFunctionType" << std::endl;
24608// assert(funcTypeA != funcTypeB);
24609 if(typesAreEqual(funcTypeA->get_return_type(), funcTypeB->get_return_type())) {
24610 // If functions don't have the same number of arguments, they are not type-equal
24611 if(funcTypeA->get_arguments().size() != funcTypeB->get_arguments().size()) {
24612 return false;
24613 }
24614 // This should always be the same as the if before...
24615 if(funcTypeA->get_argument_list()->get_arguments().size() != funcTypeB->get_argument_list()->get_arguments().size()){
24616 return false;
24617 }
24618
24619 for(SgTypePtrList::const_iterator ii = funcTypeA->get_arguments().begin(),
24620 jj = funcTypeB->get_arguments().begin();
24621 ii != funcTypeA->get_arguments().end() &&
24622 jj != funcTypeB->get_arguments().end();
24623 ++ii, ++jj) {
24624// std::cout << (*ii)->class_name() << " " << (*jj)->class_name() << std::endl;
24625 // For all argument types check whether they are equal
24626 if(!typesAreEqual((*ii), (*jj))) {
24627 return false;
24628 }
24629 }
24630 return true;
24631 }
24632 return false;
24633 } else {
24634 // We don't have a named type, pointer type or array type, so they are equal
24635 // This is for the primitive type - case
24636 return true;
24637 }
24638 } else {
24639 // In this case the types are not equal, since its variantT is not equal.
24640 return false;
24641 }
24642 }
24643 // this should be unreachable code...
24644 return equal;
24645#else
24646 std::cerr << "This feature for now is available with autotools only!" << std::endl;
24647 ROSE_ABORT();
24648#endif
24649}
24650
24651int getNamedTypeCount() {
24652 return namedType_;
24653}
24654
24655int getPointerTypeCount() {
24656 return pointerType_;
24657}
24658
24659int getArrayTypeCount() {
24660 return arrayType_;
24661}
24662
24663int getFunctionTypeCount() {
24664 return functionType_;
24665}
24666 private:
24667// SgNode * getBasetypeIfApplicable(SgNode *t);
24668 bool profile_, useSemanticEquivalence_;
24669 int namedType_, pointerType_, arrayType_, functionType_;
24670};
24671
24672TypeEquivalenceChecker tec(false, false);
24673return tec.typesAreEqual(typeA, typeB);
24674}
24675
24676
24677std::set<SgStatement*>
24679 {
24680 // DQ (6/11/2015): This reports the statements that are marked as transformed.
24681 // It is useful for debugging the token-based unparsing.
24682
24683 class StatementTraversal : public AstSimpleProcessing
24684 {
24685 public:
24686 StatementTraversal() : count (0) {}
24687 void visit (SgNode* node)
24688 {
24689 SgStatement* statement = isSgStatement(node);
24690 if (statement != nullptr && statement->isTransformation() == true)
24691 {
24692 returnset.insert(statement);
24693 count++;
24694 }
24695 }
24696
24697 int count; // running total of statements found marked as transformations in the input AST
24698 std::set<SgStatement*> returnset;
24699 };
24700
24701 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24702 StatementTraversal traversal;
24703 traversal.traverse(node, preorder);
24704
24705 return traversal.returnset;
24706 }
24707
24708std::set<SgStatement*>
24710 {
24711 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24712 // It is useful for debugging the token-based unparsing.
24713
24714#if 1
24715 printf ("In collectModifiedStatements(): node = %p = %s \n",node,node->class_name().c_str());
24716#endif
24717
24718 class StatementTraversal : public AstSimpleProcessing
24719 {
24720 public:
24721 StatementTraversal() : count (0) {}
24722 void visit (SgNode* node)
24723 {
24724 SgStatement* statement = isSgStatement(node);
24725 if (statement != NULL && statement->get_isModified() == true)
24726 {
24727 returnset.insert(statement);
24728 count++;
24729 }
24730 }
24731
24732 int count; // running total of statements found marked as transformations in the input AST
24733 std::set<SgStatement*> returnset;
24734 };
24735
24736 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24737 StatementTraversal traversal;
24738 traversal.traverse(node, preorder);
24739
24740 return traversal.returnset;
24741 }
24742
24743
24744void
24746 {
24747 // DQ (12/2/2019): This reports the file id values of all located nodes in the AST subtree represented by the input node.
24748
24749#if 0
24750 printf ("In outputFileIds(): node = %p = %s \n",node,node->class_name().c_str());
24751#endif
24752
24753 class LocatedNodeTraversal : public AstSimpleProcessing
24754 {
24755 public:
24756 LocatedNodeTraversal() {}
24757 void visit (SgNode* node)
24758 {
24759 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24760 if (locatedNode != NULL)
24761 {
24762#if 0
24763 printf ("In outputFileIds(): isModified() == %s: locatedNode = %p = %s \n",locatedNode->get_isModified() ? "true" : "false",locatedNode,locatedNode->class_name().c_str());
24764 printf (" --- file id = %d physical_file_id = %d \n",node->get_file_info()->get_file_id(),node->get_file_info()->get_physical_file_id());
24765#endif
24766 }
24767 else
24768 {
24769 SgInitializedName* initializedName = isSgInitializedName(node);
24770 if (initializedName != NULL)
24771 {
24772 printf ("In outputFileIds(): isModified() == %s: initializedName = %p = %s \n",initializedName->get_isModified() ? "true" : "false",initializedName,initializedName->class_name().c_str());
24773 printf (" --- file id = %d physical_file_id = %d \n",initializedName->get_file_info()->get_file_id(),initializedName->get_file_info()->get_physical_file_id());
24774 }
24775 }
24776 }
24777 };
24778
24779 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24780 LocatedNodeTraversal traversal;
24781 traversal.traverse(node, preorder);
24782
24783#if 0
24784 printf ("Exiting as a test! \n");
24785 ROSE_ABORT();
24786#endif
24787 }
24788
24789
24790std::set<SgLocatedNode*>
24792 {
24793 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24794 // It is useful for debugging the token-based unparsing.
24795
24796#if 0
24797 printf ("In collectModifiedLocatedNodes(): node = %p = %s \n",node,node->class_name().c_str());
24798#endif
24799
24800 class LocatedNodeTraversal : public AstSimpleProcessing
24801 {
24802 public:
24803 LocatedNodeTraversal() : count (0) {}
24804 void visit (SgNode* node)
24805 {
24806 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24807 if (locatedNode != NULL && locatedNode->get_isModified() == true)
24808 {
24809#if 0
24810 printf ("In collectModifiedLocatedNodes(): isModified() == true: locatedNode = %p = %s \n",locatedNode,locatedNode->class_name().c_str());
24811#endif
24812 returnset.insert(locatedNode);
24813 count++;
24814 }
24815 }
24816
24817 int count; // running total of statements found marked as transformations in the input AST
24818 std::set<SgLocatedNode*> returnset;
24819 };
24820
24821 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24822 LocatedNodeTraversal traversal;
24823 traversal.traverse(node, preorder);
24824
24825 return traversal.returnset;
24826 }
24827
24828
24830void
24831SageInterface::resetModifiedLocatedNodes(const std::set<SgLocatedNode*> & modifiedNodeSet)
24832 {
24833 // DQ (6/5/2019): Use a previously constructed set to reset the IR nodes to be marked as isModified.
24834
24835#if 0
24836 printf ("In resetModifiedLocatedNodes(): modifiedNodeSet.size() = %zu \n",modifiedNodeSet.size());
24837#endif
24838
24839 std::set<SgLocatedNode*>::const_iterator i = modifiedNodeSet.begin();
24840 while (i != modifiedNodeSet.end())
24841 {
24842 SgLocatedNode* node = *i;
24843#if 0
24844 printf ("Marking node = %p = %s as modified \n",node,node->class_name().c_str());
24845#endif
24846 node->set_isModified(true);
24847
24848 i++;
24849 }
24850 }
24851
24852
24853void
24855 {
24856 // DQ (10/23/2018): This reports the nodes in the AST that are marked as modified (isModified flag).
24857 // It is useful for debugging the token-based unparsing.
24858
24859 printf ("\n\n##################################################### \n");
24860 printf ("Report on modified statements: label = %s \n",label.c_str());
24861
24862 SgSourceFile* sourceFile = isSgSourceFile(node);
24863 if (sourceFile != NULL)
24864 {
24865 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24866 }
24867 else
24868 {
24869 SgGlobal* globalScope = isSgGlobal(node);
24870 if (globalScope != NULL)
24871 {
24872 sourceFile = isSgSourceFile(globalScope->get_parent());
24873 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24874 }
24875 }
24876
24877 ROSE_ASSERT(node != NULL);
24878 std::set<SgStatement*> collection = collectModifiedStatements(node);
24879
24880#if 0
24881 printf ("In reportModifiedStatements(): collection.size() = %zu \n",collection.size());
24882#endif
24883
24884 std::set<SgStatement*>::iterator i = collection.begin();
24885 while (i != collection.end())
24886 {
24887 // DQ (10/9/2019): Adding filename to debug output.
24888 string filename = (*i)->get_file_info()->get_filename();
24889
24890 // DQ (10/14/2019): Get the best name possible.
24891 if (filename == "transformation")
24892 {
24893#if 0
24894 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24895#endif
24896 // filename = (*i)->get_file_info()->get_physical_filename();
24897 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24898 if (sourceFile != NULL)
24899 {
24900 filename = sourceFile->getFileName();
24901 }
24902 }
24903
24904 printf (" --- filename = %s modified statement = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24905
24906 i++;
24907 }
24908
24909#if 1
24910 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
24911 // output spew else the message output at the top of this function will scroll off the screen.
24912 printf ("########################################################## \n");
24913 printf ("reportModifiedStatements(): Called using label = %s \n",label.c_str());
24914#endif
24915 printf ("########################################################## \n\n\n");
24916
24917#if 0
24918 printf ("Exiting as a test! \n");
24919 ROSE_ASSERT(false);
24920#endif
24921 }
24922
24923
24924
24925void
24927 {
24928 // DQ (6/21/2021): This reports the nodes in the AST that are marked as modified (isModified flag).
24929 // It is useful for debugging the token-based unparsing.
24930
24931 printf ("\n\n##################################################### \n");
24932 printf ("Report on modified locatedNodes: label = %s \n",label.c_str());
24933
24934 SgSourceFile* sourceFile = isSgSourceFile(node);
24935 if (sourceFile != NULL)
24936 {
24937 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24938 }
24939 else
24940 {
24941 SgGlobal* globalScope = isSgGlobal(node);
24942 if (globalScope != NULL)
24943 {
24944 sourceFile = isSgSourceFile(globalScope->get_parent());
24945 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24946 }
24947 }
24948
24949 ROSE_ASSERT(node != NULL);
24950 std::set<SgLocatedNode*> collection = collectModifiedLocatedNodes(node);
24951
24952#if 0
24953 printf ("In reportModifiedLocatedNode(): collection.size() = %zu \n",collection.size());
24954#endif
24955
24956 std::set<SgLocatedNode*>::iterator i = collection.begin();
24957 while (i != collection.end())
24958 {
24959 // DQ (10/9/2019): Adding filename to debug output.
24960 string filename = (*i)->get_file_info()->get_filename();
24961
24962 // DQ (10/14/2019): Get the best name possible.
24963 if (filename == "transformation")
24964 {
24965#if 0
24966 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24967#endif
24968 // filename = (*i)->get_file_info()->get_physical_filename();
24969 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24970 if (sourceFile != NULL)
24971 {
24972 filename = sourceFile->getFileName();
24973 }
24974 }
24975
24976 printf (" --- filename = %s modified locatedNode = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24977
24978 i++;
24979 }
24980
24981#if 1
24982 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
24983 // output spew else the message output at the top of this function will scroll off the screen.
24984 printf ("########################################################## \n");
24985 printf ("reportModifiedLocatedNodes(): Called using label = %s \n",label.c_str());
24986#endif
24987 printf ("########################################################## \n\n\n");
24988
24989#if 0
24990 printf ("Exiting as a test! \n");
24991 ROSE_ASSERT(false);
24992#endif
24993 }
24994
24995
24996
24997
24998// DQ (3/22/2019): Translate CPP directives from attached preprocessor information to CPP Directive Declaration IR nodes.
24999
25000void
25002 {
25003 // Debugging function to print out comments in the statements (added by DQ)
25004
25005 ROSE_ASSERT(locatedNode != NULL);
25006 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
25007
25008#if 0
25009 curprint ("/* Inside of printOutComments() */");
25010#endif
25011
25012 if (comments != NULL)
25013 {
25014#if 0
25015 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25016 curprint ("/* Inside of printOutComments(): comments != NULL */");
25017#endif
25018
25019 AttachedPreprocessingInfoType::iterator i;
25020 for (i = comments->begin(); i != comments->end(); i++)
25021 {
25022 ROSE_ASSERT ( (*i) != NULL );
25023 printf (" Attached Comment (relativePosition=%s): %s \n",
25024 // DQ (2/11/2021): Fixed to report correct relative locations.
25025 // ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25026 PreprocessingInfo::relativePositionName((*i)->getRelativePosition()).c_str(),
25027 (*i)->getString().c_str());
25028 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
25029 // curprint (string("/* Inside of printOutComments(): comments = ") + (*i)->getString() + " */");
25030
25031#if 0
25032 (*i)->get_file_info()->display("comment/directive location");
25033#endif
25034 }
25035 }
25036 else
25037 {
25038#if 0
25039 printf ("In SageInterface::printOutComments(): No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25040#endif
25041 }
25042 }
25043
25044
25045
25046bool
25048 {
25049 bool returnValue = false;
25050
25051 ROSE_ASSERT(currentPreprocessingInfo != NULL);
25052
25053 PreprocessingInfo::DirectiveType directive = currentPreprocessingInfo->getTypeOfDirective();
25054
25055 if (directive == PreprocessingInfo::C_StyleComment ||
25056 directive == PreprocessingInfo::CplusplusStyleComment ||
25057 directive == PreprocessingInfo::FortranStyleComment ||
25058 directive == PreprocessingInfo::CpreprocessorBlankLine ||
25059 directive == PreprocessingInfo::ClinkageSpecificationStart ||
25060 directive == PreprocessingInfo::ClinkageSpecificationEnd)
25061 {
25062 returnValue = true;
25063 }
25064
25065 return returnValue;
25066 }
25067
25068std::vector<SgC_PreprocessorDirectiveStatement*>
25070 {
25071 std::vector<SgC_PreprocessorDirectiveStatement*> directiveList;
25072
25073 // Find existing first and last header.
25074 AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo();
25075
25076 if (comments != nullptr)
25077 {
25078 AttachedPreprocessingInfoType::iterator i; // , firsti, lasti;
25079 for (i = comments->begin (); i != comments->end(); i++)
25080 {
25081 if (skipTranslateToUseCppDeclaration(*i) == true)
25082 {
25083 // 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).
25084 }
25085 else
25086 {
25087 SgC_PreprocessorDirectiveStatement* directive = SgC_PreprocessorDirectiveStatement::createDirective(*i);
25088 ROSE_ASSERT(directive != NULL);
25089 directiveList.push_back(directive);
25090 }
25091
25092 printf ("directiveList.size() = %zu \n",directiveList.size());
25093 }
25094 }
25095
25096 return directiveList;
25097 }
25098
25099
25100void
25102 {
25103 bool declarationsOnly = scope->containsOnlyDeclarations();
25104
25105 printf ("In translateScopeToUseCppDeclarations(): declarationsOnly = %s scope = %p = %s \n",declarationsOnly ? "true" : "false",scope,scope->class_name().c_str());
25106
25107 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> > directiveMap;
25108
25109 if (declarationsOnly == true)
25110 {
25111 // These are scopes such as global scope, namespace definitions, class definitions, etc.
25112 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
25113 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
25114 while (i != declarationList.end())
25115 {
25116 SgDeclarationStatement* declaration = *i;
25117 ROSE_ASSERT(declaration != NULL);
25118
25119 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(declaration,scope);
25120
25121 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25122
25123 if (attachDirectives.empty() == false)
25124 {
25125 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(declaration,attachDirectives));
25126 }
25127
25128 i++;
25129 }
25130
25131 // Need to save the list of things that will be added so we can avoid iterator invalidation.
25132 }
25133 else
25134 {
25135 // These are scopes such as SgBasicBlock (which can contain non-declaration statements.
25136 SgStatementPtrList & statementList = scope->getStatementList();
25137 SgStatementPtrList::iterator i = statementList.begin();
25138 while (i != statementList.end())
25139 {
25140 SgStatement* statement = *i;
25141 ROSE_ASSERT(statement != NULL);
25142
25143 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(statement,scope);
25144
25145 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25146
25147 if (attachDirectives.empty() == false)
25148 {
25149 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(statement,attachDirectives));
25150 }
25151
25152 i++;
25153 }
25154 }
25155
25156 printf ("directiveMap.size() = %zu \n",directiveMap.size());
25157
25158 printf ("Processing the directiveMap: \n");
25159 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >::iterator i = directiveMap.begin();
25160 while (i != directiveMap.end())
25161 {
25162 SgStatement* statement = i->first;
25163 std::vector<SgC_PreprocessorDirectiveStatement*> directives = i->second;
25164
25165 printf ("statement = %p = %s \n",statement,statement->class_name().c_str());
25166 printf ("directives.size() = %zu \n",directives.size());
25167 // std::vector<SgC_PreprocessorDirectiveStatement*>::reverse_iterator j = directives.begin();
25168 std::vector<SgC_PreprocessorDirectiveStatement*>::iterator j = directives.begin();
25169 while (j != directives.end())
25170 {
25171 scope->insert_statement(statement,*j);
25172
25173 j++;
25174 }
25175
25176 // Remove the directives there were attached to the statement.
25177 AttachedPreprocessingInfoType *comments = statement->getAttachedPreprocessingInfo();
25178 ROSE_ASSERT(comments != NULL);
25179
25180 AttachedPreprocessingInfoType deleteList;
25181 // std::vector<PreprocessingInfo*> deleteList;
25182
25183 // comments->erase();
25184 // statement->setAttachedPreprocessingInfo(NULL);
25185 AttachedPreprocessingInfoType::iterator k;
25186 for (k = comments->begin(); k != comments->end(); k++)
25187 {
25188#if 1
25189 ROSE_ASSERT ( (*k) != NULL );
25190 printf (" Attached Comment (relativePosition=%s): %s\n",
25191 ((*k)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25192 (*k)->getString().c_str());
25193 printf ("translateScopeToUseCppDeclarations(): Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*k)->getNumberOfLines(),(*k)->getColumnNumberOfEndOfString());
25194#endif
25195
25196 // We only want to process the CPP directives (skipping comments and a few othr kinds of obscure directives).
25197 if (skipTranslateToUseCppDeclaration(*k) == true)
25198 {
25199 // 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).
25200 printf ("Do NOT delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25201 }
25202 else
25203 {
25204 printf ("DO delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25205
25206 deleteList.push_back(*k);
25207 // delete *k;
25208 // *k = NULL;
25209 }
25210 }
25211
25212 printf ("Iterate over the deleteList: deleteList.size() = %zu comments->size() = %zu \n",deleteList.size(),comments->size());
25213 AttachedPreprocessingInfoType::iterator m = deleteList.begin();
25214 while (m != deleteList.end())
25215 {
25216 // comments->erase(m);
25217 // std::remove(comments->begin(), comments->end(), *m);
25218 comments->erase(std::remove(comments->begin(), comments->end(), *m), comments->end());
25219
25220 printf (" --- comments->size() = %zu \n",comments->size());
25221
25222 m++;
25223 }
25224
25225 // comments->clear();
25226 // delete comments; // statement->getAttachedPreprocessingInfoPtr();
25227 // statement->set_attachedPreprocessingInfoPtr(NULL);
25228
25229 i++;
25230 }
25231
25232 printf ("Leaving translateScopeToUseCppDeclarations(): scope = %p = %s \n",scope,scope->class_name().c_str());
25233 }
25234
25235
25236void
25238 {
25239 class CppTranslationTraversal : public AstSimpleProcessing
25240 {
25241 public:
25242 CppTranslationTraversal() {}
25243 void visit (SgNode* node)
25244 {
25245 printf ("In CppTranslationTraversal::visit(): node = %p = %s \n",node,node->class_name().c_str());
25246
25247 SgScopeStatement* scope = isSgScopeStatement(node);
25248 SgGlobal* globalScope = isSgGlobal(scope);
25249 if (globalScope != NULL)
25250 {
25251 printf ("In CppTranslationTraversal::visit(): processing scope = %p = %s \n",scope,scope->class_name().c_str());
25253 }
25254 else
25255 {
25256 if (scope != NULL)
25257 {
25258 printf ("In SageInterface::translateToUseCppDeclarations(): Currently skipping all but global scope! \n");
25259 }
25260 }
25261 }
25262 };
25263
25264 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
25265 CppTranslationTraversal traversal;
25266
25267 printf ("In translateToUseCppDeclarations(): Calling traversal.traverse() \n");
25268
25269 // We might want to do this traversla POSTORDER since we are transforming the AST at each scope.
25270 // traversal.traverse(n, preorder);
25271 traversal.traverse(n, postorder);
25272
25273 printf ("Leaving translateToUseCppDeclarations(): DONE: Calling traversal.traverse() \n");
25274 }
25275
25277{
25278 // print current level's info
25279 if (!n) return;
25280 cout<<"--------------"<<endl;
25281 cout<<n<<":"<<n->class_name()<< endl;
25282 if (SgLocatedNode * lnode = isSgLocatedNode(n))
25283 {
25284 cout<<"file info:\t ";
25285 lnode->get_file_info()->display();
25286 cout<<"\n unparseToString:\t ";
25287 lnode->unparseToString();
25288 }
25289
25290 // track back to its parent
25292}
25293// forward declaration is needed here,
25294//static void serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel);
25295
25296#if 0 // made it into a template function to handle various ptr lists in AST
25297// A special node in the AST text dump
25298static void serialize(SgTemplateArgumentPtrList& plist, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25299{
25300 out<<prefix;
25301 out<< (hasRemaining?"|---": "|___");
25302
25303// out<<"+"<<edgeLabel<<"+>";
25304 out<<" "<<edgeLabel<<" ->";
25305 // print address
25306 out<<"@"<<&plist<<" "<< "SgTemplateArgumentPtrList ";
25307
25308 out<<endl;
25309
25310 int last_non_null_child_idx =-1;
25311 for (int i = (int) (plist.size())-1; i>=0; i--)
25312 {
25313 if (plist[i])
25314 {
25315 last_non_null_child_idx = i;
25316 break;
25317 }
25318 }
25319
25320 for (size_t i=0; i< plist.size(); i++ )
25321 {
25322 bool n_hasRemaining=false;
25323#if 0
25324 if (i+1 < plist.size())
25325 n_hasRemaining=true;
25326#else
25327 if ((int)i< last_non_null_child_idx) n_hasRemaining = true;
25328#endif
25329 string suffix= hasRemaining? "| " : " ";
25330 string n_prefix = prefix+suffix;
25331 string n_edge_label="";
25332 if (plist[i])
25333 serialize (plist[i], n_prefix, n_hasRemaining, out,n_edge_label);
25334 }
25335}
25336#endif
25337
25338// print essential information from any AST node
25339// hasRemaining if this node has a sibling node to be visited next.
25340void SageInterface::serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25341{
25342 // there may be NULL children!!
25343 //if (!node) return;
25344
25345 out<<prefix;
25346 out<< (hasRemaining?"|---": "|___");
25347
25348 out<<" "<<edgeLabel<<" ->";
25349 if (!node)
25350 {
25351 out<<" NULL "<<endl;
25352 return;
25353 }
25354
25355 // print address
25356 out<<"@"<<node<<" "<< node->class_name()<<" ";
25357
25358 //optionally file info
25359 if (SgLocatedNode* lnode= isSgLocatedNode(node))
25360 {
25361 //Rose::StringUtility::stripPathFromFileName()
25362 out<< lnode->get_file_info()->get_filename() <<" "<<lnode->get_file_info()->get_line()<<":"<<lnode->get_file_info()->get_col();
25363 // also preprocessing info. attached.
25364 AttachedPreprocessingInfoType *comments =
25365 lnode->getAttachedPreprocessingInfo ();
25366
25367 if (comments != NULL)
25368 {
25369// printf ("Found an IR node with preprocessing Info attached:\n");
25370 out<<" AttachedPreprocessingInfoType@"<<comments;
25371 int counter = 0;
25372 AttachedPreprocessingInfoType::iterator i;
25373 out <<"{";
25374 for (i = comments->begin (); i != comments->end (); i++)
25375 {
25376 if (i!=comments->begin ())
25377 out<<endl;
25378 out<<"<id=";
25379 out<<counter++<<" ";
25380 // printf("-------------PreprocessingInfo #%d ----------- : \n",counter++);
25381 // printf("classification = %s:\n String format = %s\n",
25382 // PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str (),
25383 // (*i)->getString ().c_str ());
25384 if (*i==NULL)
25385 out<<" NULL="; // The AST may be in the middle of transformation, with NULL comments attached.
25386 else
25387 {
25388 out<<*i<<" classification="<<PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str ();
25389 out<<" string="<<(*i)->getString ().c_str ();
25390 out<<" relative pos=" ; // << (*i)->getRelativePosition ();
25391#if 1
25392 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
25393 out<<"inside";
25394 else if ((*i)->getRelativePosition () == PreprocessingInfo::before)
25395 out<<"before";
25396 else
25397 out<<"after";
25398#endif
25399 }
25400 out<<">";
25401 }
25402 out <<"}";
25403 }
25404 }
25405
25406 if (SgDeclarationStatement* v= isSgDeclarationStatement(node))
25407 {
25408 out<<" first nondefining decl@"<< v->get_firstNondefiningDeclaration();
25409 out<<" defining decl@"<< v->get_definingDeclaration();
25410 }
25411
25412 if (SgEnumVal* f = isSgEnumVal(node) )
25413 out<<" value="<< f->get_value() <<" declaration="<<f->get_declaration() << " name="<< f->get_name().getString();
25414 // optionally qualified name
25415
25416 if (SgFunctionDeclaration* f = isSgFunctionDeclaration(node) )
25417 out<<" "<< f->get_qualified_name();
25418
25419 if (SgAdaFunctionRenamingDecl* f = isSgAdaFunctionRenamingDecl(node) )
25420 out<<" renamed_function "<< f->get_renamed_function();
25421
25422 if (SgAdaRenamingDecl* f = isSgAdaRenamingDecl(node) )
25423 out<<" name="<< f->get_name() << " renamed decl "<<f->get_renamed() ;
25424
25425 if (SgClassDeclaration* f = isSgClassDeclaration(node) )
25426 out<<" "<< f->get_qualified_name();
25427
25428 if (SgTypedefDeclaration* f = isSgTypedefDeclaration(node) )
25429 out<<" "<< f->get_qualified_name();
25430
25431 if (SgAdaPackageSpecDecl * f = isSgAdaPackageSpecDecl(node) )
25432 out<<" "<< f->get_qualified_name();
25433
25434 if (SgAdaEnumRepresentationClause* f = isSgAdaEnumRepresentationClause(node) )
25435 out<<" enumType="<< f->get_enumType();
25436
25437 if (SgAdaAccessType* v = isSgAdaAccessType(node) )
25438 {
25439 // out<<" "<< v->get_qualified_name();
25440 //out<<" "<< v->get_name();
25441 // PP (2/18/22) updated to reflect properties in AdaAccessType
25442 //~ out<<" is_object_type"<< v->get_is_object_type();
25443 out<<" is_general_access"<< v->get_is_general_access();
25444 //~ out<<" is_constant:"<< v->get_is_constant();
25445 //~ out<<" is_protected:"<< v->get_is_protected ();
25446 out<<" is_anonymous:"<< v->get_is_anonymous ();
25447 }
25448
25449 if (SgAdaSubroutineType* v = isSgAdaSubroutineType(node) )
25450 {
25451 out<<" is_protected"<< v->get_is_protected();
25452 }
25453
25454 if (SgInitializedName * v = isSgInitializedName(node) )
25455 {
25456 out<<" "<< v->get_qualified_name();
25457 out<<" type@"<< v->get_type();
25458 out<<" initializer@"<< v->get_initializer();
25459 out<<" scope@"<< v->get_scope();
25460// type_set.insert (v->get_type());
25461 }
25462
25463 // associated class, function and variable declarations
25464 if (SgTemplateInstantiationDecl* f = isSgTemplateInstantiationDecl(node) )
25465 out<<" template class decl@"<< f->get_templateDeclaration();
25466
25467 if (SgMemberFunctionDeclaration* f = isSgMemberFunctionDeclaration(node) )
25468 out<<" assoc. class decl@"<< f->get_associatedClassDeclaration();
25469
25470 if (SgConstructorInitializer* ctor= isSgConstructorInitializer(node) )
25471 {
25472 out<<" member function decl@"<< ctor->get_declaration();
25473 }
25474
25475 if (SgIntVal* v= isSgIntVal(node))
25476 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25477
25478 if (SgShortVal* v= isSgShortVal(node))
25479 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25480
25481 if (SgLongIntVal* v= isSgLongIntVal(node))
25482 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25483
25484 if (SgLongLongIntVal* v= isSgLongLongIntVal(node))
25485 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25486
25487 if (SgUnsignedIntVal* v= isSgUnsignedIntVal(node))
25488 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25489
25490 if (SgUnsignedShortVal* v= isSgUnsignedShortVal(node))
25491 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25492
25493 if (SgUnsignedLongVal* v= isSgUnsignedLongVal(node))
25494 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25495
25496 if (SgUnsignedLongLongIntVal* v= isSgUnsignedLongLongIntVal(node))
25497 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25498
25499 if (SgFloatVal* v= isSgFloatVal(node))
25500 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25501
25502 if (SgDoubleVal* v= isSgDoubleVal(node))
25503 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25504
25505 if (SgLongDoubleVal* v= isSgLongDoubleVal(node))
25506 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25507
25508 if (SgVarRefExp* var_ref= isSgVarRefExp(node) )
25509 out<<" init name@"<< var_ref->get_symbol()->get_declaration() <<" symbol name="<<var_ref->get_symbol()->get_name();
25510
25511 if (SgMemberFunctionRefExp* func_ref= isSgMemberFunctionRefExp(node) )
25512 out<<" member func decl@"<< func_ref->get_symbol_i()->get_declaration();
25513
25514 if (SgTemplateInstantiationMemberFunctionDecl* cnode= isSgTemplateInstantiationMemberFunctionDecl(node) )
25515 out<<" template member func decl@"<< cnode->get_templateDeclaration();
25516
25517 if (SgFunctionRefExp* func_ref= isSgFunctionRefExp(node) )
25518 {
25519 SgFunctionSymbol* sym= func_ref->get_symbol_i();
25520 out<<" func decl@"<< sym->get_declaration() << " func sym name="<<sym->get_name();
25521 }
25522
25523 if (SgAdaRenamingRefExp* renaming_ref= isSgAdaRenamingRefExp(node) )
25524 {
25525 SgAdaRenamingDecl * renaming_decl = renaming_ref->get_decl();
25526 out<<" ada renaming decl@"<< renaming_decl;
25527 }
25528
25529 // base type of several types of nodes:
25530 if (SgTypedefDeclaration * v= isSgTypedefDeclaration(node))
25531 {
25532 out<<" base_type@"<< v->get_base_type();
25533// type_set.insert (v->get_base_type());
25534 }
25535
25536 if (SgArrayType* v= isSgArrayType(node))
25537 out<<" base_type@"<< v->get_base_type();
25538
25539 if (SgAdaAccessType* v= isSgAdaAccessType(node))
25540 out<<" base_type@"<< v->get_base_type();
25541
25542 if (SgTypeExpression* v= isSgTypeExpression(node))
25543 out<<" type@"<< v->get_type();
25544
25545 if (SgAdaAttributeExp* v= isSgAdaAttributeExp(node))
25546 out<<" attribute@"<< v->get_attribute();
25547
25548 if (SgUsingDirectiveStatement* v= isSgUsingDirectiveStatement(node))
25549 out<<" namespaceDeclaration="<< v->get_namespaceDeclaration();
25550
25551 out<<endl;
25552
25553 std::vector<SgNode* > children = node->get_traversalSuccessorContainer();
25554#if 0
25555 int total_count = children.size();
25556 int current_index=0;
25557#endif
25558
25559 int last_non_null_child_idx =-1;
25560 for (int i = (int) (children.size())-1; i>=0; i--)
25561 {
25562 if (children[i])
25563 {
25564 last_non_null_child_idx = i;
25565 break;
25566 }
25567 }
25568
25569#if 0
25570 // some Sg??PtrList are not AST nodes, not part of children , we need to handle them separatedly
25571 // we sum all children into single total_count to tell if there is remaining children.
25572 if (isSgTemplateInstantiationDecl (node))
25573 total_count += 1; // sn->get_templateArguments().size();
25574#endif
25575
25576 // handling SgTemplateArgumentPtrList first
25577 if (SgTemplateInstantiationDecl* sn = isSgTemplateInstantiationDecl (node))
25578 {
25579 SgTemplateArgumentPtrList& plist = sn->get_templateArguments();
25580 bool n_hasRemaining=false;
25581 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25582 string suffix= hasRemaining? "| " : " ";
25583 string n_prefix = prefix+suffix;
25584 string n_edge_label= "";
25585 serialize_list(plist, "SgTemplateArgumentPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25586 }
25587 else if (SgImportStatement* import_stmt = isSgImportStatement(node))
25588 {
25589 SgExpressionPtrList& plist = import_stmt->get_import_list();
25590 bool n_hasRemaining=false;
25591 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25592 string suffix= hasRemaining? "| " : " ";
25593 string n_prefix = prefix+suffix;
25594 string n_edge_label= "";
25595 serialize_list(plist, "SgExpressionPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25596 }
25597
25598 std::vector< std::string > successorNames= node->get_traversalSuccessorNamesContainer();
25599
25600 // finish sucessors
25601 for (size_t i =0; i< children.size(); i++)
25602 {
25603 bool n_hasRemaining=false;
25604#if 0
25605 if (current_index+1<total_count)
25606 n_hasRemaining=true;
25607 current_index++;
25608#else
25609 if ((int)i<last_non_null_child_idx) n_hasRemaining = true;
25610#endif
25611 string suffix= hasRemaining? "| " : " ";
25612 string n_prefix = prefix+suffix;
25613 if (children[i])
25614 serialize (children[i], n_prefix, n_hasRemaining, out, successorNames[i]);
25615 }
25616}
25617
25619{
25620 ostringstream oss;
25621 string prefix;
25622 string label="";
25623 serialize(node, prefix, false, oss, label);
25624 cout<<oss.str();
25625}
25626
25627void SageInterface::printAST(SgNode* node, const char* filename)
25628{
25629 printAST2TextFile(node, filename, true);
25630}
25631
25632void SageInterface::printAST2TextFile (SgNode* node, std::string filename, bool printType/*=true*/)
25633{
25634 // Rasmussen 9/21/2020: This leads to infinite recursion (clang warning message) and should be removed from API)
25635// ROSE_ABORT();
25636 printAST2TextFile (node, filename.c_str(), printType);
25637}
25638
25639void SageInterface::printAST2TextFile(SgNode* node, const char* filename, bool printType/*=true*/)
25640{
25641 ostringstream oss;
25642 string prefix;
25643 string label="";
25644 serialize(node, prefix, false, oss, label);
25645 ofstream textfile;
25646 textfile.open(filename, ios::out);
25647 textfile<<oss.str();
25648
25649 if (printType)
25650 {
25651 // append type information also
25652 textfile<<"Types encountered ...."<<endl;
25653 ostringstream oss2;
25654 VariantVector vv(V_SgType);
25655 Rose_STL_Container<SgNode*> tnodes= NodeQuery::queryMemoryPool(vv);
25656 for (Rose_STL_Container<SgNode*>::const_iterator i = tnodes.begin(); i != tnodes.end(); ++i)
25657 {
25658 serialize (*i, prefix, false, oss2, label);
25659 }
25660 textfile<<oss2.str();
25661 }
25662
25663 textfile.close();
25664}
25665
25667{
25668 saveToPDF(node, string("temp.pdf.json") );
25669}
25671// node to find its enclosing file node. The entire file's AST will be saved into a pdf.
25672void SageInterface:: saveToPDF(SgNode* node, std::string filename)
25673{
25674 ROSE_ASSERT(node != NULL);
25675 AstJSONGeneration json;
25676 json.generateWithinFile(filename, getEnclosingFileNode(node));
25677}
25678
25680{
25681 bool rtval = false;
25682 ROSE_ASSERT (node != NULL);
25683 Sg_File_Info* finfo = node->get_file_info();
25684 if (finfo!=NULL)
25685 {
25686 string fname = finfo->get_filenameString();
25687 string buildtree_str1 = string("include-staging/gcc_HEADERS");
25688 string buildtree_str2 = string("include-staging/g++_HEADERS");
25689 string installtree_str1 = string("include/edg/gcc_HEADERS");
25690 string installtree_str2 = string("include/edg/g++_HEADERS");
25691 string system_headers = string("/usr/include");
25692 // if the file name has a sys header path of either source or build tree
25693 if ((fname.find (buildtree_str1, 0) != string::npos) ||
25694 (fname.find (buildtree_str2, 0) != string::npos) ||
25695 (fname.find (installtree_str1, 0) != string::npos) ||
25696 (fname.find (installtree_str2, 0) != string::npos) ||
25697 (fname.find (system_headers, 0) != string::npos)
25698 )
25699 rtval = true;
25700 }
25701 return rtval;
25702}
25703
25704
25705// DQ (2/27/2021): Adding support to detect if a SgLocatedNode is located in a header file.
25707 {
25708 // Check if a node is from a header file
25709
25710 bool returnValue = false;
25711
25712 Sg_File_Info* fileInfo = node->get_file_info();
25713 ROSE_ASSERT(fileInfo != NULL);
25714 string filename = fileInfo->get_filenameString();
25715
25716#if 0
25717 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());
25718#endif
25719
25720 // DQ (2/27/2021): We save a map of all of the header files processed in the generation of the ROSE AST,
25721 // so the test is only if the filename is in the list.
25722 if (EDG_ROSE_Translation::edg_include_file_map.find(filename) == EDG_ROSE_Translation::edg_include_file_map.end())
25723 {
25724#if 0
25725 printf ("This is NOT in the EDG_ROSE_Translation::edg_include_file_map \n");
25726#endif
25727 }
25728 else
25729 {
25730#if 0
25731 printf ("This IS in the EDG_ROSE_Translation::edg_include_file_map \n");
25732#endif
25733 returnValue = true;
25734 }
25735
25736 return returnValue;
25737 }
25738
25739
25742{
25743 ROSE_ASSERT(return_type != NULL);
25744 ROSE_ASSERT(typeList != NULL);
25746 ROSE_ASSERT(fTable);
25747
25748 // This function make clever use of a static member function which can't be built
25749 // for the case of a SgMemberFunctionType (or at least not without more work).
25750 SgName typeName = SgFunctionType::get_mangled(return_type, typeList);
25751 SgFunctionType* funcType = isSgFunctionType(fTable->lookup_function_type(typeName));
25752
25753 return funcType;
25754}
25755
25760{
25761 ROSE_ASSERT (lhs != NULL);
25762 ROSE_ASSERT (rhs != NULL);
25763 if (lhs == rhs)
25764 return true;
25765
25766 bool rt = false;
25767 SgType* rt1 = lhs->get_return_type();
25768 SgType* rt2 = rhs->get_return_type();
25769
25770 if (isEquivalentType (rt1, rt2))
25771 {
25772 SgTypePtrList f1_arg_types = lhs->get_arguments();
25773 SgTypePtrList f2_arg_types = rhs->get_arguments();
25774 // Must have same number of argument types
25775 if (f1_arg_types.size() == f2_arg_types.size())
25776 {
25777 // DQ (2/16/2017): Fixed compiler warning about comparison between signed and unsigned integers
25778 // int counter = 0;
25779 size_t counter = 0;
25780 // iterate through all argument types
25781 // for (int i=0; i< f1_arg_types.size(); i++)
25782 for (size_t i=0; i< f1_arg_types.size(); i++)
25783 {
25784 if (isEquivalentType (f1_arg_types[i], f2_arg_types[i]) )
25785 counter ++; // count the number of equal arguments
25786 else
25787 break; // found different type? jump out the loop
25788 }
25789 // all arguments are equivalent, set to true
25790 if (counter == f1_arg_types.size())
25791 rt = true;
25792 }
25793 } // end if equivalent return types
25794
25795 return rt;
25796}
25797
25798bool
25800 {
25801 // This function is called in the SgType::isEquivalentType (const SgType & Y) const function.
25802
25803 // DQ (11/28/2015): A better goal for this function should be to define it as a recursive function.
25804
25805 // DQ (12/8/2015): We need to add support for SgMemberFunctionType as demonstrated by test2007_17.C.
25806 // and for SgTemplateType as demonstrated by tests/nonsmoke/functional/CompileTests/RoseExample_tests/testRoseHeaders_03.C
25807 // Note that this is only required within the change to use this isEquivalentType() function in the
25808 // support to replace:
25809 // templateParameterOrArgumentLocal->get_initializedName()->get_type() == templateParameterOrArgumentFromSymbol->get_initializedName()->get_type()
25810 // in ROSETTA/Grammar/Support.code
25811
25812 ROSE_ASSERT(lhs != NULL);
25813 ROSE_ASSERT(rhs != NULL);
25814
25815 bool isSame = false;
25816
25817 // 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).
25818 static int counter = 0;
25819
25820 const SgType & X = *lhs;
25821 const SgType & Y = *rhs;
25822
25823 // DQ (11/28/2015): We don't want to strip off everything.
25824 // SgType* stripType(unsigned char bit_array = STRIP_MODIFIER_TYPE | STRIP_REFERENCE_TYPE | STRIP_POINTER_TYPE | STRIP_ARRAY_TYPE | STRIP_TYPEDEF_TYPE ) const;
25825
25826 // I think we need to compute the type chain to evaluate equalence.
25827 // Rose_STL_Container< SgType*> getInternalTypes () const
25828
25829#define DEBUG_TYPE_EQUIVALENCE 0
25830
25831#if DEBUG_TYPE_EQUIVALENCE
25832 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25833 printf (" --- lhs = %s \n",lhs->unparseToString().c_str());
25834 printf (" --- rhs = %s \n",rhs->unparseToString().c_str());
25835#endif
25836
25837#if DEBUG_TYPE_EQUIVALENCE || 0
25838 if (counter == 0)
25839 {
25840 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25841 printf (" --- lhs = %p = %s = %s \n",lhs,lhs->class_name().c_str(),lhs->unparseToString().c_str());
25842 printf (" --- rhs = %p = %s = %s \n",rhs,rhs->class_name().c_str(),rhs->unparseToString().c_str());
25843 }
25844#endif
25845
25846#if DEBUG_TYPE_EQUIVALENCE || 0
25847 // Debugging output.
25848 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
25849 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
25850
25851 // Debugging output.
25852 printf ("Output of type chain for lhs: \n");
25853 for (size_t i = 0; i < X_typeChain.size(); i++)
25854 {
25855 SgType* element_type = X_typeChain[i];
25856 printf ("X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25857 printf (" --- X_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25858 SgModifierType* modifierType = isSgModifierType(element_type);
25859 if (modifierType != NULL)
25860 {
25861 // modifierType->get_typeModifier().display("X type chain");
25862 string s = modifierType->get_typeModifier().displayString();
25863 printf (" --- type chain modifier: %s \n",s.c_str());
25864 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25865 }
25866 }
25867
25868 printf ("Output of type chain for rhs: \n");
25869 for (size_t i = 0; i < Y_typeChain.size(); i++)
25870 {
25871 SgType* element_type = Y_typeChain[i];
25872 printf ("Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25873 printf (" --- Y_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25874 SgModifierType* modifierType = isSgModifierType(element_type);
25875 if (modifierType != NULL)
25876 {
25877 // modifierType->get_typeModifier().display("Y type chain");
25878 string s = modifierType->get_typeModifier().displayString();
25879 printf (" --- type chain modifier: %s \n",s.c_str());
25880 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25881 }
25882 }
25883#endif
25884
25885 // Increment the static variable to control the recursive depth while we debug this.
25886 counter++;
25887
25888 // DQ (11/28/2015): exit with debug output instead of infinte recursion.
25889 // if (counter >= 280)
25890 // if (counter >= 500)
25891 if (counter >= 280)
25892 {
25893 // 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());
25894 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);
25895 }
25896
25897 // DQ (12/23/2015): ASC application code requires this to be increased to over 122 (selected 300 for extra margin of safety).
25898 // DQ (11/28/2015): exit in stead of infinte recursion.
25899 // if (counter > 300)
25900 // if (counter > 600)
25901 // if (counter > 5000)
25902 // if (counter > 300)
25903 if (counter > 350)
25904 {
25905 // DQ (11/28/2015): I think this is a reasonable limit.
25906 printf ("ERROR: In SageInterface::isEquivalentType(): recursive limit exceeded for : counter = %d \n",counter);
25907 ROSE_ABORT();
25908 }
25909
25910 // bool exit = false;
25911
25912 // Strip off any typedefs since they are equivalent by definition.
25913 SgType* X_element_type = X.stripType( SgType::STRIP_TYPEDEF_TYPE );
25914 SgType* Y_element_type = Y.stripType( SgType::STRIP_TYPEDEF_TYPE );
25915
25916 // DQ (11/29/2015): We need to handle references (when they are both references we can support then uniformally).
25917 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
25918 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
25919
25920 if (X_referenceType != NULL && Y_referenceType != NULL)
25921 {
25922 X_element_type = X_referenceType->get_base_type();
25923 Y_element_type = Y_referenceType->get_base_type();
25924
25925 counter--;
25926
25927 // Recursive call.
25928 // return (*X_element_type) == (*Y_element_type);
25929 return isEquivalentType(X_element_type,Y_element_type);
25930 }
25931 else
25932 {
25933 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25934 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
25935 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
25936
25937 if (X_pointerType != NULL && Y_pointerType != NULL)
25938 {
25939 X_element_type = X_pointerType->get_base_type();
25940 Y_element_type = Y_pointerType->get_base_type();
25941
25942 counter--;
25943
25944 // Recursive call.
25945 // return (*X_element_type) == (*Y_element_type);
25946 return isEquivalentType(X_element_type,Y_element_type);
25947 }
25948 else
25949 {
25950 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25951 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
25952 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
25953
25954 // DQ (12/8/2015): We need to check that the array size is the same.
25955 if (X_arrayType != NULL && Y_arrayType != NULL)
25956 {
25957 X_element_type = X_arrayType->get_base_type();
25958 Y_element_type = Y_arrayType->get_base_type();
25959
25960 SgExpression* X_array_index_expression = X_arrayType->get_index();
25961 SgExpression* Y_array_index_expression = Y_arrayType->get_index();
25962
25963 if (X_array_index_expression == Y_array_index_expression)
25964 {
25965#if DEBUG_TYPE_EQUIVALENCE || 0
25966 printf ("In SageInterface::isEquivalentType(): counter = %d: Need to check the array size for static equivalence \n",counter);
25967#endif
25968 counter--;
25969
25970 // Recursive call.
25971 // return (*X_element_type) == (*Y_element_type);
25972 return isEquivalentType(X_element_type,Y_element_type);
25973 }
25974 else
25975 {
25976 // Need more complex test for expression equivalence.
25977#if DEBUG_TYPE_EQUIVALENCE || 0
25978 printf ("In SageInterface::isEquivalentType(): counter = %d Need more complex test for expression equivalence \n",counter);
25979 string str1 = X_array_index_expression->unparseToString();
25980 string str2 = Y_array_index_expression->unparseToString();
25981 printf (" --- array index expressions: str1 = %s str2 = %s \n",str1.c_str(),str2.c_str());
25982#endif
25983 // DQ (12/9/2016): Need to decriment the counter as part of recursive function call.
25984 counter--;
25985
25986 // Recursive call.
25987 return isEquivalentType(X_element_type,Y_element_type);
25988 }
25989 }
25990 else
25991 {
25992 // DQ (12/15/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25993 SgNonrealType* X_templateType = isSgNonrealType(X_element_type);
25994 SgNonrealType* Y_templateType = isSgNonrealType(Y_element_type);
25995
25996 // DQ (12/15/2015): We need to check that the array size is the same.
25997 if (X_templateType != NULL && Y_templateType != NULL)
25998 {
25999 string X_name = X_templateType->get_name();
26000 string Y_name = Y_templateType->get_name();
26001
26002 SgNonrealDecl* X_templateDecl = isSgNonrealDecl(X_templateType->get_declaration());
26003 ROSE_ASSERT(X_templateDecl != NULL);
26004 SgNonrealDecl* Y_templateDecl = isSgNonrealDecl(Y_templateType->get_declaration());
26005 ROSE_ASSERT(Y_templateDecl != NULL);
26006
26007 int X_template_parameter_position = X_templateDecl->get_template_parameter_position();
26008 int Y_template_parameter_position = Y_templateDecl->get_template_parameter_position();
26009
26010 SgNode * X_parent = X_templateDecl->get_parent();
26011 SgNode * Y_parent = Y_templateDecl->get_parent();
26012
26013#if DEBUG_TYPE_EQUIVALENCE
26014 SgNode * X_parent_parent = X_parent ? X_parent->get_parent() : NULL;
26015 SgNode * Y_parent_parent = Y_parent ? Y_parent->get_parent() : NULL;
26016 printf ("In SageInterface::isEquivalentType(): case SgNonrealType:\n");
26017 printf (" -- X_name = %s Y_name = %s\n", X_name.c_str(),Y_name.c_str());
26018 printf (" -- X_template_parameter_position = %d Y_template_parameter_position = %d\n", X_template_parameter_position,Y_template_parameter_position);
26019 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() : "");
26020 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() : "");
26021 printf (" -- X_templateDecl->get_mangled_name() = %s\n", X_templateDecl->get_mangled_name().str());
26022 printf (" -- Y_templateDecl->get_mangled_name() = %s\n", Y_templateDecl->get_mangled_name().str());
26023#endif
26024 bool value = (X_parent == Y_parent);
26025
26026 if (value && X_templateDecl->get_is_template_param() && Y_templateDecl->get_is_template_param()) {
26027 value = (X_template_parameter_position == Y_template_parameter_position);
26028 } else if (value && X_templateDecl->get_is_class_member() && Y_templateDecl->get_is_class_member()) {
26029 value = (X_name == Y_name);
26030 }
26031
26032 counter--;
26033
26034 return value;
26035 }
26036 else
26037 {
26038 // DQ (2/13/2018): I an unclear if we are really done since they could have resolved to different types or the same type.
26039 // Nothing to do here since we have explored all uniform pairs of intermediate types possible.
26040#if 0
26041 printf ("Nothing to do here since we have explored all uniform pairs of intermediate types possible: isSame = %s \n",isSame ? "true" : "false");
26042 // printf (" --- X_element_type = %p = %s \n",X_element_type,X_element_type->unparseToString().c_str());
26043 // printf (" --- Y_element_type = %p = %s \n",Y_element_type,Y_element_type->unparseToString().c_str());
26044 printf (" --- lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26045 printf (" --- rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26046#endif
26047#if DEBUG_TYPE_EQUIVALENCE
26048 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");
26049#endif
26050 }
26051 }
26052 }
26053 } // end if reference type, pointer type, array type, and template type
26054
26055 SgModifierType* X_modifierType = isSgModifierType(X_element_type);
26056 SgModifierType* Y_modifierType = isSgModifierType(Y_element_type);
26057
26058#if DEBUG_TYPE_EQUIVALENCE
26059 printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %p = %s Y_element_type = %p = %s \n",
26060 counter,X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26061#endif
26062
26063 if (X_modifierType != NULL && Y_modifierType != NULL)
26064 {
26065 // Handle the case of both modifiers.
26066#if DEBUG_TYPE_EQUIVALENCE
26067 printf ("In SageInterface::isEquivalentType(): loop: these are the both SgModifierType nodes: isSame = %s \n",isSame ? "true" : "false");
26068#endif
26069 if (X_modifierType == Y_modifierType)
26070 {
26071 isSame = true;
26072#if DEBUG_TYPE_EQUIVALENCE
26073 printf ("In SageInterface::isEquivalentType(): loop: these are the same modifier type: isSame = %s \n",isSame ? "true" : "false");
26074#endif
26075 }
26076 else
26077 {
26078 if (X_modifierType->get_typeModifier() == Y_modifierType->get_typeModifier())
26079 {
26080#if DEBUG_TYPE_EQUIVALENCE
26081 printf ("In SageInterface::isEquivalentType(): loop: these are equivalent modifiers: check the base type: isSame = %s \n",isSame ? "true" : "false");
26082#endif
26083 // Recursive call.
26084 // isSame = (*X_modifierType->get_base_type()) == (*Y_modifierType->get_base_type());
26085 isSame = isEquivalentType(X_modifierType->get_base_type(),Y_modifierType->get_base_type());
26086 }
26087 else
26088 {
26089#if DEBUG_TYPE_EQUIVALENCE
26090 printf ("In SageInterface::isEquivalentType(): loop: these are not equivalent modifier types: check for default settings: isSame = %s \n",isSame ? "true" : "false");
26091#endif
26092 // DQ (5/22/2016): fixing bug which cansed infinite recursion (case there the SgModifiers were different).
26093 bool skippingOverIdentityModifier = false;
26094
26095 if (X_modifierType->get_typeModifier().isIdentity() == true)
26096 {
26097#if DEBUG_TYPE_EQUIVALENCE
26098 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26099#endif
26100 X_element_type = X_modifierType->get_base_type();
26101
26102 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26103 skippingOverIdentityModifier = true;
26104 }
26105
26106 if (Y_modifierType->get_typeModifier().isIdentity() == true)
26107 {
26108#if DEBUG_TYPE_EQUIVALENCE
26109 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26110#endif
26111 Y_element_type = Y_modifierType->get_base_type();
26112
26113 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26114 skippingOverIdentityModifier = true;
26115 }
26116
26117 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26118#if DEBUG_TYPE_EQUIVALENCE
26119 printf ("In SageInterface::isEquivalentType(): loop: skippingOverIdentityModifier = %s \n",skippingOverIdentityModifier ? "true" : "false");
26120#endif
26121 // Recursive call on non-default modifier base types.
26122 // isSame = (*X_element_type) == (*Y_element_type);
26123 // isSame = isEquivalentType(X_element_type,Y_element_type);
26124 if (skippingOverIdentityModifier == true)
26125 {
26126#if DEBUG_TYPE_EQUIVALENCE
26127 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");
26128#endif
26129 // If we have made progress in skipping over an identity modifier then we need to reevaluate if these are the equivalent types.
26130 isSame = isEquivalentType(X_element_type,Y_element_type);
26131 }
26132 else
26133 {
26134 // 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).
26135 isSame = false;
26136#if DEBUG_TYPE_EQUIVALENCE
26137 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");
26138#endif
26139 }
26140
26141#if DEBUG_TYPE_EQUIVALENCE
26142 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isSame = %s \n",isSame ? "true" : "false");
26143#endif
26144 }
26145 }
26146 }
26147 else
26148 {
26149 // At least one of these is not a SgModifierType.
26150
26151 if (X_modifierType != NULL || Y_modifierType != NULL)
26152 {
26153 bool isReduceable = false;
26154
26155 if (X_modifierType != NULL && X_modifierType->get_typeModifier().isIdentity() == true)
26156 {
26157#if DEBUG_TYPE_EQUIVALENCE
26158 printf ("In SageInterface::isEquivalentType(): loop: found default setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26159#endif
26160 X_element_type = X_modifierType->get_base_type();
26161 isReduceable = true;
26162 }
26163
26164 if (Y_modifierType != NULL && Y_modifierType->get_typeModifier().isIdentity() == true)
26165 {
26166#if DEBUG_TYPE_EQUIVALENCE
26167 printf ("In SageInterface::isEquivalentType(): loop: found default setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26168#endif
26169 Y_element_type = Y_modifierType->get_base_type();
26170 isReduceable = true;
26171 }
26172
26173 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26174#if DEBUG_TYPE_EQUIVALENCE
26175 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s \n",isReduceable ? "true" : "false");
26176#endif
26177 if (isReduceable == true)
26178 {
26179 // Recursive call on non-default modifier base types.
26180 // isSame = (*X_element_type) == (*Y_element_type);
26181 isSame = isEquivalentType(X_element_type,Y_element_type);
26182 }
26183 else
26184 {
26185 // Neither of these types were reducable.
26186 isSame = false;
26187 }
26188
26189#if DEBUG_TYPE_EQUIVALENCE
26190 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s isSame = %s \n",
26191 isReduceable ? "true" : "false",isSame ? "true" : "false");
26192#endif
26193 }
26194 else
26195 {
26196 // Neither of these are SgModifierType nodes.
26197 // X_element_type = X_element_type->stripType( STRIP_TYPEDEF_TYPE );
26198 // Y_element_type = Y_element_type->stripType( STRIP_TYPEDEF_TYPE );
26199
26200 if (X_element_type == Y_element_type)
26201 {
26202 isSame = true;
26203#if DEBUG_TYPE_EQUIVALENCE || 0
26204 // printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s \n",isSame ? "true" : "false");
26205 printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s lhs = %p = %s rhs = %p = %s \n",
26206 isSame ? "true" : "false",lhs,lhs->unparseToString().c_str(),rhs,rhs->unparseToString().c_str());
26207#endif
26208#if DEBUG_TYPE_EQUIVALENCE || 0
26209 // DQ (2/13/2018): Debugging type equivalence. If they are the same typedef, they
26210 // still might not be interchangable if one is defined in a restrcited scope.
26211 const SgTypedefType* lhs_typedefType = isSgTypedefType(lhs);
26212 const SgTypedefType* rhs_typedefType = isSgTypedefType(rhs);
26213
26214 if (lhs_typedefType != NULL || rhs_typedefType != NULL)
26215 {
26216#if 0
26217 if (lhs_typedefType != NULL)
26218 {
26219 printf ("lhs was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26220 }
26221 if (rhs_typedefType != NULL)
26222 {
26223 printf ("rhs was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26224 }
26225#else
26226 printf (" --- one was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26227 printf (" --- one was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26228#endif
26229 }
26230#endif
26231 }
26232 else
26233 {
26234 // DQ (3/20/2016): This is reported by GNU as set but not used.
26235 // bool isReduceable = false;
26236
26237 // DQ (11/29/2015): We need to handle reference (when they are both references we can support then uniformally).
26238 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26239 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26240
26241 if (X_referenceType != NULL || Y_referenceType != NULL)
26242 {
26243#if 0
26244 if (X_referenceType != NULL)
26245 {
26246 X_element_type = X_referenceType->get_base_type();
26247
26248 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26249 // isReduceable = true;
26250 isReduceable = false;
26251 }
26252
26253 if (Y_referenceType != NULL)
26254 {
26255 Y_element_type = Y_referenceType->get_base_type();
26256
26257 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26258 // isReduceable = true;
26259 isReduceable = false;
26260 }
26261
26262 if (isReduceable == true)
26263 {
26264 // Recursive call on non-default modifier base types.
26265 // isSame = (*X_element_type) == (*Y_element_type);
26266 isSame = isEquivalentType(X_element_type,Y_element_type);
26267 }
26268 else
26269 {
26270 // Neither of these types were reducable.
26271 isSame = false;
26272 }
26273#else
26274 isSame = false;
26275#endif
26276 }
26277 else
26278 {
26279 // Recursive call on non-typedef base types.
26280 // isSame = (*X_element_type) == (*Y_element_type);
26281 // isSame = isEquivalentType(X_element_type,Y_element_type);
26282
26283#if DEBUG_TYPE_EQUIVALENCE
26284 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26285#endif
26286
26287 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26288 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26289 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26290
26291 if (X_pointerType != NULL || Y_pointerType != NULL)
26292 {
26293#if 0
26294 if (X_pointerType != NULL)
26295 {
26296 X_element_type = X_pointerType->get_base_type();
26297
26298 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26299 // isReduceable = true;
26300 isReduceable = false;
26301 }
26302
26303 if (Y_pointerType != NULL)
26304 {
26305 Y_element_type = Y_pointerType->get_base_type();
26306
26307 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26308 // isReduceable = true;
26309 isReduceable = false;
26310 }
26311
26312 if (isReduceable == true)
26313 {
26314 // Recursive call on non-default modifier base types.
26315 // isSame = (*X_element_type) == (*Y_element_type);
26316 isSame = isEquivalentType(X_element_type,Y_element_type);
26317 }
26318 else
26319 {
26320 // Neither of these types were reducable.
26321 isSame = false;
26322 }
26323#else
26324 isSame = false;
26325#endif
26326 }
26327 else
26328 {
26329 // Recursive call on non-typedef base types.
26330 // isSame = (*X_element_type) == (*Y_element_type);
26331 // isSame = isEquivalentType(X_element_type,Y_element_type);
26332
26333#if DEBUG_TYPE_EQUIVALENCE
26334 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26335#endif
26336
26337 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26338 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26339 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26340
26341 if (X_arrayType != NULL || Y_arrayType != NULL)
26342 {
26343#if 0
26344 if (X_arrayType != NULL)
26345 {
26346 X_element_type = X_arrayType->get_base_type();
26347
26348 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26349 // isReduceable = true;
26350 isReduceable = false;
26351 }
26352
26353 if (Y_arrayType != NULL)
26354 {
26355 Y_element_type = Y_arrayType->get_base_type();
26356
26357 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26358 // isReduceable = true;
26359 isReduceable = false;
26360 }
26361
26362 if (isReduceable == true)
26363 {
26364 // Recursive call on non-default modifier base types.
26365 // isSame = (*X_element_type) == (*Y_element_type);
26366 isSame = isEquivalentType(X_element_type,Y_element_type);
26367 }
26368 else
26369 {
26370 // Neither of these types were reducable.
26371 isSame = false;
26372 }
26373#else
26374 isSame = false;
26375#endif
26376 }
26377 else
26378 {
26379 // Recursive call on non-typedef base types.
26380 // isSame = (*X_element_type) == (*Y_element_type);
26381 // isSame = isEquivalentType(X_element_type,Y_element_type);
26382
26383#if DEBUG_TYPE_EQUIVALENCE
26384 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26385#endif
26386
26387 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26388 SgFunctionType* X_functionType = isSgFunctionType(X_element_type);
26389 SgFunctionType* Y_functionType = isSgFunctionType(Y_element_type);
26390
26391 if (X_functionType != NULL || Y_functionType != NULL)
26392 {
26393 bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (X_functionType == Y_functionType) );
26394 //TODO: Liao, 9/15/2016, better comparison of function types
26395 //bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (isEquivalentFunctionType(X_functionType, Y_functionType)) );
26396#if DEBUG_TYPE_EQUIVALENCE || 0
26397 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgFunctionType: value = %s \n",value ? "true" : "false");
26398#endif
26399 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26400 // isSame == value;
26401 isSame = value;
26402
26403 // DQ (3/20/2016): This is reported by GNU as set but not used.
26404 // isReduceable = false;
26405 }
26406 else
26407 {
26408 // Recursive call on non-typedef base types.
26409 // isSame = isEquivalentType(X_element_type,Y_element_type);
26410
26411 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26412 SgMemberFunctionType* X_memberFunctionType = isSgMemberFunctionType(X_element_type);
26413 SgMemberFunctionType* Y_memberFunctionType = isSgMemberFunctionType(Y_element_type);
26414
26415 if (X_memberFunctionType != NULL || Y_memberFunctionType != NULL)
26416 {
26417 // DQ (12/15/2015): This code should be unreachable since it would have executed the code above (the case of SgFunctionType).
26418 printf ("This should be unreachable code \n");
26419 ROSE_ABORT();
26420
26421#if 0 // [Robb Matzke 2021-03-24]: unreachable
26422 bool value = ( (X_memberFunctionType != NULL && Y_memberFunctionType != NULL) && (X_memberFunctionType == Y_memberFunctionType) );
26423#if DEBUG_TYPE_EQUIVALENCE || 0
26424 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgMemberFunctionType: value = %s \n",value ? "true" : "false");
26425#endif
26426 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26427 // isSame == value;
26428 isSame = value;
26429#endif
26430 }
26431 else
26432 {
26433 // Recursive call on non-typedef base types.
26434 // isSame = isEquivalentType(X_element_type,Y_element_type);
26435#if 0
26436 // Check for irreducable types.
26437 bool X_isReduceable = true;
26438 if (isSgTypeSignedLong(X_element_type) != NULL ||
26439 isSgTypeUnsignedInt(X_element_type) != NULL ||
26440 isSgTypeBool(X_element_type) != NULL ||
26441 isSgTypeInt(X_element_type) != NULL)
26442 {
26443 X_isReduceable = false;
26444 }
26445
26446 bool Y_isReduceable = true;
26447 if (isSgTypeSignedLong(Y_element_type) != NULL ||
26448 isSgTypeUnsignedInt(Y_element_type) != NULL ||
26449 isSgTypeBool(Y_element_type) != NULL ||
26450 isSgTypeInt(Y_element_type) != NULL)
26451 {
26452 Y_isReduceable = false;
26453 }
26454#if DEBUG_TYPE_EQUIVALENCE || 0
26455 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_isReduceable = %s Y_isReduceable = %s \n",
26456 X_isReduceable ? "true" : "false",Y_isReduceable ? "true" : "false");
26457#endif
26458 if (X_isReduceable == true || Y_isReduceable == true)
26459 {
26460 // Recursive call on non-default modifier base types.
26461 isSame = isEquivalentType(X_element_type,Y_element_type);
26462 }
26463 else
26464 {
26465 // Neither of these types were reducable.
26466 isSame = false;
26467 }
26468#else
26469 // DQ (12/20/2015): This is the default case for irreducable types.
26470 if (X_element_type->variantT() == Y_element_type->variantT())
26471 {
26472#if DEBUG_TYPE_EQUIVALENCE || 0
26473 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_element_type = %p = %s Y_element_type = %p = %s \n",
26474 X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26475#endif
26476 // DQ (5/26/2016): It is not good enough that the variants match.
26477 // isSame = true;
26478 // isSame = isEquivalentType(X_element_type,Y_element_type);
26479 isSame = (X_element_type == Y_element_type);
26480 }
26481 else
26482 {
26483 // Neither of these types were reducable or equal.
26484 isSame = false;
26485 }
26486#endif
26487 }
26488 }
26489 }
26490 }
26491 }
26492 }
26493 }
26494 }
26495
26496 // Decrement the static variable to control the recursive depth while we debug this.
26497 counter--;
26498
26499#if DEBUG_TYPE_EQUIVALENCE || 0
26500 printf ("In SageInterface::isEquivalentType(): isSame = %s \n",isSame ? "true" : "false");
26501#endif
26502
26503#if DEBUG_TYPE_EQUIVALENCE || 0
26504 if (counter == 1 && isSame == true)
26505 {
26506 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());
26507
26508 // Debugging output.
26509 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26510 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26511
26512 // Debugging output.
26513 printf (" --- Output of type chain for lhs: \n");
26514 for (size_t i = 0; i < X_typeChain.size(); i++)
26515 {
26516 SgType* element_type = X_typeChain[i];
26517 printf (" --- --- X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26518 SgModifierType* modifierType = isSgModifierType(element_type);
26519 if (modifierType != NULL)
26520 {
26521 // modifierType->get_typeModifier().display("X type chain");
26522 string s = modifierType->get_typeModifier().displayString();
26523 printf (" --- type chain modifier: %s \n",s.c_str());
26524 }
26525 }
26526
26527 printf (" --- Output of type chain for rhs: \n");
26528 for (size_t i = 0; i < Y_typeChain.size(); i++)
26529 {
26530 SgType* element_type = Y_typeChain[i];
26531 printf (" --- --- Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26532 SgModifierType* modifierType = isSgModifierType(element_type);
26533 if (modifierType != NULL)
26534 {
26535 // modifierType->get_typeModifier().display("Y type chain");
26536 string s = modifierType->get_typeModifier().displayString();
26537 printf (" --- --- type chain modifier: %s \n",s.c_str());
26538 }
26539 }
26540 }
26541#endif
26542
26543#if 0
26544 if (counter == 0)
26545 {
26546 if (isSame == true)
26547 {
26548 // 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());
26549 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26550 // printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26551 // printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26552 printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26553 printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26554 }
26555 else
26556 {
26557 // 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());
26558 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26559 }
26560 }
26561 else
26562 {
26563 printf (" --- counter = %d \n",counter);
26564 }
26565#endif
26566
26567 return isSame;
26568 }
26569
26570
26571#if 0
26572// This is modified to be a template function and so must be moved to the header file.
26573// DQ (8/30/2016): Added function to detect EDG AST normalization.
26574bool
26575SageInterface::isNormalizedTemplateInstantiation (SgFunctionDeclaration* function)
26576 {
26577 // This function is called in the Call graph generation to avoid filtering out EDG normalized
26578 // function template instnatiations (which come from normalized template functions and member functions).
26579
26580 bool retval = false;
26581
26582#if 1
26583 // DQ (8/30/2016): We need to mark this as an EDG normalization so that we can detect it as an exception
26584 // to some simple attempts to filter the AST (e.g. for the Call Graph implementation which filters on only
26585 // functions in the current directory). This explicit makring makes it much easier to get this test correct.
26586 // But we still need to look at if the location of the parent template is something that we wnat to output.
26587 // If tis is a template instantiation then it is not enough to look only at the non-defining declaration if
26588 // it is not compiler generated.
26589 retval = function->get_marked_as_edg_normalization();
26590#else
26591 // Test for this to be a template instantation (in which case it was marked as
26592 // compiler generated but we may want to allow it to be used in the call graph,
26593 // if it's template was a part was defined in the current directory).
26594 SgTemplateInstantiationFunctionDecl* templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(function);
26595 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(function);
26596
26597 if (templateInstantiationFunction != NULL)
26598 {
26599 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26600 templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(templateInstantiationFunction->get_firstNondefiningDeclaration());
26601 SgTemplateFunctionDeclaration* templateFunctionDeclaration = templateInstantiationFunction->get_templateDeclaration();
26602 if (templateFunctionDeclaration != NULL)
26603 {
26604 // retval = operator()(templateFunctionDeclaration);
26605 retval = (templateFunctionDeclaration->isCompilerGenerated() == false);
26606 }
26607 else
26608 {
26609 // Assume false.
26610 }
26611
26612#if DEBUG_SELECTOR
26613 printf (" --- case of templateInstantiationFunction: retval = %s \n",retval ? "true" : "false");
26614#endif
26615 }
26616 else
26617 {
26618 if (templateInstantiationMemberFunction != NULL)
26619 {
26620 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26621 templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(templateInstantiationMemberFunction->get_firstNondefiningDeclaration());
26622 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = templateInstantiationMemberFunction->get_templateDeclaration();
26623 if (templateMemberFunctionDeclaration != NULL)
26624 {
26625 // retval = operator()(templateMemberFunctionDeclaration);
26626 retval = (templateMemberFunctionDeclaration->isCompilerGenerated() == false);
26627 }
26628 else
26629 {
26630 // Assume false.
26631 }
26632
26633#if DEBUG_SELECTOR
26634 printf (" --- case of templateInstantiationMemberFunction: retval = %s \n",retval ? "true" : "false");
26635#endif
26636 }
26637 }
26638#endif
26639
26640 return retval;
26641 }
26642#endif
26643
26644void SageInterface::detectCycleInType(SgType * type, const std::string & from) {
26645#if 0
26646 printf("In detectCycleInType():\n");
26647 printf(" -- from = %s\n", from.c_str());
26648 printf(" -- type = %p (%s)\n", type, type->class_name().c_str());
26649#endif
26650 std::vector<SgType *> seen_types;
26651
26652 while (type != NULL) {
26653
26654 // DQ (4/15/2019): Added assertion.
26655 ROSE_ASSERT(type != NULL);
26656
26657 std::vector<SgType *>::const_iterator it = std::find(seen_types.begin(), seen_types.end(), type);
26658 if (it != seen_types.end()) {
26659 printf("ERROR: Cycle found in type = %p (%s):\n", type, type->class_name().c_str());
26660 size_t i = 0;
26661 for (; it != seen_types.end(); it++) {
26662 printf(" [%zd] %p (%s)\n", i, *it, (*it)->class_name().c_str());
26663 i++;
26664 }
26665 printf("-> detectCycleInType() was called from: %s\n", from.c_str());
26666 ROSE_ABORT();
26667 }
26668 seen_types.push_back(type);
26669
26670 SgModifierType * modType = isSgModifierType(type);
26671 SgPointerType * pointType = isSgPointerType(type);
26672 SgReferenceType * refType = isSgReferenceType(type);
26673 SgArrayType * arrayType = isSgArrayType(type);
26674 SgTypedefType * typedefType = isSgTypedefType(type);
26675
26676#if 0
26677 // DQ (4/15/2019): Don't count SgPointerMemberType (also fixed in SgType::stripType() function).
26678 if (isSgPointerMemberType(type) != NULL)
26679 {
26680 pointType = NULL;
26681 }
26682#endif
26683
26684 if ( modType ) {
26685 type = modType->get_base_type();
26686 } else if ( refType ) {
26687 type = refType->get_base_type();
26688 } else if ( pointType ) {
26689 type = pointType->get_base_type();
26690 // } else if ( pointerMemberType ) {
26691 // type = pointerMemberType->get_base_type();
26692 } else if ( arrayType ) {
26693 type = arrayType->get_base_type();
26694 } else if ( typedefType ) {
26695 type = typedefType->get_base_type();
26696 } else {
26697 break;
26698 }
26699 ROSE_ASSERT(type != NULL);
26700 }
26701}
26702
26703
26704#if 0
26705// DQ (11/10/2019): Older original version of the function.
26706
26707// DQ (6/6/2019): Move this to the SageInteface namespace.
26708void
26710 {
26711 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
26712 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
26713 // declarations in the outlined code we can support the outpiled code with those references. This
26714 // approach has the added advantage of also supporting the same include file tree as the original
26715 // file where the outlined code is being taken from.
26716
26717 class TransformFunctionDefinitionsTraversal : public AstSimpleProcessing
26718 {
26719 public:
26720 std::vector<SgFunctionDeclaration*> functionList;
26721 SgSourceFile* sourceFile;
26722 int sourceFileId;
26723 string filenameWithPath;
26724
26725 public:
26726 TransformFunctionDefinitionsTraversal(): sourceFile(NULL), sourceFileId(-99) {}
26727
26728 void visit (SgNode* node)
26729 {
26730#if 0
26731 printf ("In convertFunctionDefinitionsToFunctionPrototypes visit(): node = %p = %s \n",node,node->class_name().c_str());
26732#endif
26733 SgSourceFile* temp_sourceFile = isSgSourceFile(node);
26734 if (temp_sourceFile != NULL)
26735 {
26736 sourceFile = temp_sourceFile;
26737 sourceFileId = sourceFile->get_file_info()->get_file_id();
26738
26739 // The file_id is not sufficnet, not clear why, but the filenames match.
26740 filenameWithPath = sourceFile->get_sourceFileNameWithPath();
26741
26742 printf ("Found source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26743
26744 }
26745
26746 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
26747 if (functionDeclaration != NULL)
26748 {
26749 // This should have been set already.
26750 ROSE_ASSERT(sourceFile != NULL);
26751
26752 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
26753 if (functionDeclaration == definingFunctionDeclaration)
26754 {
26755#if 1
26756 printf ("Found a defining function declaration: functionDeclaration = %p = %s name = %s \n",
26757 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26758
26759 printf (" --- recorded source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26760 printf (" --- source file: file_info: id = %d name = %s \n",
26761 functionDeclaration->get_file_info()->get_file_id(),functionDeclaration->get_file_info()->get_filenameString().c_str());
26762#endif
26763 // DQ (3/20/2019): The file_id is not sufficent, using the filename with path to do string equality.
26764 // bool isInSourceFile = (sourceFileId == functionDeclaration->get_file_info()->get_file_id());
26765 bool isInSourceFile = (filenameWithPath == functionDeclaration->get_file_info()->get_filenameString());
26766#if 1
26767 printf (" --- isInSourceFile = %s \n",isInSourceFile ? "true" : "false");
26768#endif
26769 // Remove the defining declaration as a test.
26770 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
26771 if (isInSourceFile == true && functionDeclarationScope != NULL)
26772 {
26773#if 1
26774 printf (" --- Found a defining function declaration: functionDeclarationScope = %p = %s \n",
26775 functionDeclarationScope,functionDeclarationScope->class_name().c_str());
26776#endif
26777 // functionDeclarationScope->removeStatement(functionDeclaration);
26778 // removeStatement(functionDeclaration);
26779 functionList.push_back(functionDeclaration);
26780 }
26781 }
26782 }
26783 }
26784 };
26785
26786 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
26787 TransformFunctionDefinitionsTraversal traversal;
26788 traversal.traverse(node, preorder);
26789
26790 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
26791
26792#if 1
26793 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): functionList.size() = %zu \n",functionList.size());
26794#endif
26795
26796 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
26797 while (i != functionList.end())
26798 {
26799 SgFunctionDeclaration* functionDeclaration = *i;
26800 ROSE_ASSERT(functionDeclaration != NULL);
26801
26802 SgFunctionDeclaration* nondefiningFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
26803 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26804
26805#if 1
26806 printf (" --- Removing function declaration: functionDeclaration = %p = %s name = %s \n",
26807 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26808#endif
26809 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
26810 // removeStatement(functionDeclaration);
26811 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration);
26812
26813 i++;
26814 }
26815
26816#if 0
26817 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): exiting as a test! \n");
26818 ROSE_ABORT();
26819#endif
26820 }
26821#endif
26822
26823
26824void
26826 {
26827 // DQ (10/31/2020): Display function for scopes (useful for debugging).
26828 ROSE_ASSERT(scope != NULL);
26829
26830 printf ("Output the statements in scope = %p = %s \n",scope,scope->class_name().c_str());
26831
26832 // This makes a copy (on the stack) and is inefficent, but this is only for debugging.
26833 SgStatementPtrList statementList = scope->generateStatementList();
26834 for (size_t i = 0; i < statementList.size(); i++)
26835 {
26836 SgStatement* statement = statementList[i];
26837 printf (" --- statement: %zu ptr: %p IR node: %s name: %s \n",i,statement,statement->class_name().c_str(),SageInterface::get_name(statement).c_str());
26838 }
26839
26840#if 0
26841 printf ("Exiting as a test at the end of evaluation of global scope! \n");
26842 ROSE_ABORT();
26843#endif
26844 }
26845
26846
26849 {
26850 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
26851 // SgDeclarationStatement* nondefiningFunctionDeclaration = NULL;
26852
26853#if 0
26854 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p = %s name = %s \n",
26855 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26856#endif
26857
26858 // DQ (11/21/2019): Check if this is a constructor, this is a temporary fix.
26859 bool isConstructor = false;
26860 SgMemberFunctionDeclaration* tmp_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
26861 if (tmp_memberFunctionDeclaration != NULL)
26862 {
26863 isConstructor = tmp_memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
26864
26865#if 0
26866 if (isConstructor == true)
26867 {
26868 printf ("Skipping case of constructors (in building prototype from defining function declaration) \n");
26869 return;
26870 }
26871#endif
26872 }
26873
26874 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
26875 // bool replaceWithEmptyDeclaration = false;
26876 // SgDeclarationStatement* emptyDeclaration = NULL;
26877
26878 SgName name = functionDeclaration->get_name();
26879 SgType* return_type = functionDeclaration->get_type()->get_return_type();
26880
26881#if 0
26882 // DQ (12/10/2020): The issue is that the default arguments defined in template functions are represented in the AST.
26883 // Where we output the template as a string, it is included, and in the template instantiation it is represented in
26884 // the AST. So where it is used, default arguments are not represented in the AST and so the are not generated in
26885 // this function that builds the function prototype from the defining function.
26886
26887 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p \n",functionDeclaration);
26888 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
26889 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
26890
26891 // DQ (12/9/2020): Check if there is a default argument. Need to figure out how default arguments
26892 // are specified in the function declarations, and make sure the prototype reproduces them.
26893 for (size_t i = 0; i < functionDeclaration->get_args().size(); i++)
26894 {
26895 SgInitializedName* arg = functionDeclaration->get_args()[i];
26896#if 1
26897 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_args(): (i = %zu) arg = %p = %s isDefaultArgument = %s \n",
26898 i,arg,arg->get_name().str(),arg->get_file_info()->isDefaultArgument() ? "true" : "false");
26899 printf (" --- arg->get_initializer() = %p \n",arg->get_initializer());
26900#endif
26901 if (arg->get_file_info()->isDefaultArgument() == true)
26902 {
26903 printf ("NOTE: default argument (i = %zu) not reproduced in function prototype: arg = %p = %s \n",i,arg,arg->get_name().str());
26904 }
26905 }
26906#endif
26907
26908#if 1
26909 SgFunctionParameterList* param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26910#else
26911 // 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).
26912 // SgFunctionParameterList *param_list = functionDeclaration->get_parlist();
26913 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
26914 SgFunctionParameterList* param_list = NULL;
26915
26916 if (templateInstantiationFunctionDecl == NULL)
26917 {
26918 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26919 }
26920 else
26921 {
26922 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
26923 if (templateInstantiationMemberFunctionDecl == NULL)
26924 {
26925 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26926 }
26927 }
26928#endif
26929
26930
26931 // bool isTemplateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration) != NULL);
26932 bool isTemplateInstantiationMemberFunctionDecl = false;
26933
26934 SgScopeStatement* scope = functionDeclaration->get_scope();
26935 // SgTemplateParameterPtrList* templateParameterList = NULL; // functionDeclaration->get_templateParameterList();
26936 SgExprListExp* python_decoratorList = NULL;
26937 bool buildTemplateInstantiation = false;
26938 SgTemplateArgumentPtrList* templateArgumentsList = NULL;
26939
26940 // DQ (9/26/2019): Tracing down a null parent pointer.
26941 // ROSE_ASSERT(param_list->get_parent() != NULL);
26942 // ROSE_ASSERT(param_list->get_parent() == NULL);
26943 ROSE_ASSERT(param_list == NULL || param_list->get_parent() == NULL);
26944
26945 switch (functionDeclaration->variantT())
26946 {
26947 case V_SgTemplateMemberFunctionDeclaration:
26948 {
26949#if 0
26950 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template member functions \n");
26951#endif
26952 SgTemplateMemberFunctionDeclaration* original_templateMemberFunctionDeclaration = isSgTemplateMemberFunctionDeclaration(functionDeclaration);
26953 ROSE_ASSERT(original_templateMemberFunctionDeclaration != NULL);
26954
26955 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = NULL;
26956
26957 unsigned int functionConstVolatileFlags = 0;
26958
26959 ROSE_ASSERT(original_templateMemberFunctionDeclaration->get_type() != NULL);
26960
26961 // Need to call:
26962 // unsigned int get_mfunc_specifier();
26963
26964 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_templateMemberFunctionDeclaration->get_type());
26965 ROSE_ASSERT(memberFunctionType != NULL);
26966
26967 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
26968
26969 // SgTemplateMemberFunctionDeclaration*
26970 // buildNondefiningTemplateMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
26971 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList* templateParameterList );
26972
26973 SgTemplateParameterPtrList templateParameterList = original_templateMemberFunctionDeclaration->get_templateParameters();
26974 // ROSE_ASSERT(templateParameterList != NULL);
26975
26976 templateMemberFunctionDeclaration =
26977 buildNondefiningTemplateMemberFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags, &templateParameterList );
26978#if 0
26979 printf ("ERROR: Template functions are not yet supported! \n");
26980 ROSE_ABORT();
26981#endif
26982 nondefiningFunctionDeclaration = templateMemberFunctionDeclaration;
26983
26984 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26985
26986 // DQ (11/21/2019): Handle constructors.
26987 if (isConstructor == true)
26988 {
26989 templateMemberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
26990 }
26991
26992 break;
26993 }
26994
26995 case V_SgTemplateFunctionDeclaration:
26996 {
26997#if 0
26998 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template functions \n");
26999#endif
27000 SgTemplateFunctionDeclaration* original_templateFunctionDeclaration = isSgTemplateFunctionDeclaration(functionDeclaration);
27001 ROSE_ASSERT(original_templateFunctionDeclaration != NULL);
27002
27003 SgTemplateFunctionDeclaration* templateFunctionDeclaration = NULL; // isSgTemplateFunctionDeclaration(functionDeclaration);
27004
27005 // SgTemplateFunctionDeclaration*
27006 // buildNondefiningTemplateFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27007 // SgScopeStatement* scope=NULL, SgExprListExp* decoratorList = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
27008
27009 SgTemplateParameterPtrList templateParameterList = original_templateFunctionDeclaration->get_templateParameters();
27010
27011 templateFunctionDeclaration = buildNondefiningTemplateFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, &templateParameterList );
27012#if 0
27013 printf ("ERROR: Template functions are not yet supported! \n");
27014 ROSE_ABORT();
27015#endif
27016 nondefiningFunctionDeclaration = templateFunctionDeclaration;
27017
27018 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27019
27020 break;
27021 }
27022
27023 // DQ (10/29/2020): Added new case.
27024 case V_SgTemplateInstantiationMemberFunctionDecl:
27025 {
27026 buildTemplateInstantiation = true;
27027
27028 isTemplateInstantiationMemberFunctionDecl = true;
27029
27030 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
27031 ROSE_ASSERT(templateInstantiationMemberFunctionDecl != NULL);
27032 templateArgumentsList = &(templateInstantiationMemberFunctionDecl->get_templateArguments());
27033#if 0
27034 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27035 // printf ("name from templateInstantiationMemberFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_template_name().str());
27036 printf ("name from templateInstantiationMemberFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_templateName().str());
27037 SgTemplateMemberFunctionDeclaration* templateDeclaration = templateInstantiationMemberFunctionDecl->get_templateDeclaration();
27038 if (templateDeclaration != NULL)
27039 {
27040 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27041 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27042 }
27043#endif
27044 // name = functionDeclaration->get_name();
27045 // name = templateInstantiationMemberFunctionDecl->get_template_name();
27046 name = templateInstantiationMemberFunctionDecl->get_templateName();
27047#if 0
27048 printf ("In case V_SgTemplateInstantiationMemberFunctionDecl: using name = %s \n",name.str());
27049#endif
27050 // DQ (10/29/2020): Change this to include the functionality to build the member function support without fall-through.
27051 }
27052 // fall through
27053 case V_SgMemberFunctionDeclaration:
27054 {
27055#if 0
27056 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support member functions \n");
27057#endif
27058 SgMemberFunctionDeclaration* original_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
27059 ROSE_ASSERT(original_memberFunctionDeclaration != NULL);
27060
27061 SgMemberFunctionDeclaration* memberFunctionDeclaration = NULL; // isSgMemberFunctionDeclaration(functionDeclaration);
27062
27063 // SgMemberFunctionDeclaration*
27064 // buildNondefiningMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27065 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList* templateArgumentsList);
27066
27067 unsigned int functionConstVolatileFlags = 0;
27068
27069 ROSE_ASSERT(original_memberFunctionDeclaration->get_type() != NULL);
27070
27071 // Need to call:
27072 // unsigned int get_mfunc_specifier();
27073
27074 // DQ (12/2/2019): If it is defined outside of the class, then don't replace with member function prototype,
27075 // since they is not allowed to be declared outside of the class they are a member of.
27076
27077 // We do want to build prototypes for template instantiation member functions, and template instantiation non-member functions (see below).
27078 bool buildPrototype = isTemplateInstantiationMemberFunctionDecl || original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope();
27079#if 0
27080 printf ("In SageInterface::buildFunctionPrototype(): buildPrototype = %s \n",buildPrototype ? "true" : "false");
27081#endif
27082 if (buildPrototype == true)
27083 {
27084 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_memberFunctionDeclaration->get_type());
27085 ROSE_ASSERT(memberFunctionType != NULL);
27086#if 0
27087 printf ("original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope() \n");
27088#endif
27089 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
27090
27091 memberFunctionDeclaration =
27093 ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags,
27094 buildTemplateInstantiation,templateArgumentsList );
27095#if 0
27096 printf ("ERROR: Member functions are not yet supported! \n");
27097 ROSE_ABORT();
27098#endif
27099 // DQ (11/21/2019): Handle constructors.
27100 if (isConstructor == true)
27101 {
27102 memberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27103 }
27104
27105 nondefiningFunctionDeclaration = memberFunctionDeclaration;
27106
27107 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27108 }
27109 else
27110 {
27111 // Case of member function defined outside of it's class.
27112#if 0
27113 printf ("NOTE: Member functions defined outside of their class can not be output as member function prototypes (not allowed in C++) \n");
27114#endif
27115 // We want to build a SgEmptyDeclaration using buildEmptyDeclaration() but this is not a function.
27116 // nondefiningFunctionDeclaration = buildEmptyDeclaration();
27117 nondefiningFunctionDeclaration = NULL;
27118#if 0
27119 nondefiningFunctionDeclaration = NULL;
27120
27121 replaceWithEmptyDeclaration = true;
27122 emptyDeclaration = buildEmptyDeclaration();
27123 ROSE_ASSERT(emptyDeclaration != NULL);
27124#endif
27125 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27126 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27127
27128 // Since we din't build a member function we don't need the parameter list.
27129 delete param_list;
27130 param_list = NULL;
27131#if 0
27132 printf ("Exiting as a test! \n");
27133 ROSE_ABORT();
27134#endif
27135 }
27136
27137 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27138 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27139 break;
27140 }
27141
27142 case V_SgFunctionDeclaration:
27143 {
27144 // This is for a non-member non-template function declaration.
27145 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27146 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27147 break;
27148 }
27149
27150 // DQ (10/29/2020): Added new case.
27151 case V_SgTemplateInstantiationFunctionDecl:
27152 {
27153 // This is for a non-member non-template function declaration.
27154 buildTemplateInstantiation = true;
27155 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27156 ROSE_ASSERT(templateInstantiationFunctionDecl != NULL);
27157 templateArgumentsList = &(templateInstantiationFunctionDecl->get_templateArguments());
27158#if 0
27159 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27160 // printf ("name from templateInstantiationFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationFunctionDecl->get_template_name().str());
27161 printf ("name from templateInstantiationFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationFunctionDecl->get_templateName().str());
27162 SgTemplateFunctionDeclaration* templateDeclaration = templateInstantiationFunctionDecl->get_templateDeclaration();
27163 if (templateDeclaration != NULL)
27164 {
27165 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27166 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27167 }
27168#endif
27169 name = templateInstantiationFunctionDecl->get_templateName();
27170#if 0
27171 printf ("In case V_SgTemplateInstantiationFunctionDecl: using name = %s \n",name.str());
27172#endif
27173 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27174 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27175 break;
27176 }
27177
27178 default:
27179 {
27180 // DQ (12/4/2019): If this is any other case than that handled above, then we just return.
27181 // These cases would be only template instantiations.
27182
27183 // Nothing to do, except delete the parameter list we built, and return.
27184 delete param_list;
27185 param_list = NULL;
27186
27187 return NULL;
27188 }
27189 }
27190
27191 // DQ (10/29/2020): We should be able to change this now that we support SgTemplateInstantiationFunctionDecl and SgTemplateInstantiationMemberFunctionDecl IR nodes.
27192 // DQ (9/26/2019): Tracing down a null parent pointer.
27193 ROSE_ASSERT(param_list == NULL || param_list->get_parent() != NULL);
27194 // ROSE_ASSERT(param_list != NULL);
27195 // ROSE_ASSERT(param_list->get_parent() != NULL);
27196
27197 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27198
27199 if (nondefiningFunctionDeclaration != NULL)
27200 {
27201 if (nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() == NULL)
27202 {
27203#if 0
27204 printf ("Setting the firstNondefiningDeclaration \n");
27205#endif
27206 nondefiningFunctionDeclaration->set_firstNondefiningDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27207 }
27208
27209 if (nondefiningFunctionDeclaration->get_definingDeclaration() == NULL)
27210 {
27211#if 0
27212 printf ("Setting the definingDeclaration \n");
27213#endif
27214 nondefiningFunctionDeclaration->set_definingDeclaration(functionDeclaration->get_definingDeclaration());
27215 }
27216
27217 ROSE_ASSERT(nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() != NULL);
27218 ROSE_ASSERT(nondefiningFunctionDeclaration->get_definingDeclaration() != NULL);
27219
27220 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27221 if (nondefiningFunctionDeclaration != NULL)
27222 {
27223 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27224 // This is a bug in the support for building a new prototype from a defining function declaration
27225 // and caused this problem. This assertion will prevent this sort of error from happening again.
27226 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27227 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27228 }
27229 }
27230
27231 return nondefiningFunctionDeclaration;
27232 }
27233
27234
27235// 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).
27238 {
27239 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27240 ROSE_ASSERT(functionDeclaration != NULL);
27241
27242#if 0
27243 printf ("****************************************************************** \n");
27244 printf ("Attached comments and CPP directives: defining functionDeclaration \n");
27245 SageInterface::printOutComments (functionDeclaration);
27246 printf ("****************************************************************** \n");
27247#endif
27248
27249 // 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.
27250
27251 nondefiningFunctionDeclaration = buildFunctionPrototype(functionDeclaration);
27252
27253 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27254 if (nondefiningFunctionDeclaration != NULL)
27255 {
27256 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27257 // This is a bug in the support for building a new prototype from a defining function declaration
27258 // and caused this problem. This assertion will prevent this sort of error from happening again.
27259 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27260 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27261 }
27262
27263 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27264
27265 if (templateInstantiationFunctionDecl == NULL)
27266 {
27267 if (nondefiningFunctionDeclaration != NULL)
27268 {
27269 // DQ (10/29/2020): Match the associated declaration modifiers.
27270 nondefiningFunctionDeclaration->get_declarationModifier() = functionDeclaration->get_declarationModifier();
27271
27272 // DQ (11/11/2020): Match the associated other kinds of modifiers.
27273 nondefiningFunctionDeclaration->get_functionModifier() = functionDeclaration->get_functionModifier();
27274 nondefiningFunctionDeclaration->get_specialFunctionModifier() = functionDeclaration->get_specialFunctionModifier();
27275
27276 nondefiningFunctionDeclaration->set_linkage( functionDeclaration->get_linkage() );
27277 nondefiningFunctionDeclaration->set_externBrace( functionDeclaration->get_externBrace() );
27278
27279 ROSE_ASSERT(nondefiningFunctionDeclaration->get_forward() == true);
27280
27281 // DQ (10/15/2019): Set the physical_file_id of the transformation to match that of the original defining declaration.
27282 int file_id = functionDeclaration->get_file_info()->get_physical_file_id();
27283 nondefiningFunctionDeclaration->get_file_info()->set_physical_file_id(file_id);
27284
27285 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27286 // removeStatement(functionDeclaration);
27287 // DQ (11/22/2020): Note that this step will move the comments and CPP directives to the new statement
27288 // (better in this step than in the copy of the pointer to the list above, which cause an iterator invalidation error).
27289 // DQ (10/21/2020): I think we may want to return the orignal defining function declaration.
27290 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27291 // DQ (11/15/2020): Note that the default is false, and we need true.
27292 bool movePreprocessingInfo = true;
27293 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration,movePreprocessingInfo);
27294
27295 // DQ (11/25/2020): This is the cause of a problem in the outliner caught in the resetParentPointer.C (definingDeclaration->get_parent() != __null).
27296 // 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.
27297 // This is the cause of a name qualification bug when the functionDeclaration is inserted into global scope and the name qualification
27298 // is not computed correctly (since the parent was still the namespace scope where it was originally.
27299 ROSE_ASSERT(nondefiningFunctionDeclaration->get_parent() != NULL);
27300 }
27301 }
27302 else
27303 {
27304 // DQ (7/12/2019): Template instantiations are not directly from the source code, so we don't have to move them.
27305 nondefiningFunctionDeclaration = NULL;
27306 }
27307
27308 // Check that static declaration is preserved.
27309 if (functionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true)
27310 {
27311 ROSE_ASSERT(nondefiningFunctionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true);
27312 }
27313
27314 // DQ (10/27/2020): Added return value so that we can access the new function prototype.
27315 return nondefiningFunctionDeclaration;
27316 }
27317
27318
27319std::vector<SgFunctionDeclaration*>
27321 {
27322 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
27323 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
27324 // declarations in the outlined code we can support the outpiled code with those references. This
27325 // approach has the added advantage of also supporting the same include file tree as the original
27326 // file where the outlined code is being taken from.
27327
27328 class FunctionDefinitionsTraversal : public AstSimpleProcessing
27329 {
27330 public:
27331 std::vector<SgFunctionDeclaration*> functionList;
27332 FunctionDefinitionsTraversal() {}
27333
27334 void visit (SgNode* node)
27335 {
27336 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
27337 if (functionDeclaration != NULL)
27338 {
27339 // This should have been set already.
27340 // ROSE_ASSERT(sourceFile != NULL);
27341
27342 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27343 if (functionDeclaration == definingFunctionDeclaration)
27344 {
27345 // Remove the defining declaration as a test.
27346 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27347 if (functionDeclarationScope != NULL)
27348 {
27349 functionList.push_back(functionDeclaration);
27350 }
27351 }
27352 }
27353 }
27354 };
27355
27356 // Now build the traveral object and call the traversal (preorder) on the AST subtree.
27357 FunctionDefinitionsTraversal traversal;
27358
27359 traversal.traverseWithinFile(node, preorder);
27360
27361 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27362
27363 return functionList;
27364 }
27365
27366
27367void
27369 {
27370 ROSE_ASSERT(node != NULL);
27371
27372 std::vector<SgFunctionDeclaration*> functionList = generateFunctionDefinitionsList(node);
27373 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27374
27375 while (i != functionList.end())
27376 {
27377 SgFunctionDeclaration* functionDeclaration = *i;
27378 ROSE_ASSERT(functionDeclaration != NULL);
27379 // Transform into prototype.
27381 i++;
27382 }
27383 }
27384
27385
27386
27387// DQ (7/14/2020): Added test for initializers to support debugging of Cxx11_tests/test2020_69.C.
27388void
27390 {
27391 // This function checks variable declarations for initializers. An issue (bug) in EDG 6.0
27392 // support for variable declarations initialized using lambda functions is that the initalizer
27393 // is discarded at some point in the processing of the AST. This function reports on all
27394 // variable declarations and if they contain initializers and if so what kind of initializer.
27395
27396 ROSE_ASSERT(node != nullptr);
27397
27398 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
27399 class CheckInitializerTraversal : public AstSimpleProcessing
27400 {
27401 public:
27402 void visit (SgNode* node)
27403 {
27404 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node);
27405 if (variableDeclaration != NULL)
27406 {
27407 SgInitializedName* initializedName = getFirstInitializedName(variableDeclaration);
27408 SgExpression* initializer = initializedName->get_initializer();
27409
27410 printf ("variableDeclaration = %p initializedName = %p = %s initializer = %p \n",
27411 variableDeclaration,initializedName,initializedName->get_name().str(),initializer);
27412
27413 if (initializer != NULL)
27414 {
27415 printf (" --- initializer = %s \n",initializer->class_name().c_str());
27416 }
27417 }
27418 }
27419 };
27420
27421 // Now buid the traveral object and call the traversal (preorder) on the project.
27422 CheckInitializerTraversal traversal;
27423 traversal.traverse(node, preorder);
27424 }
27425
27426namespace
27427{
27428 struct DeclaredType : sg::DispatchHandler<SgNamedType*>
27429 {
27430 void setResult(SgNamedType* ty) { res = ty; }
27431 void setResult(SgType*) { /* not a named type */ }
27432
27433 void handle(SgNode& n, SgNode&) { SG_UNEXPECTED_NODE(n); }
27434
27435 template <class SageDeclarationStatement>
27436 void handle(SageDeclarationStatement& n, SgDeclarationStatement&)
27437 {
27438 // SgDeclarationStatement::get_type is not a virtual function
27439 // => find overloaders returning SgNamedType in subclasses
27440 // by using the full type (SageDeclarationStatement).
27441 setResult(n.get_type());
27442 }
27443
27444 template <class SageNode>
27445 void handle(SageNode& n)
27446 {
27447 handle(n, n);
27448 }
27449 };
27450}
27451
27453{
27454 return sg::dispatch(DeclaredType{}, declaration);
27455}
27456
27458 SgGlobal * gsaf = project->get_globalScopeAcrossFiles();
27459 ROSE_ASSERT(gsaf != nullptr);
27460 SgSymbolTable * st = gsaf->get_symbol_table();
27461 ROSE_ASSERT(st != nullptr);
27462 rose_hash_multimap * hmm = st->get_table();
27463 ROSE_ASSERT(hmm != nullptr);
27464 hmm->clear();
27465
27466 st = SgNode::get_globalTypeTable()->get_type_table();
27467 ROSE_ASSERT(st != nullptr);
27468 hmm = st->get_table();
27469 ROSE_ASSERT(hmm != nullptr);
27470 hmm->clear();
27471
27473 ROSE_ASSERT(st != nullptr);
27474 hmm = st->get_table();
27475 ROSE_ASSERT(hmm != nullptr);
27476 hmm->clear();
27477}
27478
27480/*
27481
27482By default, only transformation generated AST nodes will be normalized since this is designed to normalize translator-generated code.
27483
27484--- p_lhs_operand_i ->@0x7ff2fc3f1010 SgArrowExp c_rc-575-out.cpp 16:13
27485 |--- p_lhs_operand_i ->@0x7ff2fc428010 SgAddressOfOp c_rc-575-out.cpp 16:4
27486 | |___ p_operand_i ->@0x7ff2fc582078 SgVarRefExp c_rc-575-out.cpp 16:5 init name@0x7ff2fcf03890 symbol name="table1"
27487 |___ p_rhs_operand_i ->@0x7ff2fc5820e0 SgVarRefExp c_rc-575-out.cpp 16:16 init name@0x7ff2fcf03480 symbol name="item1"
27488
27489
27490TODO: we only handle simplest pattern for now: both leaf operands involved are SgVarRefExp.
27491
27492 * */
27493int SageInterface::normalizeArrowExpWithAddressOfLeftOperand(SgNode* root, bool transformationGeneratedOnly /* =true */)
27494{
27495 int match_count = 0;
27496 ROSE_ASSERT (root);
27497
27498 // find all SgArrowExp, then try to match the expected pattern
27499 // SgArrowExp(SgAddressOfOp(SgVarRefExp:table1),SgVarRefExp:item1)
27500 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgArrowExp);
27501
27502 // The jovial2cpp translator generates two source file ASTs: and they often share the same subtrees.
27503 // So we need to make sure the same subtree is only processed once
27504 boost::unordered::unordered_map <SgNode*, bool> visited;
27505
27506 // reverse iterator is safer to use than forward iterator to support translation
27507 for (Rose_STL_Container<SgNode *>::reverse_iterator i = nodeList.rbegin(); i != nodeList.rend(); i++)
27508 {
27509 // skip a node if it is previously processed.
27510 if (visited.count(*i)==1)
27511 continue;
27512
27513 visited[*i]=true;
27514
27515 SgArrowExp* a_exp = isSgArrowExp(*i);
27516
27517 if (!a_exp)
27518 {
27519 cerr<<"SageInterface::normalizeArrowExpWithAddressOfLeftOperand() expects SgArrowExp while encountering "<<(*i)->class_name()<<"@"<<(*i) <<endl;
27520 ROSE_ASSERT (a_exp);
27521 }
27522
27523 if (transformationGeneratedOnly)
27524 {
27525 if (!(a_exp->get_file_info()->isTransformation()))
27526 continue;
27527 }
27528
27529 if (SgAddressOfOp* address_op = isSgAddressOfOp(a_exp->get_lhs_operand()) )
27530 {
27531 if (SgVarRefExp* left = isSgVarRefExp(address_op->get_operand())) // match left side pattern
27532 {
27533 if (SgVarRefExp* right = isSgVarRefExp (a_exp->get_rhs_operand())) // match right side pattern
27534 {
27535 // do the transformation: copy two operands, making a dot exp instead
27536 SgDotExp* dot_exp = buildDotExp (deepCopy(left), deepCopy(right));
27537 replaceExpression (a_exp, dot_exp);
27538 match_count++;
27539 }
27540 }
27541 }
27542 } // end for
27543
27544 return match_count;
27545}
27546
27547bool
27549 {
27550 class Traversal : public AstSimpleProcessing
27551 {
27552 public:
27553 bool found;
27554 Traversal() : found(false) {}
27555 void visit (SgNode* node)
27556 {
27557 SgCastExp* castExpression = isSgCastExp(node);
27558 if (castExpression != NULL)
27559 {
27560 // SgNode* parent = castExpression->get_parent();
27561 SgInitializer* initializer = isSgInitializer(castExpression->get_parent());
27562 if (initializer == NULL)
27563 {
27564 ROSE_ASSERT(castExpression->get_file_info() != NULL);
27565 if (castExpression->get_file_info()->isTransformation() == true)
27566 {
27567 printf (" --- Found a SgCastExp marked as a transformation: castExpression = %p \n",castExpression);
27568 found = true;
27569#if 0
27570 printf ("Exiting as a test! \n");
27571 ROSE_ASSERT(false);
27572#endif
27573 }
27574 else
27575 {
27576#if 0
27577 printf (" --- SgCastExp (but not marked as a transformation) node = %p = %s \n",node,node->class_name().c_str());
27578#endif
27579 }
27580 }
27581 else
27582 {
27583 // DQ (7/14/2021): This case is less interesting (not the SgCastExp that I was looking for in testing).
27584#if 1
27585 printf (" --- SgCastExp (but from an initializer) node = %p = %s \n",node,node->class_name().c_str());
27586#endif
27587 }
27588 }
27589 else
27590 {
27591#if 0
27592 printf (" --- node = %p = %s \n",node,node->class_name().c_str());
27593#endif
27594 }
27595 }
27596 };
27597
27598#if 1
27599 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s \n",s.c_str());
27600#endif
27601
27602 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27603 Traversal traversal;
27604 traversal.traverse(n, preorder);
27605
27606#if 1
27607 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s traversal.found = %s \n",s.c_str(),traversal.found ? "true" : "false");
27608#endif
27609#if 0
27610 // DQ (7/13/2021): return false so that we can test the execution of the code to generate that backend code.
27611 if (traversal.found == true)
27612 {
27613 printf ("In findFirstSgCastExpMarkedAsTransformation(): returning false \n");
27614 }
27615
27616 return false;
27617#else
27618 return traversal.found;
27619#endif
27620 }
27621
27622// A helper function to check
27623// begin: return 1
27624// middle (#else, #elif): return 2
27625// end directive: return -1
27626// othewise return 0;
27627static int isBeginDirective (PreprocessingInfo* info)
27628{
27629 ROSE_ASSERT (info != NULL);
27630 PreprocessingInfo::DirectiveType dtype= info->getTypeOfDirective();
27631 if (dtype == PreprocessingInfo::CpreprocessorIfdefDeclaration ||
27632 dtype == PreprocessingInfo::CpreprocessorIfndefDeclaration ||
27633 dtype == PreprocessingInfo::CpreprocessorIfDeclaration )
27634 {
27635 return 1;
27636 }
27637 else if (dtype==PreprocessingInfo::CpreprocessorElseDeclaration||
27638 dtype==PreprocessingInfo::CpreprocessorElifDeclaration)
27639 {
27640 return 2;
27641 }
27642 else if (dtype==PreprocessingInfo::CpreprocessorEndifDeclaration)
27643 {
27644 return -1;
27645 }
27646
27647 return 0;
27648}
27649
27650// a helper function to move things, the associated directive in the middle
27651static void moveInofListToNewPlace(AttachedPreprocessingInfoType* infoList, int cidx, set <AttachedPreprocessingInfoType*>& relatedInfoList, SgLocatedNode* lnode, int &retVal)
27652{
27653// AttachedPreprocessingInfoType* infoList = (*ki).first;
27654// int cidx= (*ki).second;
27655
27656 relatedInfoList.insert (infoList);
27657
27658 PreprocessingInfo* info = (*infoList)[cidx];
27659 // rewrite relative position
27660 info->setRelativePosition(PreprocessingInfo::after);
27661
27662 // insert after lnode
27663 lnode->addToAttachedPreprocessingInfo (info);
27664 retVal++;
27665
27666 // zero out from original list
27667 (*infoList)[cidx]= NULL;
27668}
27669
27670// Return the number of NULL PreprocessingInfo* within a subtree of a SgLocatedNode, inclusive
27672{
27673 int retVal=0;
27674 ROSE_ASSERT(lnode);
27675
27676 // collecting NULL entries
27677 RoseAst ast(lnode);
27678 RoseAst::iterator ast_i=ast.begin();
27679
27680 vector < pair< AttachedPreprocessingInfoType*, int> > empty_entries; // preprocessing info. to be erased, list vs. idx/offset
27681 for(;ast_i!=ast.end();++ast_i) {
27682 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27683 if (current ==NULL ) // skip non located nodes
27684 continue;
27685
27686 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27687 if (infoList == NULL) continue;
27688
27689 int commentIndex=0;
27690 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27691 {
27692 // fundamentally, we want to move individual PreprocessingInfo objects
27693 // Or just duplicate them (easier)
27694 PreprocessingInfo * info = *ci;
27695 if (info==NULL)
27696 empty_entries.push_back( make_pair (infoList, commentIndex) );
27697 commentIndex++;
27698 }
27699 }
27700
27701 // using reverse iterator to remove from backwards
27702 for (auto ki = empty_entries.rbegin(); ki != empty_entries.rend(); ki ++)
27703 {
27704 AttachedPreprocessingInfoType* infoList = (*ki).first;
27705 int cidx= (*ki).second;
27706
27707 PreprocessingInfo* info = (*infoList)[cidx];
27708 ROSE_ASSERT (info==NULL);
27709
27710 // erase start+offset
27711 AttachedPreprocessingInfoType::iterator k = infoList->begin();
27712 infoList->erase(k+cidx);
27713// cout<<"debugging: direct erasing: info@"<< infoList<< " idx="<<cidx<<endl;
27714 retVal ++;
27715 }
27716 return retVal;
27717}
27718
27719//TODO: expose this to header file?
27720// We keep all things, including level : starting from 0. Later iteration ignore the level 0 directives.
27721// Should this be maintained by librose or user space code?
27722static std::unordered_map <PreprocessingInfo*, SageInterface::PreprocessingInfoData> infoMap;
27723
27724void SageInterface::preOrderCollectPreprocessingInfo(SgNode* current, vector<PreprocessingInfo*>& infoList, int depth)
27725{
27726 // stop condition
27727 if (current == NULL)
27728 return;
27729
27730 // Three possible locations: before, inside, and after
27731 // immediately add prepression info that is before and inside of current node
27732 // delayed additions of these that are located after the current node
27733 vector<PreprocessingInfo*> afterList;
27734 if (SgLocatedNode* locatedNode = isSgLocatedNode(current))
27735 {
27736 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
27737
27738 if (comments != nullptr)
27739 {
27740 AttachedPreprocessingInfoType::iterator i;
27741 int idx=0;
27742 for (i = comments->begin (); i != comments->end (); i++)
27743 {
27744 PreprocessingInfo* info= *i;
27745
27746 // prepare the data just in case
27748 data.container=comments;
27749 data.index = idx;
27750 data.depth = depth;
27751
27752 // put directives with before or inside location into the infoList
27753 if (info->getRelativePosition () == PreprocessingInfo::before||
27754 info->getRelativePosition () == PreprocessingInfo::inside)
27755 {
27756 infoList.push_back (info);
27757 infoMap[info] = data;
27758 }
27759 else if (info->getRelativePosition () == PreprocessingInfo::after)
27760 {
27761 afterList.push_back (info); // if attached to be after, save to afterList
27762 infoMap[info] = data;
27763 }
27764 else
27765 {
27766 cerr<<"Warning: unhandled relative position value:" <<info->getRelativePosition () <<endl;
27767 // ROSE_ASSERT (false); // Jovial has end_of
27768 }
27769
27770 idx++;
27771 } // end for
27772 }
27773 } // end if
27774
27775 // handling children nodes
27776 std::vector<SgNode* > children = current->get_traversalSuccessorContainer();
27777 for (auto c: children)
27778 preOrderCollectPreprocessingInfo (c, infoList, depth +1);
27779
27780 // append after locations after recursively handling children nodes.
27781 for (auto fi : afterList)
27782 infoList.push_back(fi);
27783}
27784
27785// This may be expensive to run since it is called anytime replace() is called.
27787// We need to attach them to be after lnode, before we can safely remove lnode. So the inner preprocessing info. can be preserved properly.
27788// This should be done before removing or replace the statement: lnode
27789// TODO: this may need to be a recursive function for multiple levels of nested directives.
27790//
27791// We only care about directives attached to inner nodes, not lnode : TODO: double check this for corner cases
27792//
27794{
27795 int retVal=0;
27796 ROSE_ASSERT(lnode);
27797
27798// algorithm: using a queue (vector to simulate it)
27799// queue <PreProcessingInfo* > q;
27800// start from 2nd node: ignore the first root node
27801// if start preprocessing info: (if, ifndef, ifdef), push to the end of q
27802// if end of preprocessing info. (endif), neturalize possible end p info at the end of q, otherwise push it to the end
27803//
27804// the queue in the end may contain mixed preprocessing info. #endif #endif ... #if #ifndef
27805// They cannot neutralize each other.
27806// They should be attached to be after lnode !
27807 RoseAst ast(lnode);
27808 RoseAst::iterator ast_i=ast.begin();
27809 ++ast_i; // skip the root node itself
27810
27811 // we store both the container and the element's index within the container. so later we can easily remove elements from containers
27812 vector < pair< AttachedPreprocessingInfoType*, int> > keepers; // preprocessing info. to be kept
27813 // for the middle directives like #else or #elif, sometimes their status (balanced or not) is directly associatd with its preceeding begin directive
27814 // it is not always an independent decision.
27815 // Note : the association is between individual preprocessing info. however, to faciliate removing them, the second part uses InfoList vs offset
27816 unordered_map < PreprocessingInfo * , vector< pair<AttachedPreprocessingInfoType*, int>> > associated_directives;
27817
27818 // store the associated middle directives what should be erased in the end
27819 // we have to store this separatedly since the begin diretive pinfo becomes NULL after they have been erased!
27820 // associated_directives[BeginInfo] will not retrieve them!
27821 vector< pair<AttachedPreprocessingInfoType*, int>> associated_erase;
27822
27823 // Two steps here
27824 // Step 1: We build the list first, then go through them to neutralize them
27825 // to simplify the problem: we exclude comments attached to the current located node, only consider things inside
27826 //
27827 // The list must provide the following information
27828 // infoList (container), index of the directive, PreprocessingInfo* itself
27829 vector<PreprocessingInfo*> candidateInfoList;
27830 // recursively search all directives, preserving original order in AST, consider attachment locations: before, inside and after.
27831 preOrderCollectPreprocessingInfo (lnode, candidateInfoList, 0);
27832 // now we have both candidateInfoList and infoMap.
27833
27834 for (auto candidate: candidateInfoList)
27835 {
27836 // fundamentally, we want to move individual PreprocessingInfo objects
27837 // Or just duplicate them (easier)
27838 PreprocessingInfo * info = candidate;
27839
27840 // we skip candidate that is attached to a node with depth of 0 (root node of the subtree)
27841 if (infoMap[info].depth ==0)
27842 continue;
27843
27844 int commentIndex = infoMap[info].index;
27845 AttachedPreprocessingInfoType* infoList = infoMap[info].container;
27846
27847 // begin directives
27848 if ( isBeginDirective(info) == 1)
27849 {
27850 keepers.push_back(make_pair (infoList,commentIndex));
27851 }
27852 // the middle #else, #elif,
27853 else if (isBeginDirective(info) == 2)
27854 {
27855 // two situtations for immediate decision of unbalanced status
27856 //1. empty stack, or
27857 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27858 if (keepers.size()==0)
27859 keepers.push_back(make_pair (infoList, commentIndex));
27860 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27861 {
27862 keepers.push_back(make_pair (infoList,commentIndex));
27863 }
27864 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27865 {
27866 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27867 // we associated this middle directive with the beginning directive
27868 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27869 }
27870 }
27871 // end directive
27872 else if ( isBeginDirective(info) == -1)
27873 {
27874 bool neutralized = false;
27875 // neutralize an internall matched pair, if any
27876 if (keepers.size()>0)
27877 {
27878 AttachedPreprocessingInfoType* comments = keepers.back().first;
27879 int idx = keepers.back().second;
27880
27881 if(isBeginDirective( (*comments)[idx] )==1)
27882 {
27883 keepers.pop_back();
27884 neutralized = true;
27885 }
27886 }
27887
27888 if (!neutralized)
27889 keepers.push_back(make_pair (infoList,commentIndex));
27890 }
27891
27892 }
27893
27894#if 0 // old and wrong linear search of directives
27895
27896 // Then we go through the list, extract keepers, neutralize anything else.
27897 for(;ast_i!=ast.end();++ast_i) {
27898 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27899 if (current ==NULL ) // skip non located nodes
27900 continue;
27901
27902 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27903 if (infoList == NULL) continue;
27904
27905 int commentIndex=0;
27906 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27907 {
27908 ROSE_ASSERT(*ci != NULL);
27909 // fundamentally, we want to move individual PreprocessingInfo objects
27910 // Or just duplicate them (easier)
27911 PreprocessingInfo * info = *ci;
27912
27913 // begin directives
27914 if ( isBeginDirective(info) == 1)
27915 {
27916 keepers.push_back(make_pair (infoList,commentIndex));
27917 }
27918 // the middle #else, #elif,
27919 else if (isBeginDirective(info) == 2)
27920 {
27921 // two situtations for immediate decision of unbalanced status
27922 //1. empty stack, or
27923 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27924 if (keepers.size()==0)
27925 keepers.push_back(make_pair (infoList,commentIndex));
27926 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27927 {
27928 keepers.push_back(make_pair (infoList,commentIndex));
27929 }
27930 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27931 {
27932 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27933 // we associated this middle directive with the beginning directive
27934 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27935 }
27936 }
27937 // end directive
27938 else if ( isBeginDirective(info) == -1)
27939 {
27940 bool neutralized = false;
27941 // neutralize an internall matched pair, if any
27942 if (keepers.size()>0)
27943 {
27944 AttachedPreprocessingInfoType* comments = keepers.back().first;
27945 int idx = keepers.back().second;
27946
27947 if(isBeginDirective( (*comments)[idx] )==1)
27948 {
27949 keepers.pop_back();
27950 neutralized = true;
27951 }
27952 }
27953
27954 if (!neutralized)
27955 keepers.push_back(make_pair (infoList,commentIndex));
27956 }
27957 commentIndex++;
27958 }
27959 }
27960#endif
27961// TODO this variable is not used in the end.
27962 set <AttachedPreprocessingInfoType*> relatedInfoList; // containers with comments to be moved
27963 // 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!
27964 // move from old containers, and add into lnode's after position
27965 for (auto ki = keepers.begin(); ki != keepers.end(); ki ++)
27966 {
27967 AttachedPreprocessingInfoType* infoList = (*ki).first;
27968 int cidx= (*ki).second;
27969 // TODO replace the code block below with moveInofListToNewPlace()
27970 relatedInfoList.insert (infoList);
27971
27972 PreprocessingInfo* info = (*infoList)[cidx];
27973 // rewrite relative position
27974 info->setRelativePosition(PreprocessingInfo::after);
27975
27976 // insert after lnode
27977 lnode->addToAttachedPreprocessingInfo (info);
27978 retVal++;
27979
27980 // we additionally process the associated directives, if any, TODO: reverse processing also??
27981 if (associated_directives.count (info)!=0)
27982 {
27983 vector<pair<AttachedPreprocessingInfoType*,int>> a_list_vec = associated_directives[info];
27984 for (auto vec_i = a_list_vec.rbegin(); vec_i != a_list_vec.rend(); vec_i ++ )
27985 {
27986 AttachedPreprocessingInfoType* a_infoList = (*vec_i).first;
27987 int aidx= (*vec_i).second;
27988 moveInofListToNewPlace (a_infoList, aidx, relatedInfoList, lnode, retVal);
27989 associated_erase.push_back(make_pair (a_infoList, aidx));
27990 }
27991 } // each begin directive may associate multiple other middle directives
27992
27993 // Doing this after the associated directives are processed.
27994 // zero out from original list, Note this element slot is NULL now!
27995 (*infoList)[cidx]= NULL;
27996
27997 }
27999 return retVal;
28000}
to specify a construct using a specifier Can be used alone or with parent handles when relative speci...
virtual void * getNode() const
Get the raw IR node associated with the current abstract node.
Base class for all IR node attribute values.
Attribute Evaluator for synthesized attributes.
SynthesizedAttributeType traverse(SgNode *node)
evaluates attributes on the entire AST
Attribute storing an SgNode.
Class for traversing the AST.
void traverse(SgNode *node, Order treeTraversalOrder)
traverse the entire AST. Order defines preorder (preorder) or postorder (postorder) traversal....
void visit(SgNode *astNode)
this method is called at every traversed node.
void visit(SgNode *astNode)
visitor function for each node to collect non-builtin types' declarations
void visit(SgNode *astNode)
this method is called at every traversed node.
For preprocessing information including source comments, include , if, define, etc.
RelativePositionType
MK: Enum type to store if the directive goes before or after the corresponding line of source code.
AST iterator.
Definition RoseAst.h:54
Interface for iterating over an AST.
Definition RoseAst.h:26
iterator begin()
Iterator positioned at root of subtree.
iterator end()
Iterator positioned at the end of the traversal.
const Digest & digest() override
Return the digest.
void insert(const std::string &x)
Insert data into the digest.
uint64_t make64Bits()
Returns the hash as a 64 bit int.
void visit(SgNode *node)
this method is called at every traversed node.
Interface for creating a statement whose computation writes its answer into a given variable.
A persistent attribute to represent a unique name for an expression.
SgName get_name() const override
Access function for getting name from declarations or types internally.
Base class for binary files.
SgAsmGenericHeaderList *const & get_headers() const
Property: List of all headers in file.
SgAsmGenericHeaderPtrList const & get_headers() const
Property: List of file header nodes.
Base class for container file headers.
SgAsmInterpretationPtrList const & get_interpretations() const
Property: Interpretation list.
Represents an interpretation of a binary container.
This class represents the concept of a C Assembler statement.
This class represents the rhs of a variable declaration which includes an optional assignment (e....
void set_operand(SgExpression *exp)
This sets the rhs expression.
SgExpression * get_operand() const
Returns the rhs.
This class represents the concept of a block (not a basic block from control flow analysis).
const SgStatementPtrList & get_statements() const
Returns a const STL list by reference.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a binary operator. It is derived from a SgExpression because oper...
SgExpression * get_lhs_operand() const
returns SgExpression pointer to the lhs operand associated with this binary operator.
void set_rhs_operand(SgExpression *exp)
This function allows the p_rhs_operand pointer to be set (used internally).
void set_lhs_operand(SgExpression *exp)
This function allows the p_lhs_operand pointer to be set (used internally).
SgExpression * get_rhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
SgExpression * get_lhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
virtual VariantT variantT() const override
returns new style SageIII enum values
SgExpression * get_rhs_operand() const
returns SgExpression pointer to the rhs operand associated with this binary operator.
This class represents a boolean value (expression value).
This class represents the notion of a break statement (typically used in a switch statment).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a C and C++ case option (used within a switch statement).
SgStatement * get_body() const
Returns pointer to a SgBasicBlock object.
void set_key(SgExpression *key)
Access function for pointer to SgExpression object wrapped by SgExpressionRoot in p_key_root.
void set_body(SgStatement *body)
Access function for p_body.
SgExpression * get_key() const
Returns pointer to a SgExpression object wrapped by SgExpressionRoot in p_key_root.
This class represents a cast of one type to another.
SgType * get_type() const override
unparsing support for pragmas
This class represents the concept of a catch within a try-catch construct used in C++ exception handl...
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Access function for p_body.
This class represents the concept of a class declaration statement. It includes the concept of an ins...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgScopeStatement * get_scope() const override
Returns scope of current statement.
This class represents the concept of a class definition in C++.
SgClassDeclaration * get_declaration() const
returns the class declaration associated with this class decinition.
const SgDeclarationStatementPtrList & get_members() const
Returns a const list to the data member declarations.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a C++ expression built from a class name.
SgClassSymbol * get_symbol() const
Returns pointer to SgSymbol.
This class represents the concept of a class name within the compiler.
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
static SgClassType * createType(SgDeclarationStatement *decl=NULL, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgClassType (types whose constructors take par...
This class represents the concept of a C trinary conditional expression (e.g. "test ?...
SgExpression * get_true_exp() const
Access function for p_true_exp.
void set_false_exp(SgExpression *false_exp)
Access function for p_false_exp.
SgExpression * get_conditional_exp() const
Access function for p_conditional_exp.
SgExpression * get_false_exp() const
Access function for p_false_exp.
void set_true_exp(SgExpression *true_exp)
Access function for p_true_exp.
void set_conditional_exp(SgExpression *conditional_exp)
Access function for p_conditional_exp.
This class represents the call of a class constructor to initialize a variable. For example "Foo foo;...
SgType * get_expression_type() const
Access function for p_expression_type, returns pointer to SgType associated with constructor.
This class represents the concept of a C or C++ continue statement.
Supporting class from copy mechanism within ROSE.
Definition sageCopy.h:26
This class represents the concept of a contructor initializer list (used in constructor (member funct...
bool isFriend() const
declaration modifier is friend.
This class represents the concept of a declaration statement.
SgSymbol * search_for_symbol_from_symbol_table() const
User interface for retrieving the associated symbol from the declaration.
void set_definingDeclaration(SgDeclarationStatement *definingDeclaration)
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
void set_firstNondefiningDeclaration(SgDeclarationStatement *firstNondefiningDeclaration)
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
SgDeclarationStatement * get_definingDeclaration() const
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
bool isForward() const
Returns boolean value indicating if this is a forward declaration.
SgDeclarationStatement * get_firstNondefiningDeclaration() const
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool hasAssociatedSymbol() const
Returns boolean value true of this type of declaration has an associated sysmbol.
SgName get_template_name() const
This function returns the template name (taken from the template declaration for the class,...
This class represents the concept of a C or C++ default case within a switch statement.
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Returns pointer to SgBasicBlock.
This class represents a directory within a projects file structure of files and directories.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_condition(SgStatement *condition)
Access function for p_condition.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the notion of an value (expression value).
This class represents the concept of an enum declaration.
SgScopeStatement * get_scope() const override
Access function for p_scope.
SgName get_name() const
Access function for p_name.
void set_scope(SgScopeStatement *scope) override
Access function for p_scope.
const SgInitializedNamePtrList & get_enumerators() const
Access function for p_enumerators.
This class represents the concept of a C and C++ expression list.
int replace_expression(SgExpression *o, SgExpression *n) override
This class represents the base class of all the expressions within this grammar.
This class represents the concept of a C or C++ statement which contains a expression.
This class represents the notion of an expression. Expressions are derived from SgLocatedNodes,...
virtual std::string class_name() const override
returns a string representing the class name
void set_need_paren(bool need_paren)
This function allows the p_need_paren flag to be set (used internally).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgType * get_type() const
unparsing support for pragmas
virtual int replace_expression(SgExpression *oldChild, SgExpression *newChild)
This class represents the base class of all the expressions within this grammar.
virtual const char * sage_class_name() const override
virtual Sg_File_Info * get_file_info(void) const override
Interface function to implement original SAGE interface to SgFile_Info objects.
void set_lvalue(bool lvalue)
This function allows the p_lvalue flag to be set (used internally).
bool get_lvalue() const
Returns a bool value if the current expression is assigned to.
This class represents a source file for a project (which may contian many source files and or directo...
std::string getFileName() const
associated filename
Sg_File_Info * get_file_info() const override
Access function calling get_startOfConstruct(), provided to support older interface.
This class represents the notion of an value (expression value).
This class represents the variable declaration or variable initialization withn a for loop.
const SgStatementPtrList & get_init_stmt() const
Returns const reference to a SgStatementPtrList (typedef to a STL list).
This class represents the concept of a for loop.
SgExpression * get_test_expr() const
Access function for p_test_expr_root.
SgForInitStatement * get_for_init_stmt() const
Access function for p_for_init_stmt.
void set_loop_body(SgStatement *loop_body)
Access function for p_loop_body.
SgStatement * get_loop_body() const
Access function for p_loop_body.
void set_for_init_stmt(SgForInitStatement *for_init_stmt)
Access function for p_for_init_stmt.
This class represents the concept of a C++ function call (which is an expression).
SgFunctionSymbol * getAssociatedFunctionSymbol() const
Returns the associated function symbol, if it can be resolved statically.
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a function declaration statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool isTemplateFunction() const
Determines if function is a template or non-template function.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
virtual std::string class_name() const override
returns a string representing the class name
SgBasicBlock * get_body() const
Access function for p_body.
This class represents the concept of a declaration list.
const SgInitializedNamePtrList & get_args() const
Access function for p_args.
const SgTypePtrList & get_arguments() const
Get a const list of input types (types of the parameters list) to this function type (from a cost fun...
This class represents the function being called and must be assembled in the SgFunctionCall with the ...
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the function type table (stores all function types so that they can be shared i...
SgSymbolTable * get_function_type_table() const
Returns pointer to SgSymbolTable used for function type symbols only.
This class represents a type for all functions.
virtual std::string class_name() const override
returns a string representing the class name
const SgTypePtrList & get_arguments() const
This is a const convience access function to the STL container of types in the child IR node (SgFunct...
virtual SgName get_mangled(void) const override
Mangled name support for unparser support.
This class represents the concept of a namespace definition.
virtual std::string class_name() const override
returns a string representing the class name
const SgDeclarationStatementPtrList & get_declarations() const
Returns a const list to the global scope declarations.
This class represents the concept of a C or C++ goto statement.
SgLabelStatement * get_label() const
Returns pointer to SgLabelStatement where control flow will be transfered during execution.
void set_label(SgLabelStatement *label)
Access function for p_label.
InheritedAttributeType traverse(SgGraphNode *basenode, SgIncidenceDirectedGraph *g, InheritedAttributeType inheritedValue, InheritedAttributeType nullInherit, SgGraphNode *endnode, bool insep=false, bool pcHk=false)
This is the function that is used by the user directly to start the algorithm.
This class represents the concept of an "if" construct.
void set_false_body(SgStatement *false_body)
Access function for p_false_body.
virtual std::string class_name() const override
returns a string representing the class name
void set_true_body(SgStatement *true_body)
Access function for p_true_body.
SgStatement * get_conditional() const
Access function for p_conditional.
SgStatement * get_true_body() const
Access function for p_true_body.
SgStatement * get_false_body() const
Access function for p_false_body.
void set_conditional(SgStatement *conditional)
Access function for p_conditional.
This class represents the notion of a declared variable.
SgName get_qualified_name() const
Returns the name with appropriate qualified names representing nested scopes.
SgSymbol * get_symbol_from_symbol_table() const
Get the associated SgSymbol from the symbol table located in the scope, without considering possible ...
virtual std::string class_name() const override
returns a string representing the class name
SgDeclarationStatement * get_declaration() const
Equal operator : it checks if all the data members are the same or point to the same objects.
This class represents the notion of an initializer for a variable declaration or expression in a func...
This class represents the concept of a C or C++ label statement.
SgName get_label() const
Returns SgName by value.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
label_type_enum
Type of label used (fortran only)
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of an expression or statement which has a position within the source...
virtual std::string class_name() const override
returns a string representing the class name
virtual const char * sage_class_name() const override
Sg_File_Info * get_endOfConstruct() const override
New function interface for Sg_File_Info data stores ending location of contruct (typically the closin...
void setTransformation()
Allow IR nodes (mostly SgLocatedNode) to be marked as a transformation.
virtual void addNewAttribute(std::string s, AstAttribute *a) override
Add a new attribute represented by the named string.
void set_endOfConstruct(Sg_File_Info *endOfConstruct)
This function sets the current source location position of the end of the current construct.
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
void addToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo::RelativePositionType locationInList=PreprocessingInfo::after)
This function adds comment or CPP directives to the current IR node.
virtual AstAttribute * getAttribute(std::string s) const override
Returns attribute of name 's'.
void set_startOfConstruct(Sg_File_Info *startOfConstruct)
This function sets the current source location position of the start of the current construct.
bool isCompilerGenerated() const
Simple test for if this is a compiler generated node.
void insertToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo *anchorInfoPtr, bool insertAfter=true)
Insert prepInfo After (or before if last parameter is false) an anchor info ptr in the list of prepro...
virtual VariantT variantT() const override
returns new style SageIII enum values
void setOutputInCodeGeneration()
Allow IR nodes (mostly SgLocatedNode) to be marked as to when the information was unavilable in the f...
virtual Sg_File_Info * get_file_info() const override
Interface function to implement original SAGE interface to SgFile_Info objects.
bool isTransformation() const
Simple test for if this is a part of a transformation.
AttachedPreprocessingInfoType *& getAttachedPreprocessingInfo(void)
Computes the number of nodes in the defined subtree of the AST.
This class represents the notion of an value (expression value).
This class represents the concept of a member function declaration statement.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the member function being called and must be assembled in the SgFunctionCall wi...
SgMemberFunctionDeclaration * getAssociatedMemberFunctionDeclaration() const
This is helpful in chasing down the associated declaration to this member function reference.
SgName get_name() const override
Access function for getting name from declarations or types internally.
SgTypeModifier & get_typeModifier()
Access function for modifier.
This class represents strings within the IR nodes.
virtual SgName get_name() const
Gets name of the type (useful for debugging, unparsing, etc.)
SgName get_qualified_name() const
Used for the SgNamedType object (base class for the SgClassType, SgTypedefType and the SgEnumType obj...
This class represents the concept of a C++ namespace alias declaration statement.
SgName get_name() const
Access function for p_name.
SgNamespaceDeclarationStatement * get_namespaceDeclaration() const
Access function for p_namespaceDeclaration.
This class represents the concept of a C++ namespace declaration.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgName get_name() const
Access function for p_name.
SgNamespaceDefinitionStatement * get_definition() const
Returns pointer to SgNamespaceDefinitionStatement.
This class represents the concept of a namespace definition.
This class represents the concept of a namespace name within the compiler.
This class represents the base class for all IR nodes within Sage III.
static SgTypeTable * get_globalTypeTable()
Access function for symbol table specific to non-function types.
virtual std::vector< std::string > get_traversalSuccessorNamesContainer()
container of names of variables or container indices used used in the traversal to access AST success...
SgNode * get_parent() const
Access function for parent node.
void set_isModified(bool isModified)
All nodes in the AST contain a isModified flag used to track changes to the AST.
virtual VariantT variantT() const
returns new style SageIII enum values
void set_parent(SgNode *parent)
All nodes in the AST contain a reference to a parent node.
virtual std::string unparseToString(SgUnparse_Info *info) const
This function unparses the AST node (excluding comments and unnecessary white space)
virtual std::vector< SgNode * > get_traversalSuccessorContainer()
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
virtual std::string class_name() const
returns a string representing the class name
static std::map< SgNode *, std::string > & get_globalMangledNameMap()
Access function for performance optimizing global mangled name map.
virtual void checkDataMemberPointersIfInMemoryPool()
FOR INTERNAL USE This is used in internal tests to verify that all IR nodes are allocated from the he...
virtual AstAttribute * getAttribute(std::string s) const
Returns attribute of name 's'.
static SgFunctionTypeTable * get_globalFunctionTypeTable()
Access function for symbol table specific to function types.
virtual Sg_File_Info * get_file_info(void) const
File information containing filename, line number, column number, and if the SgNode is a part of a ne...
virtual bool attributeExists(std::string s) const
Tests if attribute of name 's' is present.
virtual std::vector< std::pair< SgNode *, std::string > > returnDataMemberPointers() const
FOR INTERNAL USE Returns STL vector of pairs of SgNode* and strings for use in AST tools
virtual void addNewAttribute(std::string s, AstAttribute *a)
Add a new attribute represented by the named string.
static std::map< std::string, uint64_t > & get_shortMangledNameCache()
Access function for lower level optimizing of global mangled name map.
bool get_isModified() const
Acess function for isModified flag.
SgName get_name() const override
Support for some classes which have pure virtual function in base classes.
This class represents the concept of a C Assembler statement (untested).
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents a source project, with a list of SgFile objects and global information about th...
std::vector< std::string > getAbsolutePathFileNames() const
This function generates a list of files resolved to absolute paths (symbolic links should not be reso...
static void visitRepresentativeNode(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for type-based traversal.
static int get_verbose(void)
DQ: Modified to accept a value on the command line (no longer a boolean variable) value of 0 means qu...
This class represents a OLD concept of the structure require for qualified names when they were in th...
This class represents the concept of a C Assembler statement (untested).
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
bool supportsDefiningFunctionDeclaration()
Reports if scope can support defining function declarations. Not all scopes permit function declarati...
const SgStatementPtrList generateStatementList() const
Generate s list of statements from either the existing list of statements or the list of declarations...
bool isNamedScope()
Some scopes have associated names for purposed of name qualification. This returns true if the scope ...
SgSymbolTable * get_symbol_table() const
Returns a pointer to the locally strored SgSymbolTable.
virtual const char * sage_class_name() const override
SgDeclarationStatementPtrList & getDeclarationList()
Gets reference to internal STL list of pointers to SgDeclarationStatement objects (only defined for s...
SgStatementPtrList & getStatementList()
Gets reference to internal STL list of pointers to SgStatement objects (only defined for scopes conta...
void append_statement(SgStatement *stmt)
Higher level function to handle statements and declarations is scopes.
void set_symbol_table(SgSymbolTable *symbol_table)
Sets the pointer to the locally strored SgSymbolTable.
virtual std::string class_name() const override
returns a string representing the class name
bool statementExistsInScope(SgStatement *statement)
Test for existence of statement is scope.
bool containsOnlyDeclarations() const
This function is used to indicate if either the getDeclarationList() or getStatementList() can be cal...
void insert_symbol(const SgName &n, SgSymbol *s)
Puts a SgSymbol object into the local symbol table.
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgName get_qualified_name() const
Returns SgName (a string) representing the name of the current scope.
This class represents the "sizeof()" operator (applied to any type).
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a statement.
virtual std::string class_name() const override
returns a string representing the class name
void insert_statement(SgStatement *target, SgStatement *newstmt, bool inFront=true)
This function inserts a single statement at the position indicated by target.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() override
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
virtual void set_scope(SgScopeStatement *newScope)
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual bool hasExplicitScope() const
Support for where the scope is explicitly required.
virtual SgSymbol * get_symbol_from_symbol_table() const
Get the associated symbol from the symbol table in the stored scope.
virtual SgScopeStatement * get_scope(void) const
Returns scope of current statement.
void remove_statement(SgStatement *)
This function removes the target statement from the AST.
void replace_statement(SgStatement *target, SgStatement *newstmt)
This function replaces the target statement with a single statement.
virtual VariantT variantT() const override
returns new style SageIII enum values
bool isStatic() const
Storage modifier is static (always false for the SgStorageModifier in the SgInitializedName).
This class represents the base class of a numbr of IR nodes that don't otherwise fit into the existin...
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a switch.
void set_item_selector(SgStatement *item_selector)
Access function for p_item_selector.
SgStatement * get_body() const
Access function for p_body.
SgStatement * get_item_selector() const
Access function for p_item_selector_root.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the symbol tables used in both SgScopeStatement and the SgFunctionTypeSymbolTab...
std::set< SgNode * > get_symbols() const
Complexity O(n)
void print(std::string label, VariantT nodeType=V_SgSymbol)
Outputs symbol table information (useful for debugging)
int size() const
Computes the number of symbols in the symbol table (forced to count them, I think,...
void remove(const SgSymbol *symbol)
Complexity O(n)
This class represents the concept of a name within the compiler.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgName get_name() const =0
Access function for getting name from declarations or types internally.
virtual SgType * get_type() const =0
This function returns the type associated with the named entity.
This class represents template argument within the use of a template to build an instantiation.
SgExpression * get_expression() const
This function returns argumentExpression.
SgType * get_type() const
This function returns argumentType.
SgTemplateArgument::template_argument_enum get_argumentType() const
This function returns argumentType.
This class represents the concept of a template declaration.
SgName get_string() const
Returns stringified template declaration.
virtual std::string class_name() const override
returns a string representing the class name
SgName get_name() const
Returns name of template declaration.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of an instantiated class template.
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgName get_templateName() const
Returns name of class template, the name excludes template arguments.
SgTemplateClassDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
This class represents the concept of a class definition in C++.
This class represents the concept of a C++ template instantiation directive.
SgDeclarationStatement * get_declaration() const
Returns pointer to SgDeclarationStatement.
This class represents the concept of an instantiation of function template.
virtual std::string class_name() const override
returns a string representing the class name
const SgTemplateArgumentPtrList & get_templateArguments() const
Returns pointer to STL list of pointers to SgTemplateArgument objects.
SgTemplateFunctionDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
SgName get_templateName() const
Returns name of instantiated function template, name includes template arguments.
This class represents the concept of an instantiation of member function template or a member functio...
virtual std::string class_name() const override
returns a string representing the class name
const SgTemplateArgumentPtrList & get_templateArguments() const
Returns pointer to STL list of pointers to SgTemplateArgument objects.
SgName get_templateName() const
Returns name of instantiated function template, name includes template arguments.
SgTemplateMemberFunctionDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the "this" operator (can be applied to any member data).
Supporting class for "Deep" copies of the AST.
Definition sageCopy.h:86
static SgTypeBool * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
static SgTypeInt * createType(int sz=0, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgTypeInt (types whose constructors take param...
static SgTypeUnknown * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
static SgTypeVoid * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
This class represents the base class for all types.
std::vector< SgType * > getInternalTypes() const
Generate a container of types hidden in the input type.
SgType * stripType(unsigned char bit_array=STRIP_MODIFIER_TYPE|STRIP_REFERENCE_TYPE|STRIP_RVALUE_REFERENCE_TYPE|STRIP_POINTER_TYPE|STRIP_ARRAY_TYPE|STRIP_TYPEDEF_TYPE|STRIP_POINTER_MEMBER_TYPE) const
Returns hidden type beneath layers of typedefs, pointers, references, modifiers, array representation...
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of a typedef declaration.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgDeclarationStatement * get_baseTypeDefiningDeclaration() const
Returns the defining declaration if get_typedefBaseTypeContainsDefiningDeclaration() is true,...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
SgType * get_base_type() const
This is used in the SgTypedefType object (is not associated with a base_type data field)
void set_operand_i(SgExpression *operand_i)
This function allows the p_operand_i pointer to be set (used internally).
SgExpression * get_operand() const
returns SgExpression pointer to the operand associated with this unary operator.
This class represents the concept of a C++ using declaration.
SgDeclarationStatement * get_declaration() const
Access function for p_declaration.
SgInitializedName * get_initializedName() const
Access function for p_initializedName.
This class represents the concept of a C++ using directive.
SgNamespaceDeclarationStatement * get_namespaceDeclaration() const
Access function for p_namespaceDeclaration.
This class represents the notion of an value (expression value).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
This class represents the variable refernece in expressions.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the concept of a C or C++ variable declaration.
const SgInitializedNamePtrList & get_variables() const
Access function for p_variables.
SgDeclarationStatement * get_baseTypeDefiningDeclaration() const
Returns the defining declaration if get_variableDeclarationContainsBaseTypeDefiningDeclaration() is t...
bool get_variableDeclarationContainsBaseTypeDefiningDeclaration() const
Access function for p_variableDeclarationContainsBaseTypeDefiningDeclaration.
This class represents the definition (initialization) of a variable.
SgInitializedName * get_vardefn() const
Access function for SgInitializedName stored in p_vardefn.
This class represents the concept of a variable name within the compiler (a shared container for the ...
virtual std::string class_name() const override
returns a string representing the class name
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
void set_condition(SgStatement *condition)
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the location of the code associated with the IR node in the original source cod...
void setTransformation()
Marks an IR node to be a transformation if it is not one already.
const char * get_filename() const
Returns filename of source code associated with IR node.
bool isOutputInCodeGeneration() const
Returns true only if required to be unparsed in generated code.
int get_line() const
Returns the line number of the associated code for this IR node.
bool isCompilerGenerated() const
Returns true only if compiler generated (either by the front-end or by ROSE).
int get_col() const
Returns the column number of the associated code for this IR node.
static Sg_File_Info * generateDefaultFileInfoForTransformationNode()
Static function to return new Sg_File_Info object set to default values appropriate for transformatio...
bool isTransformation() const
Access function for classification bit field.
bool isShared() const
Returns true only if shared internally (either by the front-end or by ROSE).
static Sg_File_Info * generateDefaultFileInfo()
Static function to return new Sg_File_Info object set to default values.
void setOutputInCodeGeneration()
Marks IR node as compiler generated but required in the generated source (e.g. requied templates).
Hash table support for symbol tables within ROSE.
ROSE_DLL_API abstract_handle * buildAbstractHandle(SgNode *snode)
A default builder function handles all details: file use name, others use numbering
ROSE_DLL_API std::vector< std::string > generateSourceFilenames(std::vector< std::string > argList, bool binaryMode)
Build the list of isolated file names from the command line.
ROSE_UTIL_API void removeAllFileNamesExcept(std::vector< std::string > &argv, std::vector< std::string > filenameList, std::string exceptFilename)
Remove file names specified in filenameList from argv, except for 'exceptFilename'.
void edgePointerReplacement(replacement_map_t const &)
For all nodes in the memory pool, it looks for the edges in the replacement map. If a match is found ...
ROSE_DLL_API std::string toBase62String(uint64_t num)
Converts a 64 bit in to base 62 (All letters and numbers).
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
Definition sageBuilder.C:58
void serialize(std::ostream &output, Graph &graph)
Serialize a graph into a stream of bytes.
ROSE_UTIL_API std::string stripFileSuffixFromFileName(const std::string &fileNameWithSuffix)
Get the file name without the ".suffix".
ROSE_UTIL_API std::string numberToString(long long)
Convert an integer to a string.
ROSE_UTIL_API std::string copyEdit(const std::string &inputString, const std::string &oldToken, const std::string &newToken)
Replace all occurrences of a string with another string.
ROSE_UTIL_API std::string stripPathFromFileName(const std::string &fileNameWithPath)
Returns the last component of a path in a filesystem.
The ROSE library.
SgStatement * getPreviousStatement(SgStatement *targetStatement, bool climbOutScope=true)
Functions to move to SgStatement object in SAGE III later.
Functions that build an AST.
Definition sageBuilder.h:32
ROSE_DLL_API SgAddOp * buildAddOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgFunctionDeclaration * buildNondefiningFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope=NULL, SgExprListExp *decoratorList=NULL, bool buildTemplateInstantiation=false, SgTemplateArgumentPtrList *templateArgumentsList=NULL, SgStorageModifier::storage_modifier_enum sm=SgStorageModifier::e_default)
Build a prototype for a function, handle function type, symbol etc transparently.
SourcePositionClassification
intended to be a private member, don't access it directly. could be changed any time
@ e_sourcePosition_last
Specify as source position to be filled in as part of AST construction in the front-end.
@ e_sourcePositionNullPointers
Classify as compiler generated code (e.g. template instantiation).
@ e_sourcePositionCompilerGenerated
Classify as a transformation.
@ e_sourcePositionFrontendConstruction
Set pointers to Sg_File_Info objects to NULL.
@ e_sourcePositionDefault
Error value for enum.
@ e_sourcePositionTransformation
Default source position.
ROSE_DLL_API SgPragma * buildPragma(const std::string &name)
Build SgPragma.
ROSE_DLL_API SourcePositionClassification getSourcePositionClassificationMode()
Get the current source position classification (defines how IR nodes built by the SageBuilder interfa...
ROSE_DLL_API SgEqualityOp * buildEqualityOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgTemplateMemberFunctionDeclaration * buildNondefiningTemplateMemberFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope, SgExprListExp *decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList *templateParameterList)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgLabelStatement * buildLabelStatement(const SgName &name, SgStatement *stmt=NULL, SgScopeStatement *scope=NULL)
Build a label statement, name is the label's name. Handling label symbol and scope internally.
ROSE_DLL_API SgAddressOfOp * buildAddressOfOp(SgExpression *op=NULL)
ROSE_DLL_API SgTemplateFunctionDeclaration * buildNondefiningTemplateFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope=NULL, SgExprListExp *decoratorList=NULL, SgTemplateParameterPtrList *templateParameterList=NULL)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgMultiplyOp * buildMultiplyOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgGotoStatement * buildGotoStatement(SgLabelStatement *label=NULL)
Build a goto statement.
ROSE_DLL_API std::string display(SourcePositionClassification &scp)
display function for debugging
ROSE_DLL_API SgLabelRefExp * buildLabelRefExp(SgLabelSymbol *s)
Build a Fortran numeric label ref exp.
ROSE_DLL_API SgLessOrEqualOp * buildLessOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgSubtractOp * buildSubtractOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgMemberFunctionType * buildMemberFunctionType(SgType *return_type, SgFunctionParameterTypeList *typeList, SgScopeStatement *struct_name, unsigned int mfunc_specifier)
Built in simple types.
ROSE_DLL_API SgWhileStmt * buildWhileStmt(SgStatement *condition, SgStatement *body, SgStatement *else_body=NULL)
Build while statement.
ROSE_DLL_API SgForStatement * buildForStatement(SgStatement *initialize_stmt, SgStatement *test, SgExpression *increment, SgStatement *loop_body, SgStatement *else_body=NULL)
Build a for statement, assume none of the arguments is NULL.
ROSE_DLL_API SgEmptyDeclaration * buildEmptyDeclaration()
Build an empty declaration (useful for adding precission to comments and CPP handling under token-bas...
ROSE_DLL_API SgConditionalExp * buildConditionalExp(SgExpression *test=NULL, SgExpression *a=NULL, SgExpression *b=NULL)
Build a conditional expression ?:
ROSE_DLL_API SgTypeInt * buildIntType()
Built in simple types.
SourcePositionClassification SourcePositionClassificationMode
C++ SageBuilder namespace specific state for storage of the source code position state (used to contr...
ROSE_DLL_API SgMinusOp * buildMinusOp(SgExpression *op=NULL)
ROSE_DLL_API SgExprListExp * buildExprListExp(SgExpression *expr1=NULL, SgExpression *expr2=NULL, SgExpression *expr3=NULL, SgExpression *expr4=NULL, SgExpression *expr5=NULL, SgExpression *expr6=NULL, SgExpression *expr7=NULL, SgExpression *expr8=NULL, SgExpression *expr9=NULL, SgExpression *expr10=NULL)
Build a SgExprListExp, used for function call parameter list etc.
ROSE_DLL_API SgPlusAssignOp * buildPlusAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgVarRefExp * buildVarRefExp(const SgName &name, SgScopeStatement *scope=NULL)
Build SgVarRefExp based on a variable's Sage name. It will lookup the name in the symbol table intern...
bool symbol_table_case_insensitive_semantics
Support for construction of case sensitive/insensitive symbol table handling in scopes.
ROSE_DLL_API SgDotExp * buildDotExp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgAssignInitializer * buildAssignInitializer(SgExpression *operand_i=NULL, SgType *expression_type=NULL)
Build the rhs of a variable declaration which includes an assignment.
ROSE_DLL_API SgArrayType * getUniqueJavaArrayType(SgType *, int)
Build a SgFile node and attach it to SgProject.
ROSE_DLL_API SgVariableDeclaration * buildVariableDeclaration(const SgName &name, SgType *type, SgInitializer *varInit=NULL, SgScopeStatement *scope=NULL)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgScopeStatement * topScopeStack()
intended to be a private member, don't access it directly. could be changed any time
ROSE_DLL_API SgNullExpression * buildNullExpression()
Build a null expression, set file info as the default one.
ROSE_DLL_API SgGreaterOrEqualOp * buildGreaterOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgReferenceType * buildReferenceType(SgType *base_type=nullptr)
Build a reference type.
ROSE_DLL_API SgExprStatement * buildExprStatement(SgExpression *exp=NULL)
Build a SgExprStatement, set File_Info automatically.
ROSE_DLL_API SgIfStmt * buildIfStmt(SgStatement *conditional, SgStatement *true_body, SgStatement *false_body)
Build if statement.
ROSE_DLL_API SgFunctionParameterList * buildFunctionParameterList(SgInitializedName *in1=NULL, SgInitializedName *in2=NULL, SgInitializedName *in3=NULL, SgInitializedName *in4=NULL, SgInitializedName *in5=NULL, SgInitializedName *in6=NULL, SgInitializedName *in7=NULL, SgInitializedName *in8=NULL, SgInitializedName *in9=NULL, SgInitializedName *in10=NULL)
Build an empty SgFunctionParameterList, possibly with some initialized names filled in.
ROSE_DLL_API SgPointerDerefExp * buildPointerDerefExp(SgExpression *op=NULL)
ROSE_DLL_API SgTypeBool * buildBoolType()
Built in simple types.
ROSE_DLL_API SgAssignOp * buildAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgPointerType * buildPointerType(SgType *base_type=nullptr)
Build a pointer type.
ROSE_DLL_API SgBoolValExp * buildBoolValExp(int value=0)
Build a bool value expression, the name convention of SgBoolValExp is little different from others fo...
ROSE_DLL_API SgFunctionParameterTypeList * buildFunctionParameterTypeList(SgFunctionParameterList *paralist)
Build SgFunctionParameterTypeList from SgFunctionParameterList.
ROSE_DLL_API SgLessThanOp * buildLessThanOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgCastExp * buildCastExp(SgExpression *operand_i=NULL, SgType *expression_type=NULL, SgCastExp::cast_type_enum cast_type=SgCastExp::e_C_style_cast)
Build a type casting expression.
ROSE_DLL_API SgMinusAssignOp * buildMinusAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgDivideOp * buildDivideOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgBasicBlock * buildBasicBlock(SgStatement *stmt1=NULL, SgStatement *stmt2=NULL, SgStatement *stmt3=NULL, SgStatement *stmt4=NULL, SgStatement *stmt5=NULL, SgStatement *stmt6=NULL, SgStatement *stmt7=NULL, SgStatement *stmt8=NULL, SgStatement *stmt9=NULL, SgStatement *stmt10=NULL)
Build a SgBasicBlock, setting file info internally.
ROSE_DLL_API SgModOp * buildModOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgExprStatement * buildAssignStatement(SgExpression *lhs, SgExpression *rhs)
Build an assignment statement from lefthand operand and right hand operand.
ROSE_DLL_API SgMemberFunctionDeclaration * buildNondefiningMemberFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope, SgExprListExp *decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList *templateArgumentsList)
Build a prototype member function declaration.
ROSE_DLL_API SgMemberFunctionDeclaration * buildDefaultConstructor(SgClassType *classType)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgCommaOpExp * buildCommaOpExp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgIntVal * buildIntVal(int value=0)
Build an integer value expression.
SgDeclarationStatement * associatedDeclaration(const SgSymbol &n)
returns the associated declaration for symbol n or nullptr if there is none.
Functions that are useful when operating on the AST.
Definition sageBuilder.h:25
ROSE_DLL_API void checkSgNodePointers()
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool isLastStatement(SgStatement *stmt)
Check if a statement is the last statement within its closed scope.
ROSE_DLL_API bool isUnionDeclaration(SgNode *node)
Check if a SgNode is a declaration for a union.
ROSE_DLL_API void translateScopeToUseCppDeclarations(SgScopeStatement *scope)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
void initializeIfStmt(SgIfStmt *ifstmt, SgStatement *conditional, SgStatement *true_body, SgStatement *false_body)
Support function used for variable declarations in conditionals.
ROSE_DLL_API void deepDelete(SgNode *root)
Deep delete a sub AST tree. It uses postorder traversal to delete each child node....
void annotateExpressionsWithUniqueNames(SgProject *project)
Generate unique names for expressions and attach the names as persistent attributes ("UniqueNameAttri...
ROSE_DLL_API bool hasMultipleInitStatmentsOrExpressions(SgForStatement *for_loop)
Check if a for loop uses C99 style initialization statement with multiple expressions like for (int i...
ROSE_DLL_API void fixNamespaceDeclaration(SgNamespaceDeclarationStatement *structDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
void serialize(SgNode *node, std::string &prefix, bool hasRemaining, std::ostringstream &out, std::string &edgeLabel)
we have two serialize() functions, one for a single node, the other for a list of pointers
ROSE_DLL_API void deleteExpressionTreeWithOriginalExpressionSubtrees(SgNode *root)
Special purpose function for deleting AST expression tress containing valid original expression trees...
void setSourcePositionAsTransformation(SgNode *node)
DQ (5/1/2012): New function with improved name.
ROSE_DLL_API void insertStatementList(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmts, bool insertBefore=true)
Insert a list of statements before or after the target statement within the.
void whereAmI(SgNode *node)
Diagnostic function for tracing back through the parent list to understand at runtime where in the AS...
ROSE_DLL_API SgStatement * getLastStatement(SgScopeStatement *scope)
get the last statement within a scope, return NULL if it does not exit
ROSE_DLL_API void addStepToLoopBody(SgScopeStatement *loopStmt, SgStatement *step)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API bool is_UPC_dynamic_threads()
ROSE_DLL_API SgFunctionDeclaration * getFunctionDeclaration(SgFunctionCallExp *functionCallExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_mixed_Fortran_and_C_language()
ROSE_DLL_API void addTextForUnparser(SgNode *astNode, std::string s, AstUnparseAttribute::RelativePositionType inputlocation)
Add a string to be unparsed to support code generation for back-end specific tools or compilers.
ROSE_DLL_API std::string getTempDirectory(SgProject *project)
Create a temporary directory if it does not yet exist and return its name.
ROSE_DLL_API void displayScope(SgScopeStatement *scope)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_Jovial_language()
ROSE_DLL_API SgMemberFunctionDeclaration * findJavaMain(SgClassDefinition *)
Find a main method in a Java class.
ROSE_DLL_API bool is_Cxx_language()
void resetScopeNumbers(SgFunctionDefinition *functionDeclaration)
Assigns unique numbers to each SgScopeStatement of a function.
ROSE_DLL_API SgFunctionDeclaration * replaceDefiningFunctionDeclarationWithFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool hasSameGlobalScope(SgStatement *statement_1, SgStatement *statement_2)
This is supporting the recognition of functions in header files from two different ASTs.
SgCommaOpExp * insertBeforeUsingCommaOp(SgExpression *new_exp, SgExpression *anchor_exp)
Insert an expression (new_exp )before another expression (anchor_exp) has possible side effects,...
ROSE_DLL_API void fixFunctionDeclaration(SgFunctionDeclaration *stmt, SgScopeStatement *scope)
Fix the symbol table and set scope (only if scope in declaration is not already set).
ROSE_DLL_API std::string preprocessImport(SgProject *, std::string)
Using the import_string parameter, create a file with the relevant import statement; translate the fi...
ROSE_DLL_API bool collectReadWriteRefs(SgStatement *stmt, std::vector< SgNode * > &readRefs, std::vector< SgNode * > &writeRefs, bool useCachedDefUse=false)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void prependStatementList(const std::vector< SgStatement * > &stmt, SgScopeStatement *scope=NULL)
prepend a list of statements to the beginning of the current scope, handling side effects as appropri...
ROSE_DLL_API SgInitializer * getInitializerOfExpression(SgExpression *n)
Get the initializer containing an expression if it is within an initializer.
ROSE_DLL_API std::vector< SgInitializedName * > getInParameters(const SgInitializedNamePtrList &params)
Get a vector of Jovial input parameters from the function parameter list (may work for Fortran in the...
ROSE_DLL_API bool language_may_contain_nondeclarations_in_scope()
ROSE_DLL_API std::set< SgStatement * > collectTransformedStatements(SgNode *node)
This collects the statements that are marked as transformed (useful in debugging).
ROSE_DLL_API void cleanupNontransformedBasicBlockNode()
Remove unused basic block IR nodes added as part of normalization.
ROSE_DLL_API bool skipTranslateToUseCppDeclaration(PreprocessingInfo *currentPreprocessingInfo)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API AbstractHandle::abstract_handle * buildAbstractHandle(SgNode *)
Build an abstract handle from an AST node, reuse previously built handle when possible.
ROSE_DLL_API void insertStatementListBefore(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmts)
Insert a list of statements before a target statement.
ROSE_DLL_API void fixStructDeclaration(SgClassDeclaration *structDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
void recursivePrintCurrentAndParent(SgNode *n)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void appendExpressionList(SgExprListExp *, const std::vector< SgExpression * > &)
Append an expression list to a SgExprListExp, set the parent pointers also.
ROSE_DLL_API void collectReadOnlySymbols(SgStatement *stmt, std::set< SgVariableSymbol * > &readOnlySymbols, bool coarseGrain=true)
Collect read only variable symbols within a statement. The statement can be either of a function,...
bool isOverloaded(SgFunctionDeclaration *functionDeclaration)
Return true if function is overloaded.
ROSE_DLL_API int set_name(SgInitializedName *initializedNameNode, SgName new_name)
set_name of symbol in symbol table.
ROSE_DLL_API SgClassDefinition * findOrInsertJavaPackage(SgProject *, std::string, bool create_directory=false)
Process a qualified package name, if needed, and return its package definition.
ROSE_DLL_API SgClassDeclaration * findOrImportJavaClass(SgProject *, SgClassDefinition *package_definition, std::string)
If the class_name already exists in the scope, return it.
ROSE_DLL_API SgVariableSymbol * getFirstVarSym(SgVariableDeclaration *decl)
Get the variable symbol for the first initialized name of a declaration stmt.
ROSE_DLL_API bool templateArgumentEquivalence(SgTemplateArgument *arg1, SgTemplateArgument *arg2)
Verify that 2 SgTemplateArgument are equivalent (same type, same expression, or same template declara...
ROSE_DLL_API SgFunctionDeclaration * findFirstDefiningFunctionDecl(SgScopeStatement *scope)
Find the first defining function declaration statement in a scope.
ROSE_DLL_API bool is_Jvm_language()
void addMessageStatement(SgStatement *stmt, std::string message)
Function to add "C" style comment to statement.
ROSE_DLL_API bool isLoopIndexVariable(SgInitializedName *ivar, SgNode *subtree_root)
Check if a SgInitializedName is used as a loop index within a AST subtree This function will use a bo...
SgInitializedName & getFirstVariable(SgVariableDeclaration &vardecl)
convenience function that returns the first initialized name in a list of variable declarations.
void initializeSwitchStatement(SgSwitchStatement *switchStatement, SgStatement *item_selector, SgStatement *body)
Support function used for variable declarations in conditionals.
SgExprListExp * loopCollapsing(SgForStatement *target_loop, size_t collapsing_factor)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API void fixStatement(SgStatement *stmt, SgScopeStatement *scope)
A wrapper containing fixes (fixVariableDeclaration(),fixStructDeclaration(), fixLabelStatement(),...
ROSE_DLL_API SgStatement * copyStatement(SgStatement *s)
Deep copy a statement.
ROSE_DLL_API int eraseNullPreprocessingInfo(SgLocatedNode *lnode)
Dumps a located node's preprocessing information.
ROSE_DLL_API bool isCanonicalDoLoop(SgFortranDo *loop, SgInitializedName **ivar, SgExpression **lb, SgExpression **ub, SgExpression **step, SgStatement **body, bool *hasIncrementalIterationSpace, bool *isInclusiveUpperBound)
Check if a Fortran Do loop has a complete canonical form: Do I=1, 10, 1.
SgCommaOpExp * insertAfterUsingCommaOp(SgExpression *new_exp, SgExpression *anchor_exp, SgStatement **temp_decl=NULL, SgVarRefExp **temp_ref=NULL)
Insert an expression (new_exp ) after another expression (anchor_exp) has possible side effects,...
ROSE_DLL_API SgTemplateVariableSymbol * lookupTemplateVariableSymbolInParentScopes(const SgName &name, SgTemplateParameterPtrList *tplparams, SgTemplateArgumentPtrList *tplargs, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void moveUpPreprocessingInfo(SgStatement *stmt_dst, SgStatement *stmt_src, PreprocessingInfo::RelativePositionType src_position=PreprocessingInfo::undef, PreprocessingInfo::RelativePositionType dst_position=PreprocessingInfo::undef, bool usePrepend=false)
Identical to movePreprocessingInfo(), except for the stale name and confusing order of parameters....
ROSE_DLL_API SgStatement * lastStatementOfScopeWithTokenInfo(SgScopeStatement *scope, std::map< SgNode *, TokenStreamSequenceToNodeMapping * > &tokenStreamSequenceMap)
Used to support token unparsing (when the output the trailing token sequence).
ROSE_DLL_API void cutPreprocessingInfo(SgLocatedNode *src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType &save_buf)
Cut preprocessing information from a source node and save it into a buffer. Used in combination of pa...
ROSE_DLL_API bool normalizeForLoopTest(SgForStatement *loop)
Normalize a for loop's test expression i<x is normalized to i<= (x-1) and i>x is normalized to i>= (x...
bool declarationPreceedsDefinition(SgDeclarationStatement *nonDefiningDeclaration, SgDeclarationStatement *definingDeclaration)
Check if a defining declaration comes before of after the non-defining declaration.
ROSE_DLL_API bool isSameFunction(SgFunctionDeclaration *func1, SgFunctionDeclaration *func2)
Check if two function declarations refer to the same one. Two function declarations are the same when...
std::vector< SgVariableSymbol * > getSymbolsUsedInExpression(SgExpression *expr)
Find referenced symbols within an expression.
ROSE_DLL_API bool isStructDeclaration(SgNode *node)
Check if a SgNode is a declaration for a structure.
ROSE_DLL_API void moveVariableDeclaration(SgVariableDeclaration *decl, SgScopeStatement *target_scope)
Move a variable declaration to a new scope, handle symbol, special scopes like For loop,...
ROSE_DLL_API std::string preprocessPackage(SgProject *, std::string)
Using the package_name, create a file with a package statement, translate it in order to load the pac...
ROSE_DLL_API void setOneSourcePositionForTransformation(SgNode *root)
Set current node's source position as transformation generated.
NodeType * deepCopy(const NodeType *subtree)
A template function for deep copying a subtree. It is also used to create deepcopy functions with spe...
void clearMangledNameCache(SgGlobal *globalScope)
Support for faster mangled name generation (caching avoids recomputation).
std::vector< SgStatement * > getSwitchCases(SgSwitchStatement *sw)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
ROSE_DLL_API bool isScalarType(SgType *t)
Is this a scalar type?
ROSE_DLL_API void changeBreakStatementsToGotos(SgStatement *loopOrSwitch)
If the given statement contains any break statements in its body, add a new label below the statement...
ROSE_DLL_API SgFunctionDefinition * getEnclosingFunctionDefinition(SgNode *astNode, const bool includingSelf=false)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_CAF_language()
ROSE_DLL_API void printOutComments(SgLocatedNode *locatedNode)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void ReductionRecognition(SgForStatement *loop, std::set< std::pair< SgInitializedName *, OmpSupport::omp_construct_enum > > &results)
Recognize and collect reduction variables and operations within a C/C++ loop, following OpenMP 3....
ROSE_DLL_API bool loopUnrolling(SgForStatement *loop, size_t unrolling_factor)
Unroll a target loop with a specified unrolling factor. It handles steps larger than 1 and adds a fri...
ROSE_DLL_API void setLoopCondition(SgScopeStatement *loop, SgStatement *cond)
Set the condition statement of a loop, including While-loop, For-loop, and Do-While-loop.
bool ROSE_DLL_API isStatic(SgDeclarationStatement *stmt)
Check if a declaration has a "static' modifier.
PreprocessingInfo * attachComment(SgSourceFile *source_file, const std::string &content, PreprocessingInfo::DirectiveType directive_type=PreprocessingInfo::C_StyleComment, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before)
Build and attach comment onto the global scope of a source file.
ROSE_DLL_API SgClassDefinition * getEnclosingClassDefinition(SgNode *astnode, const bool includingSelf=false)
Get the closest class definition enclosing the specified AST node,.
ROSE_DLL_API bool mergeDeclarationAndAssignment(SgVariableDeclaration *decl, SgExprStatement *assign_stmt, bool removeAssignStmt=true)
Merge a variable assignment statement into a matching variable declaration statement....
ROSE_DLL_API void checkAccessPermissions(SgNode *)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API std::vector< SgFunctionDeclaration * > generateFunctionDefinitionsList(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API void replaceMacroCallsWithExpandedStrings(SgPragmaDeclaration *target)
Check if a pragma declaration node has macro calls attached, if yes, replace macro calls within the p...
std::string generateUniqueNameForUseAsIdentifier(SgDeclarationStatement *declaration)
Generate a useful name to support construction of identifiers from declarations.
ROSE_DLL_API bool isRestrictType(SgType *t)
Is this a restrict type?
ROSE_DLL_API std::string generateProjectName(const SgProject *project, bool supressSuffix=false)
Added mechanism to generate project name from list of file names.
ROSE_DLL_API void resetInternalMapsForTargetStatement(SgStatement *sourceStatement)
Reset internal data structures used for token-based unparsing and macro summaries based on modificati...
ROSE_DLL_API bool is_Cuda_language()
ROSE_DLL_API bool isLambdaCapturedVariable(SgVarRefExp *varRef)
check if a variable reference is this->a[i] inside of a lambda function
ROSE_DLL_API int instrumentEndOfFunction(SgFunctionDeclaration *func, SgStatement *s)
Instrument(Add a statement, often a function call) into a function right before the return points,...
ROSE_DLL_API SgInitializedName * getFirstInitializedName(SgVariableDeclaration *decl)
Get the first initialized name of a declaration statement.
void setSourcePositionPointersToNull(SgNode *node)
Set the source code positon for the current (input) node.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfDoWhile(SgDoWhileStmt *ws)
Check if the body of a 'do .. while' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void reportModifiedStatements(const std::string &label, SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API std::vector< SgInitializedName * > getOutParameters(const SgInitializedNamePtrList &params)
Get a vector of Jovial output parameters from the function parameter list (may work for Fortran in th...
ROSE_DLL_API void setSourcePositionForTransformation(SgNode *root)
Recursively set source position info(Sg_File_Info) as transformation generated.
ROSE_DLL_API SgGlobal * getGlobalScope(const SgNode *astNode)
Traverse back through a node's parents to find the enclosing global scope.
ROSE_DLL_API void insertStatementListAfter(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmt)
Insert a list of statements after a target statement.
ROSE_DLL_API bool isMain(const SgNode *node)
Check if a SgNode is a main() function declaration.
std::map< std::string, int > local_name_collision_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API void fixClassDeclaration(SgClassDeclaration *classDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
ROSE_DLL_API int collectVariableReferencesInArrayTypes(SgLocatedNode *root, Rose_STL_Container< SgNode * > &currentVarRefList)
Collect variable references in array types. The default NodeQuery::querySubTree() will miss variables...
SgBasicBlock * ensureBasicBlockAsBodyOfCaseOption(SgCaseOptionStmt *cs)
Check if the body of a 'case option' statement is a SgBasicBlock, create one if not.
void checkForInitializers(SgNode *node)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void removeUnusedLabels(SgNode *top, bool keepChild=false)
Remove labels which are not targets of any goto statements: its child statement is also removed by de...
ROSE_DLL_API SgProject * getProject()
Get the current SgProject IR Node.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfUpcForAll(SgUpcForAllStatement *fs)
Check if the body of a 'upc_forall' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API SgClassDeclaration * getEnclosingClassDeclaration(SgNode *astNode)
Get the closest class declaration enclosing the specified AST node,.
ROSE_DLL_API void insertStatement(SgStatement *targetStmt, SgStatement *newStmt, bool insertBefore=true, bool autoMovePreprocessingInfo=true)
Insert a statement before or after the target statement within the target's scope....
ROSE_DLL_API void listHeaderFiles(SgIncludeFile *includeFile)
return path prefix for subtree of include files.
ROSE_DLL_API void markSubtreeToBeUnparsedTreeTraversal(SgNode *root, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
void saveToPDF(SgNode *node, std::string filename)
Save AST into a pdf file. Start from a node to find its enclosing file node. The entire file's AST wi...
ROSE_DLL_API bool normalizeForLoopInitDeclaration(SgForStatement *loop)
Normalize loop init stmt by promoting the single variable declaration statement outside of the for lo...
void detectCycleInType(SgType *type, const std::string &from)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void deleteAST(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool statementCanBeTransformed(SgStatement *stmt)
If header file unparsing and token-based unparsing are used, then some statements in header files use...
ROSE_DLL_API SgStatement * getNextStatement(SgStatement *currentStmt)
Get next statement within the same scope of current statement.
ROSE_DLL_API std::set< SgLabelStatement * > findUnusedLabels(SgNode *top)
Find unused labels which are not targets of any goto statements.
ROSE_DLL_API void setExtern(SgDeclarationStatement *stmt)
Set a declaration as extern.
ROSE_DLL_API void deleteAllNodes()
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool templateArgumentListEquivalence(const SgTemplateArgumentPtrList &list1, const SgTemplateArgumentPtrList &list2)
Verify that 2 SgTemplateArgumentPtrList are equivalent.
ROSE_DLL_API LivenessAnalysis * call_liveness_analysis(SgProject *project, bool debug=false)
Call liveness analysis on an entire project.
ROSE_DLL_API void reportModifiedLocatedNodes(const std::string &label, SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void fixTemplateDeclaration(SgTemplateDeclaration *stmt, SgScopeStatement *scope)
Fix the symbol table and set scope (only if scope in declaration is not already set).
SgType * getBoolType(SgNode *n)
Get the right bool type according to C or C++ language input.
void clearSharedGlobalScopes(SgProject *project)
Collect all read and write references within stmt, which can be a function, a scope statement,...
void initializeWhileStatement(SgWhileStmt *whileStatement, SgStatement *condition, SgStatement *body, SgStatement *else_body)
Support function used for variable declarations in conditionals.
ROSE_DLL_API void setSourcePosition(SgNode *node)
Set the source code positon for the current (input) node.
ROSE_DLL_API void setPragma(SgPragmaDeclaration *decl, SgPragma *pragma)
Set a pragma of a pragma declaration. handle memory release for preexisting pragma,...
ROSE_DLL_API void insertStatementListBeforeFirstNonDeclaration(const std::vector< SgStatement * > &newStmts, SgScopeStatement *scope)
Insert statements before the first non-declaration statement in a scope. If the scope has no non-decl...
ROSE_DLL_API bool isPostfixOperator(SgExpression *exp)
Is an overloaded operator a postfix operator. (e.g. ).
ROSE_DLL_API SgStatement * findSurroundingStatementFromSameFile(SgStatement *targetStmt, bool &surroundingStatementPreceedsTargetStatement)
Supporting function to comment relocation in insertStatement() and removeStatement().
SgNamespaceDefinitionStatement * enclosingNamespaceScope(SgDeclarationStatement *declaration)
Find the enclosing namespace of a declaration.
ROSE_DLL_API SgStatement * getLoopBody(SgScopeStatement *loop)
Routines to get and set the body of a loop.
ROSE_DLL_API bool is_mixed_C_and_Cxx_language()
bool isStructurallyEquivalentAST(SgNode *tree1, SgNode *tree2)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API PreprocessingInfo * insertHeader(SgSourceFile *source_file, const std::string &header_file_name, bool isSystemHeader, bool asLastHeader)
Insert #include "filename" or #include <filename> (system header) onto the global scope of a source f...
void printAST2TextFile(SgNode *node, const char *filename, bool printType=true)
Pretty print AST horizontally, output to a specified text file. If printType is set to false,...
ROSE_DLL_API SgFunctionSymbol * lookupTemplateFunctionSymbolInParentScopes(const SgName &functionName, SgFunctionType *ftype, SgTemplateParameterPtrList *tplparams, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool is_language_case_insensitive()
ROSE_DLL_API void replaceStatement(SgStatement *oldStmt, SgStatement *newStmt, bool movePreprocessinInfo=false)
Replace a statement with another. Move preprocessing information from oldStmt to newStmt if requested...
ROSE_DLL_API void recordNormalizations(SgStatement *s)
Record where normalization have been done so that we can preform denormalizations as required for the...
ROSE_DLL_API bool loopInterchange(SgForStatement *loop, size_t depth, size_t lexicoOrder)
Interchange/permutate a n-level perfectly-nested loop rooted at 'loop' using a lexicographical order ...
void printAST(SgNode *node)
Pretty print AST horizontally, output to std output.
ROSE_DLL_API SgFunctionSymbol * lookupTemplateMemberFunctionSymbolInParentScopes(const SgName &functionName, SgFunctionType *ftype, SgTemplateParameterPtrList *tplparams, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool is_PHP_language()
ROSE_DLL_API bool isEqualToIntConst(SgExpression *e, int value)
Check if a SgIntVal node has a given value.
ROSE_DLL_API void insertStatementBeforeFirstNonDeclaration(SgStatement *newStmt, SgScopeStatement *scope, bool movePreprocessingInfo=true)
Insert a statement before the first non-declaration statement in a scope. If the scope has no non-dec...
ROSE_DLL_API SgFunctionSymbol * lookupFunctionSymbolInParentScopes(const SgName &functionName, SgScopeStatement *currentScope=NULL)
look up the first matched function symbol in parent scopes given only a function name,...
ROSE_DLL_API void appendStatementWithDependentDeclaration(SgDeclarationStatement *decl, SgGlobal *scope, SgStatement *original_statement, bool excludeHeaderFiles)
Append a copy ('decl') of a function ('original_statement') into a 'scope', include any referenced de...
ROSE_DLL_API bool insideHeader(SgLocatedNode *node)
Check if a node is from a header file.
ROSE_DLL_API void markSubtreeToBeUnparsed(SgNode *root, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isDataMemberReference(SgVarRefExp *varRefExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool collectReadWriteVariables(SgStatement *stmt, std::set< SgInitializedName * > &readVars, std::set< SgInitializedName * > &writeVars, bool coarseGrain=true)
Collect unique variables which are read or written within a statement. Note that a variable can be bo...
ROSE_DLL_API void constantFolding(SgNode *r)
Constant folding an AST subtree rooted at 'r' (replacing its children with their constant values,...
std::vector< SgBreakStmt * > findBreakStmts(SgStatement *code, const std::string &fortranLabel="")
Find break statements inside a particular statement, stopping at nested loops or switches.
ROSE_DLL_API SgFile * getEnclosingFileNode(SgNode *astNode)
get the SgFile node from current node
ROSE_DLL_API void setStatic(SgDeclarationStatement *stmt)
Set a declaration as static.
ROSE_DLL_API bool doLoopNormalization(SgFortranDo *loop)
Normalize a Fortran Do loop. Make the default increment expression (1) explicit.
ROSE_DLL_API SgFile * preprocessCompilationUnit(SgProject *, std::string, std::string, bool unparse=true)
Using the file_content string, create a file with the content in question; build its AST and add it t...
ROSE_DLL_API void removeLabeledGotos(SgNode *top)
Remove labeled goto statements.
std::map< SgNode *, std::string > local_node_to_name_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
std::vector< SgGotoStatement * > findGotoStmts(SgStatement *scope, SgLabelStatement *l)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
ROSE_DLL_API bool mergeDeclarationWithAssignment(SgVariableDeclaration *decl, SgExprStatement *assign_stmt)
Merge a declaration statement into a matching followed variable assignment. Callers should make sure ...
ROSE_DLL_API bool isAssignmentStatement(SgNode *_s, SgExpression **lhs=NULL, SgExpression **rhs=NULL, bool *readlhs=NULL)
Check if a SgNode _s is an assignment statement (any of =,+=,-=,&=,/=, ^=, etc)
ROSE_DLL_API void outputSharedNodes(SgNode *node)
Find a node by type using upward traversal.
bool ROSE_DLL_API isAncestor(SgNode *node1, SgNode *node2)
check if node1 is a strict ancestor of node 2. (a node is not considered its own ancestor)
ROSE_DLL_API SgScopeStatement * getEnclosingScope(SgNode *n, const bool includingSelf=false)
Get the enclosing scope from a node n.
ROSE_DLL_API SgNonrealSymbol * lookupNonrealSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API SgSwitchStatement * findEnclosingSwitch(SgStatement *s)
Find the closest switch outside a given statement (normally used for case and default statements)
ROSE_DLL_API void removeAllOriginalExpressionTrees(SgNode *top)
Set original expression trees to NULL for SgValueExp or SgCastExp expressions, so you can change the ...
ROSE_DLL_API std::vector< SgNode * > astIntersection(SgNode *original, SgNode *copy, SgCopyHelp *help=NULL)
Compute the intersection set for two ASTs.
ROSE_DLL_API bool isPrefixOperator(SgExpression *exp)
Is an overloaded operator a prefix operator (e.g. address operator X * operator&(),...
ROSE_DLL_API void setLhsOperand(SgExpression *target, SgExpression *lhs)
set left hand operand for binary expressions, transparently downcasting target expressions when neces...
ROSE_DLL_API std::vector< SgC_PreprocessorDirectiveStatement * > translateStatementToUseCppDeclarations(SgStatement *statement, SgScopeStatement *scope)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API int suggestNextNumericLabel(SgFunctionDefinition *func_def)
Suggest next usable (non-conflicting) numeric label value for a Fortran function definition scope.
ROSE_DLL_API std::set< SgStatement * > collectModifiedStatements(SgNode *node)
This collects the statements that are marked as modified (a flag automatically set by all set_* gener...
ROSE_DLL_API SgFunctionDeclaration * getEnclosingFunctionDeclaration(SgNode *astNode, const bool includingSelf=false)
Find the enclosing function declaration, including its derived instances like isSgProcedureHeaderStat...
SgFunctionDeclaration * findFunctionDeclaration(SgNode *root, std::string name, SgScopeStatement *scope, bool isDefining)
Topdown traverse a subtree from root to find the first function declaration matching the given name,...
ROSE_DLL_API bool isPrefixOperatorName(const SgName &functionName)
Check for proper names of possible prefix operators (used in isPrefixOperator()).
ROSE_DLL_API void setLoopStride(SgNode *loop, SgExpression *stride)
Set the stride(step) of a loop 's incremental expression, regardless the expression types (i+=s; i= i...
ROSE_DLL_API bool isInSubTree(SgExpression *subtree, SgExpression *exp)
Find a node by type using upward traversal.
ROSE_DLL_API bool forLoopNormalization(SgForStatement *loop, bool foldConstant=true)
Normalize a for loop, return true if successful.
unsigned long long getIntegerConstantValue(SgValueExp *expr)
Get the constant value from a constant integer expression; abort on everything else.
ROSE_DLL_API bool is_UPC_language()
ROSE_DLL_API void checkSymbolTables(SgNode *)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void updateDefiningNondefiningLinks(SgFunctionDeclaration *func, SgScopeStatement *scope)
Update defining and nondefining links due to a newly introduced function declaration....
ROSE_DLL_API SgNode * deepCopyNode(const SgNode *subtree)
Deep copy an arbitrary subtree.
SgBasicBlock * ensureBasicBlockAsBodyOfDefaultOption(SgDefaultOptionStmt *cs)
Check if the body of a 'default option' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void getLiveVariables(LivenessAnalysis *liv, SgForStatement *loop, std::set< SgInitializedName * > &liveIns, std::set< SgInitializedName * > &liveOuts)
get liveIn and liveOut variables for a for loop from liveness analysis result liv.
ROSE_DLL_API void resetModifiedLocatedNodes(const std::set< SgLocatedNode * > &modifiedNodeSet)
Use the set of IR nodes and set the isModified flag in each IR node to true.
ROSE_DLL_API SgNode * replaceWithPattern(SgNode *anchor, SgNode *new_pattern)
Replace an anchor node with a specified pattern subtree with optional SgVariantExpression....
ROSE_DLL_API bool ROSE_DLL_API isJovialOutParam(SgInitializedName *name)
True if a parameter name is a Jovial output parameter.
ROSE_DLL_API void moveForStatementIncrementIntoBody(SgForStatement *f)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfOmpBodyStmt(SgOmpBodyStatement *ompbodyStmt)
Check if the body of a SgOmpBodyStatement is a SgBasicBlock, create one if not.
ROSE_DLL_API bool is_Python_language()
ROSE_DLL_API bool is_mixed_Fortran_and_Cxx_language()
ROSE_DLL_API SgStatement * getLoopCondition(SgScopeStatement *loop)
Routines to get the condition of a loop. It recognize While-loop, For-loop, and Do-While-loop.
ROSE_DLL_API SgEnumSymbol * lookupEnumSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
std::pair< SgVariableDeclaration *, SgExpression * > createTempVariableAndReferenceForExpression(SgExpression *expression, SgScopeStatement *scope)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API SgTypedefSymbol * lookupTypedefSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfWhile(SgWhileStmt *ws)
Check if the body of a 'while' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfFor(SgForStatement *fs)
Check if the body of a 'for' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API PreprocessingInfo * attachArbitraryText(SgLocatedNode *target, const std::string &text, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before)
Attach an arbitrary string to a located node. A workaround to insert irregular statements or vendor-s...
ROSE_DLL_API void markNodeToBeUnparsed(SgNode *node, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isConstantTrue(SgExpression *e)
Check if a bool or int constant expression evaluates to be a true value.
std::map< std::string, SgNode * > local_name_to_node_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API bool is_binary_executable()
void changeAllBodiesToBlocks(SgNode *top, bool createEmptyBody=true)
Fix up ifs, loops, while, switch, Catch, OmpBodyStatement, etc. to have blocks as body components....
void dumpPreprocInfo(SgLocatedNode *locatedNode)
Dumps a located node's preprocessing information.
void fixupReferencesToSymbols(const SgScopeStatement *this_scope, SgScopeStatement *copy_scope, SgCopyHelp &help)
All the symbol table references in the copied AST need to be reset after rebuilding the copied scope'...
ROSE_DLL_API void moveDeclarationToAssociatedNamespace(SgDeclarationStatement *declarationStatement)
Relocate the declaration to be explicitly represented in its associated namespace (required for some ...
ROSE_DLL_API bool isCanonicalForLoop(SgNode *loop, SgInitializedName **ivar=NULL, SgExpression **lb=NULL, SgExpression **ub=NULL, SgExpression **step=NULL, SgStatement **body=NULL, bool *hasIncrementalIterationSpace=NULL, bool *isInclusiveUpperBound=NULL)
Check if a for-loop has a canonical form, return loop index, bounds, step, and body if requested.
ROSE_DLL_API bool isArrayReference(SgExpression *ref, SgExpression **arrayNameExp=NULL, std::vector< SgExpression * > **subscripts=NULL)
Check if an expression is an array access (SgPntrArrRefExp). If so, return its name expression and su...
ROSE_DLL_API void insertStatementAfterLastDeclaration(SgStatement *stmt, SgScopeStatement *scope)
Insert a statement after the last declaration within a scope. The statement will be prepended to the ...
ROSE_DLL_API void destroyTempDirectory(std::string)
Use the system command to remove a temporary directory and all its containing files.
void serialize_list(T &plist, std::string T_name, std::string &prefix, bool hasRemaining, std::ostringstream &out, std::string &edgeLabel)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
void resetMangledNameCache(SgGlobal *globalScope)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API SgTemplateInstantiationMemberFunctionDecl * buildForwardFunctionDeclaration(SgTemplateInstantiationMemberFunctionDecl *memberFunctionInstantiation)
Generate a non-defining (forward) declaration from a defining function declaration.
ROSE_DLL_API bool is_Fortran_language()
ROSE_DLL_API SgVariableSymbol * lookupVariableSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void outputFileIds(SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API SgExprStatement * splitVariableDeclaration(SgVariableDeclaration *decl)
Split a variable declaration with an rhs assignment into two statements: a declaration and an assignm...
ROSE_DLL_API SgStatement * getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated=false)
Get the first statement within a scope, return NULL if it does not exist. Skip compiler-generated sta...
ROSE_DLL_API SgNamespaceSymbol * lookupNamespaceSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool isExtern(SgDeclarationStatement *stmt)
Check if a declaration has an "extern" modifier.
std::string extractPragmaKeyword(const SgPragmaDeclaration *)
Extract a SgPragmaDeclaration's leading keyword . For example "#pragma omp parallel" has a keyword of...
ROSE_DLL_API SgTemplateClassSymbol * lookupTemplateClassSymbolInParentScopes(const SgName &name, SgTemplateParameterPtrList *templateParameterList, SgTemplateArgumentPtrList *templateArgumentList, SgScopeStatement *cscope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool isEquivalentFunctionType(const SgFunctionType *lhs, const SgFunctionType *rhs)
Test if two types are equivalent SgFunctionType nodes.
ROSE_DLL_API void setLoopLowerBound(SgNode *loop, SgExpression *lb)
Set the lower bound of a loop header for (i=lb; ...)
void guardNode(SgLocatedNode *target, std::string guard)
Add preproccessor guard around a given node.
bool checkTypesAreEqual(SgType *typeA, SgType *typeB)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API bool isReferenceType(SgType *t)
Is this type a const or non-const reference type? (Handles typedefs correctly)
ROSE_DLL_API 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 void moveCommentsToNewStatement(SgStatement *sourceStatement, const std::vector< int > &indexList, SgStatement *targetStatement, bool surroundingStatementPreceedsTargetStatement)
Relocate comments and CPP directives from one statement to another.
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