ROSE 0.11.145.250
sageInterface.C
1
2#include "sage3basic.h"
3#include "markLhsValues.h"
4#include "fixupNames.h"
5#include "FileUtility.h"
6#include <Sawyer/Message.h>
7
8#include "AstJSONGeneration.h"
9
10#include "SgNodeHelper.h" //Markus's helper functions
11
12#include "Rose/AST/Utility.h"
13
14#include "sageInterface.h"
15#include "Combinatorics.h"
16
17
18#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
19#include "replaceExpressionWithStatement.h"
20
21#include "constantFolding.h"
22#endif
23
24// DQ (10/14/2006): Added supporting help functions. tps commented out since it caused no compilation errors
25//#include "rewrite.h"
26
27// Liao 1/24/2008 : need access to scope stack sometimes
28#include "sageBuilder.h"
29
30// DQ (3/14/2017): Try to comment this out since it is not tested (used in get_C_array_dimensions(),
31// from midend/programTransformation/ompLowering/omp_lowering.cpp, but not tested).
32#include "sageGeneric.h"
33
34#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
35// For reusing some code from Qing's loop optimizer
36// Liao, 2/26/2009
37#include "AstInterface_ROSE.h"
38#include "LoopTransformInterface.h"
39
40#include "DepInfoAnal.h" // for AnalyzeStmtRefs()
41#include "ArrayAnnot.h"
42#include "ArrayInterface.h"
43
44#include "LoopUnroll.h"
45#include "abstract_handle.h"
46#include "roseAdapter.h"
47#endif
48
49#include <boost/lexical_cast.hpp>
50#include <boost/foreach.hpp>
51#include <sstream>
52#include <iostream>
53#include <algorithm> // for set operations
54#include <numeric> // for std::accumulate
55#include <map>
56#include <unordered_map>
57
58#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
59# include "jni.h"
60
61namespace Rose {
62 namespace Frontend {
63 namespace Java {
64 namespace Ecj {
65
66 extern jclass currentJavaTraversalClass;
67 extern JNIEnv *currentEnvironment;
68 extern jmethodID mainMethod;
69 extern jmethodID hasConflictsMethod;
70 extern jmethodID getTempDirectoryMethod;
71 extern jmethodID createTempFileMethod;
72 extern jmethodID createTempNamedFileMethod;
73 extern jmethodID createTempNamedDirectoryMethod;
74
75 } // ::Rose::Frontend::Java::Ecj
76 }// ::Rose::frontend::java
77 }// ::Rose::frontend
78}// ::Rose
79
80using namespace Rose::Frontend::Java::Ecj;
81
82#endif
83
84
85// DQ (11/5/2019): Added to support SageInterface::statementCanBeTransformed().
86namespace EDG_ROSE_Translation
87 {
88 // DQ (9/18/2018): Declare this map so that we can use it for the unparse header files option.
89#if defined(ROSE_BUILD_CXX_LANGUAGE_SUPPORT) && !defined(ROSE_USE_CLANG_FRONTEND)
90 // DQ (12/11/2018): Use the definition in the EDG edgRose.C file if C/C++ support IS defined.
91 extern std::map<std::string, SgIncludeFile*> edg_include_file_map;
92#else
93 // DQ (12/11/2018): Allow this to be the definition if C/C++ support is NOT defined.
94 std::map<std::string, SgIncludeFile*> edg_include_file_map;
95#endif
96 }
97
98
99
100// DQ (12/1/2015): Added to support macro handling.
101#include "detectMacroOrIncludeFileExpansions.h"
102
103namespace SageInterface {
104 template<class T> void setSourcePositionToDefault( T* node );
105}
106
107
108#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
109 #include "transformationSupport.h"
110#endif
111
112// We need this so that USE_CMAKE will be seen (set via configure).
113#include "rose_config.h"
114
115// DQ (3/4/2014): We need this feature to support the function: isStructurallyEquivalentAST().
116#include "RoseAst.h"
117
118// DQ (2/13/2022): We need this feature to support the function: deleteAllNodes().
119#include "AST_FILE_IO.h"
120
121
122// DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
123// The value of 0 allows the old implementation to be tested, and the value of 1 allows the new optimized implementation to be tested.
124#define OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS 1
125
128
129// DQ (3/21/2016): Added support for generateUniqueNameForUseAsIdentifier().
131std::map<std::string,SgNode*> SageInterface::local_name_to_node_map;
132std::map<SgNode*,std::string> SageInterface::local_node_to_name_map;
133
134typedef std::set<SgLabelStatement*> SgLabelStatementPtrSet;
135
136namespace SageInterface
137{
138 Transformation_Record trans_records;
139}
140
141// DQ (12/31/2005): This is OK if not declared in a header file
142using namespace std;
143using namespace Rose;
144using namespace SageBuilder;
145//using namespace Rose::Diagnostics; // for mlog, INFO, WARN, ERROR, FATAL, etc.
146
147// Used by serialize() to collect all types visited
148//std::set<SgType*> type_set;
149// DQ (1/18/2015): Define this container locally in this file only.
150namespace SageInterface
151 {
152 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
153 vector<SgBasicBlock*> addedBasicBlockNodes;
154 }
155
156
157#if 1
158// DQ (2/13/2022): Adding support to delete the whole AST (every SgNode).
159void
161 {
162 // This function uses a memory pool traversal specific to the SgFile IR nodes
163
164 // We need to use this function to get all of the SgNodes.
165 // template <typename NodeType> std::vector<NodeType*> getSgNodeListFromMemoryPool()
166
167 class MyTraversal : public ROSE_VisitTraversal
168 {
169 public:
170 std::vector<SgNode*> resultlist;
171 void visit ( SgNode* node)
172 {
173 SgNode* result = dynamic_cast<SgNode*>(node);
174 ROSE_ASSERT(result != NULL);
175#if 0
176 printf ("In SageInterface::deleteAllNodes(): result = %p = %s \n",result,result->class_name().c_str());
177#endif
178#if 0
179 if (result != NULL)
180 {
181 resultlist.push_back(result);
182 }
183#else
184 resultlist.push_back(result);
185#endif
186 };
187
188 virtual ~MyTraversal() {}
189 };
190
191 // For debugging, recode the number of IR nodes before we delete the AST.
192 size_t numberOfNodes_before = numberOfNodes();
193
194 MyTraversal my_traversal;
195
196 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
197 // NodeType::traverseMemoryPoolNodes(my_traversal);
198 my_traversal.traverseMemoryPool();
199
200 // return my_traversal.resultlist;
201
202
203 // vector<SgNode*> nodeList = getSgNodeListFromMemoryPool<SgNode>();
204 vector<SgNode*> & nodeList = my_traversal.resultlist;
205
206 printf ("In SageInterface::deleteAllNodes(): get list of SgNode: nodeList.size() = %zu \n",nodeList.size());
207
208 vector<SgNode*>::iterator i = nodeList.begin();
209
210 // This loop will call the delete operator on all of the IR nodes in the AST.
211 while (i != nodeList.end())
212 {
213 SgNode* node = *i;
214#if 0
215 // It is an error to be calling get_name() while so many nodes are being deleted.
216 // printf (" --- calling delete (and thus the destructor) node = %p = %s name = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
217 printf (" --- calling delete (and thus the destructor) node = %p = %s \n",node,node->class_name().c_str());
218#endif
219 delete node;
220 node = NULL;
221
222 i++;
223 }
224
225#if 0
226 // This demonstrates that this function only visits the specific IR node that is used as a template parameter.
227 vector<SgFunctionDeclaration*> functionDeclarationList = getSgNodeListFromMemoryPool<SgFunctionDeclaration>();
228 printf ("In SageInterface::deleteAllNodes(): get list of SgFunctionDeclaration: functionDeclarationList.size() = %zu \n",functionDeclarationList.size());
229#endif
230
231 // Now we need to delete the memory pools (implemented by ROSETTA).
232 AST_FILE_IO::clearAllMemoryPools();
233
234 size_t numberOfNodes_after = numberOfNodes();
235
236#if 1
237 printf ("Leaving SageInterface::deleteAllNodes(): numberOfNodes_before = %zu numberOfNodes_after = %zu \n",numberOfNodes_before,numberOfNodes_after);
238#endif
239 }
240#endif
241
242
243#if 0
244// DQ (3/5/2022): Adding support to check AST for invalide poionters.
245void
247 {
248 // This function uses a memory pool traversal to look for any pointers to invalid IR nodes.
249
250 // Step 1: is to build a map of the boundaries of the memory pools for each IR node kind.
251 // Step 2: traverse all of the IR nodes across all of the memory pools and check
252 // a) if the pointer to each node in the list of child IR nodes is in the map from step 1.
253 // b) if it is then we can expect to dereference the pointer and check the value of
254 // get_freepointer(), the value should be 0xffffffffffffffff, else it is an error
255 // (when it is an error it usually should be a value that is in the map from step 1, but it
256 // is a node that was previously deleted, so it is a stale pointer).
257
258 class BuildMapTraversal : public ROSE_VisitTraversal
259 {
260 public:
261 // std::vector<SgNode*> resultlist;
262 // std::map<enum VariantT,std::vector<std::pair<SgNode*,SgNode*>> mapOfMemoryPoolsBounds;
263
264 // We need to get the pools variable for each IR node.
265
266 void visit ( SgNode* node)
267 {
268 // Get list of all pointers to all IR nodes in the current node.
269
270 // $CLASSNAME::pools
272
273 resultlist.push_back(result);
274 };
275
276 virtual ~MyTraversal() {}
277 };
278
279 // For debugging, recode the number of IR nodes before we delete the AST.
280 size_t numberOfNodes_before = numberOfNodes();
281
282 MyTraversal my_traversal;
283
284 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
285 // NodeType::traverseMemoryPoolNodes(my_traversal);
286 my_traversal.traverseMemoryPool();
287 }
288#endif
289
290void
291SageInterface::DeclarationSets::addDeclaration(SgDeclarationStatement* decl)
292 {
293 // DQ (4/3/2014): This function either builds a new set or inserts declarations into an
294 // existing set based on if a set defined by the key (firstNondefiningDeclaration) is present.
295 ASSERT_not_null(decl);
296
297#if 0
298 printf ("TOP of SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
299#endif
300
301 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
302
303 if (firstNondefiningDeclaration == nullptr)
304 {
305 // It appears that some loop transformations (pass3.C) don't set the firstNondefiningDeclaration.
306#if 0
307 printf ("WARNING: SageInterface::DeclarationSets::addDeclaration(): firstNondefiningDeclaration == NULL: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
308#endif
309 return;
310 }
311 ASSERT_not_null(firstNondefiningDeclaration);
312
313 if (decl == firstNondefiningDeclaration)
314 {
315#if 0
316 if (isSgTypedefDeclaration(decl) != nullptr)
317 {
318 printf ("TOP of SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
319 }
320#endif
321 if (declarationMap.find(firstNondefiningDeclaration) == declarationMap.end())
322 {
323#if 0
324 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add a set for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
325#endif
326#if 0
327 if (isSgTypedefDeclaration(decl) != nullptr)
328 {
329 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add a set for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
330 }
331#endif
332 // Add a new set.
333 declarationMap[decl] = new set<SgDeclarationStatement*>();
334
335 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
336 ROSE_ASSERT(declarationMap[decl] != nullptr);
337
338 // Add a declaration to an existing set.
339 declarationMap[firstNondefiningDeclaration]->insert(decl);
340 }
341 else
342 {
343 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
344 {
345#if 0
346 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add the declaration to the existing set: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
347#endif
348#if 0
349 if (isSgTypedefDeclaration(decl) != nullptr)
350 {
351 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add the declaration to the existing set: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
352 }
353#endif
354 // Add a declaration to an existing set.
355 declarationMap[firstNondefiningDeclaration]->insert(decl);
356 }
357 else
358 {
359#if 0
360 printf ("WARNING: SageInterface::DeclarationSets::addDeclaration(): A set already exists for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
361#endif
362 // DQ (4/5/2014): The case of SgFunctionParameterList fails only for boost examples (e.g. test2014_240.C).
363 // Problem uses are associated with SgTemplateInstantiationFunctionDecl IR nodes.
364 bool ignore_error = (isSgFunctionParameterList(decl) != nullptr);
365
366 // DQ (4/17/2014): This is required for the EDG version 4.8 and I don't know why.
367 // Currently the priority is to pass our existing tests.
368 // An idea is that this is sharing introduced as a result of the use of default parameters.
369
370 // DQ (7/2/2014): I am seeing that this is required for a new application using GNU 4.4.7.
371 // It allows a boost issue specific to a revisited SgTypedefDeclaration pass, but I still
372 // don't understand the problem. so this needs a better fix.
373
375 bool isInTemplateFunctionDeclaration = enclosingFunction != nullptr && (isSgTemplateMemberFunctionDeclaration(enclosingFunction) || isSgTemplateFunctionDeclaration(enclosingFunction));
376
377 // Use short-circuit evaluation to improve performance.
378 SgClassDefinition* enclosingClassDefinition = isInTemplateFunctionDeclaration == true ? nullptr : getEnclosingClassDefinition(decl);
379 bool isInTemplateClassDefinition = enclosingClassDefinition != nullptr && isSgTemplateClassDefinition(enclosingClassDefinition);
380
381 bool isInTemplateDeclaration = isInTemplateFunctionDeclaration || isInTemplateClassDefinition;
382
383 ignore_error = ignore_error || (isSgTypedefDeclaration(decl) != nullptr) || (isSgTemplateInstantiationDecl(decl) != nullptr) || (isInTemplateDeclaration == true);
384
385 // DQ (2/5/2015): We need to ignore the case of un-named classes (or maybe those classes
386 // from unnamed classes with lambda member functions). See test2015_13.C for an example.
387 // Or maybe these should have been added to the declarationMap in the front-end?
388 if (isSgClassDeclaration(decl) != nullptr)
389 {
390 ignore_error = ignore_error || (isSgClassDeclaration(decl)->get_isUnNamed() == true);
391 }
392 }
393 }
394 }
395 else
396 {
397 // Add the declaration (make sure there is a set that exists).
398 if (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end())
399 {
400 // Make sure it does not already exist in the set.
401 ROSE_ASSERT (declarationMap[firstNondefiningDeclaration] != nullptr);
402 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
403 {
404 // Add a declaration to an existing set.
405 declarationMap[firstNondefiningDeclaration]->insert(decl);
406 }
407 else
408 {
409#if 0
410 printf ("This declaration is already in the set (skip adding it twice): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
411#endif
412 }
413 }
414 else
415 {
416 // In this case the defining declaration might be the only declaration to be traversed and
417 // so a set has not been built yet.
418#if 0
419 printf ("In SageInterface::DeclarationSets::addDeclaration(): Adding set and declaration for the firstNondefiningDeclaration = %p = %s = %s \n",
420 firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str(),get_name(firstNondefiningDeclaration).c_str());
421#endif
422
423 // DQ (4/5/2014): Just build the set and don't insert the firstNondefiningDeclaration.
424 // If we were to do so then it would be an error to use the insert it later.
425 // Note recursive call.
426 // addDeclaration(firstNondefiningDeclaration);
427 declarationMap[firstNondefiningDeclaration] = new set<SgDeclarationStatement*>();
428
429 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
430
431 // DQ (4/5/2014): We have to insert this since it is different from the firstNondefiningDeclaration.
432 // Add the declaration to the existing set.
433 declarationMap[firstNondefiningDeclaration]->insert(decl);
434
435 // DQ (4/5/2014): Added assertion.
436 ROSE_ASSERT(declarationMap[firstNondefiningDeclaration]->find(decl) != declarationMap[firstNondefiningDeclaration]->end());
437#if 0
438 printf ("SageInterface::DeclarationSets::addDeclaration(): No set exists for the firstNondefiningDeclaration = %p = %s = %s \n",firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str(),get_name(firstNondefiningDeclaration).c_str());
439 ROSE_ABORT();
440#endif
441 }
442 }
443
444#if 0
445 printf ("Leaving SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
446#endif
447 }
448
449const std::set<SgDeclarationStatement*>*
450SageInterface::DeclarationSets::getDeclarations(SgDeclarationStatement* decl)
451 {
452 // DQ (4/3/2014): This function returns the associated set of declarations.
453 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
454
455 ROSE_ASSERT(declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
456
457 const set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
458
459 // return this->declarationMap[firstNondefiningDeclaration];
460 return declarationSet;
461 }
462
463std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* > &
464SageInterface::DeclarationSets::getDeclarationMap()
465 {
466 return declarationMap;
467 }
468
469bool
470SageInterface::DeclarationSets::isLocatedInDefiningScope(SgDeclarationStatement* decl)
471 {
472 // DQ (4/7/2014): This function assumes that the input is a friend declaration.
473
474 // The existence of a declaration in a named scope (if a friend function) will cause
475 // subsequent declarations to be qualified where name qualification is required.
476 // A couple of issues:
477 // We likely need to keep track of the order of the declarations in the more
478 // complex cases because name qualification will be required after the declaration
479 // that appears in the named scope; but will not be required before the declaration in
480 // the named scope.
481
482#define DEBUG_LOCATED_IN_DEFINING_SCOPE 0
483
484 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
485 ROSE_ASSERT(firstNondefiningDeclaration != nullptr);
486
487 set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
488 ROSE_ASSERT(declarationSet != nullptr);
489
490 set<SgDeclarationStatement*>::iterator i = declarationSet->begin();
491
492 bool isDefinedInNamedScope = false;
493
494#if DEBUG_LOCATED_IN_DEFINING_SCOPE
495 printf ("In DeclarationSets::isLocatedInDefiningScope(): decl = %p = %s \n",decl,decl->class_name().c_str());
496 printf (" --- declarationSet->size() = %" PRIuPTR " \n",declarationSet->size());
497#endif
498
499 while (isDefinedInNamedScope == false && i != declarationSet->end())
500 {
501 ROSE_ASSERT(*i != nullptr);
502#if DEBUG_LOCATED_IN_DEFINING_SCOPE
503 printf (" --- *i = %p = %s \n",*i,(*i)->class_name().c_str());
504#endif
505 // We want to know the structural position, not the semantic scope.
506 SgScopeStatement* semantic_scope = (*i)->get_scope();
507 SgScopeStatement* structural_scope = isSgScopeStatement((*i)->get_parent());
508
509#if DEBUG_LOCATED_IN_DEFINING_SCOPE
510 printf (" --- semantic_scope = %p = %s \n",semantic_scope,semantic_scope->class_name().c_str());
511 printf (" --- structural_scope = %p = %s \n",structural_scope,structural_scope->class_name().c_str());
512#endif
513 // DQ (4/7/2014): If it is a member of a class then we don't consider the structural scope, else it makes a difference,
514 SgScopeStatement* scope = isSgClassDefinition(semantic_scope) != nullptr ? semantic_scope : structural_scope;
515 ASSERT_not_null(scope);
516
517#if DEBUG_LOCATED_IN_DEFINING_SCOPE
518 printf (" --- scope = %p = %s \n",scope,scope->class_name().c_str());
519 printf (" --- scope->isNamedScope() = %s \n",scope->isNamedScope() ? "true" : "false");
520#endif
521 SgGlobal* globalScope = isSgGlobal(scope);
522
523 // Friend functions declared in the class definition are not meaningful for determining name qualification.
524 if (globalScope != nullptr || (scope->isNamedScope() == true && isSgClassDefinition(structural_scope) == nullptr) )
525 {
526 // Check if the function is output in the unparing, else it would not be defined.
527 bool willBeOutput = ((*i)->get_file_info()->isCompilerGenerated() == false ||
528 ((*i)->get_file_info()->isCompilerGenerated() &&
529 (*i)->get_file_info()->isOutputInCodeGeneration()) );
530#if DEBUG_LOCATED_IN_DEFINING_SCOPE
531 printf (" --- before: willBeOutput = %s \n",willBeOutput ? "true" : "false");
532#endif
533 // Being output only count when it is output where it is located structurally.
534 willBeOutput = willBeOutput && scope == structural_scope;
535
536#if DEBUG_LOCATED_IN_DEFINING_SCOPE
537 printf (" --- after: willBeOutput = %s \n",willBeOutput ? "true" : "false");
538#endif
539 // DQ (3/20/2016): this is reported by GNU as set but not used.
540 // associatedDeclaration = *i;
541
542 // isDefinedInNamedScope = true;
543 isDefinedInNamedScope = willBeOutput;
544 }
545
546 i++;
547 }
548
549#if DEBUG_LOCATED_IN_DEFINING_SCOPE
550 if (associatedDeclaration != nullptr)
551 {
552 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p = %s \n",associatedDeclaration,associatedDeclaration->class_name().c_str());
553 }
554 else
555 {
556 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p \n",associatedDeclaration);
557 }
558#endif
559
560 return isDefinedInNamedScope;
561 }
562
564SageInterface::buildDeclarationSets(SgNode* n)
565 {
566 DeclarationSets* declarationSet = new DeclarationSets();
567
568 class DeclarationSetTraversal : public AstSimpleProcessing
569 {
570 private:
571 DeclarationSets* declarationSet;
572
573 public:
574 DeclarationSetTraversal(DeclarationSets* ds) : declarationSet(ds) {}
575 void visit (SgNode* node)
576 {
577 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
578 if (decl != nullptr)
579 {
580 declarationSet->addDeclaration(decl);
581 }
582 }
583 };
584
585 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
586 DeclarationSetTraversal traversal(declarationSet);
587 traversal.traverse(n, preorder);
588
589 return declarationSet;
590 }
591
593// DQ: 09/23/03
594// We require a global function for getting the string associated
595// with the definition of a variant (which is a global enum).
596string getVariantName ( VariantT v )
597 {
598 ROSE_ASSERT( int(v) < int(V_SgNumVariants));
599
600 // This code is far simpler (if the function is static)
601
602 // DQ (4/8/2004): Modified code to use new global list of sage
603 // class names (simpler this way)
604 // return string(SgTreeTraversal<int,int>::get_variantName(v));
605 extern const char* roseGlobalVariantNameList[];
606 return string(roseGlobalVariantNameList[v]);
607 }
608
609bool
611 {
612 // DQ (6/7/2012): This refactors the test for template instantiation syntax in names used for classes, member functions, and functions
613 bool usingTemplateSyntax = false;
614 string nameString = name.getString();
615
616 // DQ (6/7/2012): We need to avoid the identification of the "operator<()" as valid template syntax.
617 usingTemplateSyntax = (nameString.find('<') != string::npos) && (nameString.find('>') != string::npos);
618
619 // DQ (5/10/2016): Debugging case of C++11 using the Intel v16 compiler and it's associated mutex header file.
620 // See Cxx11_tests/test2016_32.C for an example that demonstrates this problem.
621 if (nameString == "<unnamed>")
622 {
623 printf ("In SageInterface::hasTemplateSyntax(): Identified case of name == <unnamed> \n");
624
625 usingTemplateSyntax = false;
626 }
627
628 // return (name.getString().find('<') == string::npos);
629 return usingTemplateSyntax;
630 }
631
632
633
634void
636 {
637 // DQ (2/12/2012): Refactoring disagnostic support for detecting where we are when something fails.
638
639 // This highest level node acceptable for us by this function is a SgGlobal (global scope).
640
641 ROSE_ASSERT(node != NULL);
642// printf ("Inside of SageInterface::whereAmI(node = %p = %s) \n",node,node->class_name().c_str());
643
644 // Enforce that some IR nodes should not be acepted inputs.
645 ROSE_ASSERT(isSgFile(node) == NULL);
646 ROSE_ASSERT(isSgFileList(node) == NULL);
647 ROSE_ASSERT(isSgProject(node) == NULL);
648
649 SgNode* parent = node->get_parent();
650
651 // Don't traverse past the SgFile level.
652 while (parent != nullptr && isSgFileList(parent) == nullptr)
653 {
654 // DQ (7/14/2019): These were commented out, but they are intended for debugging, so
655 // if someone does not need this output then the function should not have been called.
656 printf ("--- parent = %p = %s \n",parent,parent->class_name().c_str());
657
658 ROSE_ASSERT(parent->get_file_info() != NULL);
659 parent->get_file_info()->display("In SageInterface::whereAmI() diagnostics support");
660
661 parent = parent->get_parent();
662 }
663 }
664
665void
666SageInterface::initializeIfStmt(SgIfStmt *ifstmt, SgStatement* conditional, SgStatement * true_body, SgStatement * false_body)
667 {
668 // DQ (2/13/2012): Added new function to support proper initialization of a SgIfStmt that has already been built.
669 // This is important when we have to build the scope ahead of the test becasue the text contains a simple
670 // declaration (which must be put into the SgIfStmt scope).
671
672 // SgIfStmt *ifstmt = new SgIfStmt(conditional, true_body, false_body);
673 ROSE_ASSERT(ifstmt);
674
675 if (ifstmt->get_conditional() == nullptr)
676 ifstmt->set_conditional(conditional);
677
678 if (ifstmt->get_true_body() == nullptr)
679 ifstmt->set_true_body(true_body);
680
681 if (ifstmt->get_false_body() == nullptr)
682 ifstmt->set_false_body(false_body);
683
684 // Rasmussen (3/22/2020): Fixed setting case insensitivity
686 ifstmt->setCaseInsensitive(true);
687
689 if (conditional) conditional->set_parent(ifstmt);
690 if (true_body) true_body->set_parent(ifstmt);
691 if (false_body) false_body->set_parent(ifstmt);
692 }
693
694
695void
697 {
698 ROSE_ASSERT(switchStatement != NULL);
699
700 // Rasmussen (3/22/2020): Fixed setting case insensitivity
702 switchStatement->setCaseInsensitive(true);
703
704 if (switchStatement->get_item_selector() == nullptr)
705 switchStatement->set_item_selector(item_selector);
706
707 if (switchStatement->get_body() == nullptr)
708 switchStatement->set_body(body);
709
711 if (item_selector != nullptr)
712 item_selector->set_parent(switchStatement);
713 if (body != nullptr)
714 body->set_parent(switchStatement);
715 }
716
717
718void
720 {
721 ROSE_ASSERT(whileStatement);
722
723 // Rasmussen (3/22/2020): Fixed setting case insensitivity
725 whileStatement->setCaseInsensitive(true);
726
727 if (whileStatement->get_condition() == nullptr)
728 whileStatement->set_condition(condition);
729 if (whileStatement->get_body() == nullptr)
730 whileStatement->set_body(body);
731
732 // Python support.
733 if (whileStatement->get_else_body() == nullptr)
734 whileStatement->set_else_body(else_body);
735
736 setOneSourcePositionNull(whileStatement);
737 if (condition) condition->set_parent(whileStatement);
738 if (body) body->set_parent(whileStatement);
739
740 // DQ (8/10/2011): This is added by Michael to support a Python specific feature.
741 if (else_body != nullptr)
742 {
743 whileStatement->set_else_body(else_body);
744 else_body->set_parent(whileStatement);
745 }
746 }
747
748
749
752 {
753 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
754
755 // This function returns the namespace associated with any declaration.
756 // If the declaration is nested inside of other scopes this function
757 // iterates through these scopes to get the the first namespace.
758 // This is important for details of template handling, namely making sure
759 // that the template specializations (generated by ROSE) are put into the
760 // correct location (namespace) since stricted rules in gnu now enforce
761 // these details. If the declaration is not in a namespace as computed
762 // in the chain of scopes then this function returns nullptr.
763
764 ROSE_ASSERT(declaration != NULL);
765 SgScopeStatement* tempScope = declaration->get_scope();
766
767 // Loop back to the first namespace or stop at global scope (stop on either a namespace or the global scope)
768 while ( isSgNamespaceDefinitionStatement(tempScope) == nullptr && isSgGlobal(tempScope) == nullptr )
769 {
770 tempScope = tempScope->get_scope();
771 ROSE_ASSERT(tempScope != NULL);
772#if 0
773 printf ("Iterating back through scopes: tempScope = %p = %s = %s \n",tempScope,tempScope->class_name().c_str(),SageInterface::get_name(tempScope).c_str());
774#endif
775 }
776
777 SgNamespaceDefinitionStatement* namespaceScope = isSgNamespaceDefinitionStatement(tempScope);
778 return namespaceScope;
779 }
780
781
784 {
785 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
786 // DQ (11/4/2007): Get the associated declaration that will be in the original source code,
787 // if it is part of a template instantiation then get the original template declaration.
788
789 SgDeclarationStatement* parentDeclaration = nullptr;
790
791 SgScopeStatement* defn = memberFunctionInstantiation->get_class_scope();
792 ASSERT_not_null(defn);
793
794 // SgTemplateDeclaration* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
795 SgDeclarationStatement* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
796 ASSERT_not_null(templateDeclaration);
797
798 // If it is a template instatiation, then we have to find the temple declaration (not the template instantiation declaration), else we want the class declaration.
799 SgClassDefinition* cdefn = isSgClassDefinition(defn);
800 SgDeclarationScope* nrscope = isSgDeclarationScope(defn);
801 SgTemplateInstantiationDefn* templateInstatiationClassDefinition = isSgTemplateInstantiationDefn(defn);
802 if (templateInstatiationClassDefinition != nullptr)
803 {
804 // This is the case of a template member function in a templated class (see test2005_172.C).
805 SgTemplateInstantiationDefn* parentTemplateInstantiationDefinition = isSgTemplateInstantiationDefn(templateDeclaration->get_scope());
806 ASSERT_not_null(parentTemplateInstantiationDefinition);
807 SgTemplateInstantiationDecl* parentTemplateInstantiationDeclaration = isSgTemplateInstantiationDecl(parentTemplateInstantiationDefinition->get_declaration());
808 ASSERT_not_null(parentTemplateInstantiationDeclaration);
809
810 parentDeclaration = parentTemplateInstantiationDeclaration->get_templateDeclaration();
811 ASSERT_not_null(parentDeclaration);
812 }
813 else if (cdefn != nullptr)
814 {
815 // This is the case of a template member function in a class definition (see test2005_168.C).
816 parentDeclaration = cdefn->get_declaration();
817 ASSERT_not_null(parentDeclaration);
818 }
819 else if (nrscope != nullptr)
820 {
821 parentDeclaration = isSgDeclarationStatement(nrscope->get_parent());
822 ASSERT_not_null(parentDeclaration);
823 }
824 else
825 {
826 ROSE_ABORT();
827 }
828
829 return parentDeclaration;
830 }
831
835void
837{
838 ASSERT_not_null(var_decl);
839 ASSERT_not_null(base_decl);
840
841 // There is a bug (see gitlab-issue-349.jov) that arises when base_decl has a comment and it is the
842 // first statement, because base_decl will be removed (causing comments to be moved, where? good question!).
843 // Consider moving comments to var_decl first to circumvent (by artfulness or deception) potential problems.
844 // [Rasmussen 2024.04.10]
845
846 // try to remove it from the scope's declaration list
847 // If the struct decl was previously inserted into its scope
848 if (base_decl->get_parent() != nullptr)
849 {
850 if (base_decl->get_scope() == base_decl->get_parent())
851 {
852 SgStatementPtrList stmt_list = base_decl->get_scope()->generateStatementList();
853 if (find(stmt_list.begin(), stmt_list.end(), base_decl) != stmt_list.end())
855 }
856 }
857 base_decl->set_parent(var_decl);
858 var_decl->set_baseTypeDefiningDeclaration(base_decl);
859
860 //Set an internal mangled name for the anonymous declaration, if necessary
861 // resetNamesInAST(); // this will trigger mangleNameMap.size() ==0 assertion.
862 // We call resetEmptyNames directly instead.
863 ResetEmptyNames t1;
864 t1.traverseMemoryPool();
865}
866
867// DQ (11/4/2007): This looks for a forward temple member function declaration of matching name exists in the specified scope.
868bool
870 {
871 // DQ (11/3/2007): Look for an existing previously inserted (or existing) template member function declaration and only add one if we can't find it.
872
873 bool foundExistingPrototype = false;
874
875 ROSE_ASSERT(scope != NULL);
876 ROSE_ASSERT(functionDeclaration != NULL);
877 ROSE_ASSERT(startingAtDeclaration != NULL);
878
879 // TV (09/17/2018): ROSE-1378
880 if (isSgDeclarationScope(scope)) {
881 printf("TODO: SgDeclarationScope handling in SageInterface::isPrototypeInScope see ROSE-1378\n");
882 return false;
883 }
884
885 // These are the scopes for which get_declarationList() is properly defined.
886 ROSE_ASSERT(scope->containsOnlyDeclarations() == true);
887
888 // Note that this is only defined for certain scopes, but we only want it for THOSE scopes
889 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
890
891 // This is a simple way to restrict the evaluation (still linear, but jumps to initial position to start search).
892 SgDeclarationStatementPtrList::iterator startingLocation = find(declarationList.begin(),declarationList.end(),startingAtDeclaration);
893
894 if (startingLocation != declarationList.end())
895 {
896#if 0
897 printf ("startingLocation = %p = %s = %s \n",*startingLocation,(*startingLocation)->class_name().c_str(),SageInterface::get_name(*startingLocation).c_str());
898#endif
899 // printf ("Found the startingLocation is the global scope, now check if we need to add a new declaration \n");
900 SgDeclarationStatementPtrList::iterator i = startingLocation;
901 SgScopeStatement* targetScope = functionDeclaration->get_scope();
902 SgName targetName = functionDeclaration->get_name();
903
904 while (i != declarationList.end())
905 {
906 // printf ("i = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
907
908 // Look for a prototype like what we want to insert, if we find it then we don't need to add a second one!
909 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(*i);
910 if (templateMemberFunction != nullptr)
911 {
912 // Check the name and the scope
913 if (targetScope == templateMemberFunction->get_scope())
914 {
915 if (targetName == templateMemberFunction->get_name())
916 {
917 // Don't count the defining declaration which may be at the end of the global scope.
918 if (templateMemberFunction->isForward() == true)
919 {
920 foundExistingPrototype = true;
921
922 // Exit the loop (optimization)
923 break;
924 }
925 }
926 }
927 }
928
929 i++;
930 }
931 }
932
933 return foundExistingPrototype;
934 }
935
936bool
938 {
939 ROSE_ASSERT(node1 && node2);
940
941 SgNode* curnode = node2;
942 if (node1==node2)
943 {
944 return false;
945 }
946
947 do {
948 curnode= curnode->get_parent();
949 } while( (curnode!=nullptr) && (curnode!=node1));
950
951 if (curnode==node1)
952 {
953 return true;
954 }
955 else
956 {
957 return false;
958 }
959 }
960
961bool
963 {
964 // DQ (12/7/2020): This is supporting the recognition of functions in header files from two different AST.
965
966#define DEBUG_HAS_SAME_SCOPE 0
967
968#if DEBUG_HAS_SAME_SCOPE
969 printf ("In SageInterface::hasSameGlobalScope(): \n");
970 printf (" --- statement_1 = %p = %s \n",statement_1,statement_1->class_name().c_str());
971 printf (" --- statement_2 = %p = %s \n",statement_2,statement_2->class_name().c_str());
972#endif
973
974 bool includingSelf = true;
975 SgGlobal* global_scope_1 = getEnclosingNode<SgGlobal>(statement_1,includingSelf);
976 SgGlobal* global_scope_2 = getEnclosingNode<SgGlobal>(statement_2,includingSelf);
977
978#if DEBUG_HAS_SAME_SCOPE
979 printf (" --- global_scope_1 = %p = %s \n",global_scope_1,global_scope_1->class_name().c_str());
980 SgSourceFile* sourcefile_1 = isSgSourceFile(global_scope_1->get_parent());
981 printf (" --- --- sourcefile_1 = %p filename = %s \n",sourcefile_1,sourcefile_1->getFileName().c_str());
982
983 printf (" --- global_scope_2 = %p = %s \n",global_scope_2,global_scope_2->class_name().c_str());
984 SgSourceFile* sourcefile_2 = isSgSourceFile(global_scope_2->get_parent());
985 printf (" --- --- sourcefile_2 = %p filename = %s \n",sourcefile_2,sourcefile_2->getFileName().c_str());
986#endif
987
988 bool returnResult = (global_scope_1 == global_scope_2);
989
990#if DEBUG_HAS_SAME_SCOPE
991 printf ("Leaving SageInterface::hasSameGlobalScope(): returning: %s \n",returnResult ? "true" : "false");
992#endif
993
994 return returnResult;
995 }
996
997
998std::vector<SgNode*>
1000 {
1001 std::vector<SgNode*> intersectionSet;
1002
1003 // Collect all the IR nodes for the original AST
1004 std::vector<SgNode*> AST_original = NodeQuery::querySubTree (original,V_SgNode);
1005 std::vector<SgNode*> AST_copy = NodeQuery::querySubTree (copy,V_SgNode);
1006
1007 int AST_original_size = AST_original.size();
1008 int AST_copy_size = AST_copy.size();
1009
1010 if (SgProject::get_verbose() > 0)
1011 {
1012 printf ("Original AST size = %d \n",AST_original_size);
1013 printf ("Copy of original AST size = %d \n",AST_copy_size);
1014 }
1015
1016 int differenceInSizes = AST_original_size - AST_copy_size;
1017 if (differenceInSizes == 0)
1018 {
1019 if (SgProject::get_verbose() > 0)
1020 printf ("Copied AST is the SAME size as the original (size = %d) \n",AST_original_size);
1021 }
1022 else
1023 {
1024 printf ("Warning: Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) \n",AST_original_size,AST_copy_size);
1025 }
1026
1027 // Compute the intersection (reference in the copy that point to the origal AST).
1028 // std::set<SgNode*> AST_set_original = AST_original;
1029 std::set<SgNode*> AST_set_original;
1030 for (int i = 0; i < AST_original_size; i++)
1031 {
1032 AST_set_original.insert(AST_original[i]);
1033 }
1034
1035 std::set<SgNode*> AST_set_copy;
1036 for (int i = 0; i < AST_copy_size; i++)
1037 {
1038 AST_set_copy.insert(AST_copy[i]);
1039 }
1040
1041 int size = AST_original_size;
1042 std::vector<SgNode*> intersectionList(size);
1043
1044 // Is there a better way to do this? Build scratch space and then use the different between begin() and end to build another vector.
1045 std::vector<SgNode*>::iterator end = set_intersection(AST_set_original.begin(),AST_set_original.end(),AST_set_copy.begin(),AST_set_copy.end(),intersectionList.begin());
1046
1047 // Build a new vector from the relevant elements of the intersectionList scratch space.
1048 std::vector<SgNode*> meaningIntersectionList = std::vector<SgNode*>(intersectionList.begin(),end);
1049 std::vector<SgNode*> deleteList;
1050 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
1051 {
1052 if (meaningIntersectionList[i] != nullptr && isSgType(meaningIntersectionList[i]) != nullptr)
1053 {
1054 deleteList.push_back(meaningIntersectionList[i]);
1055 }
1056 }
1057
1058 // Remove the types since they are allowed to be shared...
1059 if (SgProject::get_verbose() > 0)
1060 printf ("Remove the types that are allowed to be shared: deleteList.size() = %ld \n",(long)deleteList.size());
1061
1062 for (std::vector<SgNode*>::iterator i = deleteList.begin(); i != deleteList.end(); i++)
1063 {
1064 meaningIntersectionList.erase(find(meaningIntersectionList.begin(),meaningIntersectionList.end(),*i));
1065 }
1066
1067 if (SgProject::get_verbose() > 0)
1068 printf ("After removing the types there are meaningIntersectionList.size() = %ld \n",(long)meaningIntersectionList.size());
1069
1070 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
1071 {
1072 printf (" meaningIntersectionList[%d] = %p = %s = %s \n",i,meaningIntersectionList[i],meaningIntersectionList[i]->class_name().c_str(),get_name(meaningIntersectionList[i]).c_str());
1073 }
1074
1075 int unmatchedIRnodes = 0;
1076 if (help != nullptr)
1077 {
1078 std::vector<SgNode*> tmp_AST_original; // = AST_original;
1079 std::vector<SgNode*> tmp_AST_copy; // = AST_copy;
1080
1081 int AST_original_size = AST_original.size();
1082 for (int j = 0; j < AST_original_size; j++)
1083 {
1084 if (AST_original[j] != NULL && isSgType(AST_original[j]) == NULL)
1085 {
1086 tmp_AST_original.push_back(AST_original[j]);
1087 }
1088 }
1089
1090 int AST_copy_size = AST_copy.size();
1091 for (int j = 0; j < AST_copy_size; j++)
1092 {
1093 if (AST_copy[j] != NULL && isSgType(AST_copy[j]) == NULL)
1094 {
1095 tmp_AST_copy.push_back(AST_copy[j]);
1096 }
1097 }
1098
1099 std::vector<SgNode*> deleteList_original;
1100 std::vector<SgNode*> deleteList_copy;
1101 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1102 {
1103 // printf (" (before removing types) meaningIntersectionList[%d] = %p = %s \n",i,meaningIntersectionList[i],(meaningIntersectionList[i] != NULL) ? meaningIntersectionList[i]->class_name().c_str() : "NULL");
1104 SgCopyHelp::copiedNodeMapTypeIterator i = help->get_copiedNodeMap().find(tmp_AST_original[j]);
1105 // printf ("SgCopyHelp::copiedNodeMapTypeIterator i != help->get_copiedNodeMap().end() = %s \n",i != help->get_copiedNodeMap().end() ? "true" : "false");
1106 if (i != help->get_copiedNodeMap().end())
1107 {
1108 // Matched up an original IR node with it's copy
1109 SgNode* associated_node_copy = i->second;
1110 ROSE_ASSERT(associated_node_copy != NULL);
1111 deleteList_original.push_back(tmp_AST_original[j]);
1112 deleteList_copy.push_back(associated_node_copy);
1113#if 0
1114 // printf ("Original IR node = %p = %s copy = %p \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),associated_node_copy);
1115 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(tmp_AST_original[j]);
1116 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction_copy = isSgTemplateInstantiationMemberFunctionDecl(associated_node_copy);
1117 if (templateMemberFunction != NULL)
1118 {
1119 printf ("In SageInterface::astIntersection(): Found a SgTemplateInstantiationMemberFunctionDecl = %p copy = %p \n",templateMemberFunction,associated_node_copy);
1120 // templateMemberFunction->get_startOfConstruct()->display("original: debug");
1121 // templateMemberFunction_copy->get_startOfConstruct()->display("copy: debug");
1122 }
1123#endif
1124 }
1125 }
1126
1127 int deleteList_original_size = deleteList_original.size();
1128 for (int j = 0; j < deleteList_original_size; j++)
1129 {
1130 // tmp_AST_original.erase(find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]));
1131 std::vector<SgNode*>::iterator k = find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]);
1132 if (k != tmp_AST_original.end())
1133 {
1134 tmp_AST_original.erase(k);
1135 }
1136 }
1137
1138 if (SgProject::get_verbose() > 0)
1139 printf ("IR nodes different between the original AST and the copy of the AST = %" PRIuPTR " \n",tmp_AST_original.size());
1140
1141 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1142 {
1143 printf ("non matched IR node = %p = %s = %s \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),get_name(tmp_AST_original[j]).c_str());
1144 // tmp_AST_original[j]->get_startOfConstruct()->display("debug");
1145 }
1146
1147 unmatchedIRnodes = (int)tmp_AST_original.size();
1148 }
1149
1150 // DQ (11/2/2007): Make this an error now!
1151 if (differenceInSizes != 0)
1152 {
1153 SgProject* originalProject = isSgProject(original);
1154 if (originalProject != NULL)
1155 {
1156 printf ("In %s Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) IR nodes different = %d \n",
1157 (*originalProject)[0]->get_sourceFileNameWithoutPath().c_str(),AST_original_size,AST_copy_size,unmatchedIRnodes);
1158 }
1159
1160 if (unmatchedIRnodes > 0)
1161 {
1162 printf ("Make this an error under stricter testing \n");
1163 ROSE_ABORT();
1164 }
1165 }
1166
1167 return intersectionSet;
1168 }
1169
1170// AJ (10/21/2004): Added support for changing the symbol name associated with an SgInitializedName
1171// by updating the symbol table
1172int
1173SageInterface::set_name ( SgInitializedName *initializedNameNode, SgName new_name )
1174 {
1175 // find the appropriate symbol table, delete the symbol
1176 // with the old name and add a symbol with the new name.
1177 ROSE_ASSERT(initializedNameNode != NULL);
1178
1179#define DEBUG_SET_NAME 0
1180
1181 // SgNode * node = this;
1182#if DEBUG_SET_NAME
1183 printf ("In SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1184#endif
1185
1186#if 0
1187 // DQ (12/9/2004): This should likely call the get_scope function (which is more robust than traversing
1188 // parents, there is a reason why we are forced to include the scope explicitly on some IR nodes,
1189 // see test2004_133.C for details).
1190 while((node!=NULL) && ( isSgScopeStatement(node)==NULL))
1191 node = node->get_parent();
1192
1193 ROSE_ASSERT(node!=NULL);
1194
1195 SgScopeStatement * scope_stmt = isSgScopeStatement(node);
1196#else
1197 SgScopeStatement *scope_stmt = initializedNameNode->get_scope();
1198#endif
1199
1200 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1201 if (isSgEnumDeclaration(initializedNameNode->get_parent()) != NULL)
1202 {
1203 ROSE_ASSERT(scope_stmt != NULL);
1204 printf ("scope_stmt = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1205#if 0
1206 printf ("Detected isSgEnumDeclaration as parent: exiting as a test in SageInterface::set_name() \n");
1207 ROSE_ASSERT(false);
1208#endif
1209 }
1210
1211 ROSE_ASSERT(scope_stmt != NULL);
1212 ROSE_ASSERT(scope_stmt->get_symbol_table() != NULL);
1213 ROSE_ASSERT(scope_stmt->get_symbol_table()->get_table() != NULL);
1214
1215 SgDeclarationStatement * parent_declaration = initializedNameNode->get_declaration();
1216
1217 ROSE_ASSERT(parent_declaration != NULL);
1218
1219 // Find the symbols associated with p_name
1220 std::pair<SgSymbolTable::hash_iterator,SgSymbolTable::hash_iterator> pair_it = scope_stmt->get_symbol_table()->get_table()->equal_range(initializedNameNode->get_name());
1221
1222 SgSymbolTable::hash_iterator found_it = scope_stmt->get_symbol_table()->get_table()->end();
1223
1224 for (SgSymbolTable::hash_iterator it = pair_it.first; it != pair_it.second; ++it)
1225 {
1226#if DEBUG_SET_NAME
1227 printf ("Looking for symbol in scope = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1228 printf (" --- *it = %p = %s \n",(*it).second,(*it).second->class_name().c_str());
1229#endif
1230 switch(parent_declaration->variantT())
1231 {
1232 case V_SgFunctionParameterList:
1233 case V_SgVariableDeclaration:
1234 {
1235 if (isSgVariableSymbol((*it).second) != NULL)
1236 found_it = it;
1237 break;
1238 }
1239
1240 case V_SgClassDeclaration:
1241 {
1242 if (isSgClassSymbol((*it).second) != NULL)
1243 found_it = it;
1244 break;
1245 }
1246
1247 case V_SgFunctionDeclaration:
1248 {
1249 if (isSgFunctionSymbol((*it).second) != NULL)
1250 found_it = it;
1251 break;
1252 }
1253
1254 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1255 case V_SgEnumDeclaration:
1256 {
1257 if (isSgEnumFieldSymbol((*it).second) != NULL)
1258 found_it = it;
1259 break;
1260 }
1261
1262 default:
1263 {
1264 printf ("Default reached in switch in SageInterface::set_name() \n");
1265 }
1266 };
1267 }
1268
1269 // there is no Variable, Class or Function symbol associated with p_name
1270 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1271 {
1272 printf ("Warning: There is no Variable, Class, Function, or EnumValue symbol associated with p_name \n");
1273 return 0;
1274 }
1275
1276 // DQ (11/12/2018): In general, this can't be tested if we permit it to be transformed.
1277 if (statementCanBeTransformed(parent_declaration) == false)
1278 {
1279 printf ("WARNING: SageInterface::set_name(): This statement can not be transformed because it is part of a header file specific more then once with different include file syntax \n");
1280 return 0;
1281 }
1282 else
1283 {
1284#if DEBUG_SET_NAME
1285 printf ("In SageInterface::set_name(): This statement can be transformed! parent_declaration = %p = %s \n",parent_declaration,get_name(parent_declaration).c_str());
1286#endif
1287
1288#if 0
1289 // DQ (11/12/2018): Initial test problem should not permit a transformation!
1290 printf ("Exiting as a test! \n");
1291 ROSE_ABORT();
1292#endif
1293 }
1294
1295 SgSymbol * associated_symbol = (*found_it).second;
1296
1297 // erase the name from there
1298 scope_stmt->get_symbol_table()->get_table()->erase(found_it);
1299
1300 // insert the new_name in the symbol table
1301// CH (4/9/2010): Use boost::unordered instead
1302//#ifdef _MSCx_VER
1303#if 0
1304 // DQ (11/28/2009): Unclear if this code is a problem (testing).
1305
1306// CH (4/7/2010): It seems that the following code can be compiled under MSVC 9.0
1307//#pragma message ("WARNING: this code does not apprear to compile with MSVC.")
1308// printf ("ERROR: this code does not apprear to compile with MSVC. \n");
1309// ROSE_ASSERT(false);
1310 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1311#else
1312 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1313#endif
1314 // if insertion failed
1315 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1316 {
1317 printf ("Warning: insertion of new symbol failed \n");
1318 return 0;
1319 }
1320
1321#if DEBUG_SET_NAME
1322 // Set the p_name to the new_name
1323 printf ("Reset initializedNameNode->get_name() = %s to new_name = %s \n",initializedNameNode->get_name().str(),new_name.str());
1324#endif
1325
1326 // p_name = new_name;
1327 initializedNameNode->set_name(new_name);
1328
1329 // DQ (11/30/2018): Mark the enclosing statement as modified, so that it will be recognized
1330 // in the header file unparsing as being a header file that should be unparsed.
1331 SgStatement* enclosingStatement = getEnclosingStatement(initializedNameNode);
1332 ROSE_ASSERT(enclosingStatement != NULL);
1333 enclosingStatement->set_isModified(true);
1334 enclosingStatement->setTransformation();
1335
1336 // Invalidate the p_iterator, p_no_name and p_name data members in the Symbol table
1337
1338#if 1
1339 // Search the AST for references to this SgInitializedName (SgVarRefExp), check if the symbol matches
1340 // (we can do this since we only reused the exisitng symbol), and mark those expressions as modified.
1341 class RoseVisitor : public ROSE_VisitTraversal
1342 {
1343 public:
1344 int counter;
1345 SgSymbol* symbol;
1346
1348 void visit (SgNode* node)
1349 {
1350 SgVarRefExp* varRefExp = isSgVarRefExp(node);
1351 SgVariableSymbol* variableSymbol = isSgVariableSymbol(symbol);
1352
1353 ROSE_ASSERT(varRefExp != NULL);
1354 ROSE_ASSERT(variableSymbol != NULL);
1355
1356 if (varRefExp->get_symbol() == variableSymbol)
1357 {
1358#if DEBUG_SET_NAME
1359 printf ("In SageInterface::set_name(): Found associated SgVarRefExp varRefExp = %p to symbol associated_symbol = %p \n",varRefExp,variableSymbol);
1360#endif
1361#if 0
1362 printf ("Exiting as a test! \n");
1363 ROSE_ABORT();
1364#endif
1365 varRefExp->set_isModified(true);
1366 varRefExp->setTransformation();
1367#if 1
1368 // DQ (5/2/2021): The traversal over the file will identify the nesting of and transformations in outer (enclosing) IR nodes.
1369 // DQ (5/1/2021): I think that we may have to set the physical node id and maybe make it to be output. This is
1370 // special to the case of using the header file unparsing (any maybe the token-based unparsing with the header
1371 // file unparsing, but I think just the header file unparsing).
1372#if 0
1373 printf ("In SageInterface::set_name(): When unparsing header files, we need to set the physical file id to the correct file \n");
1374#endif
1375 // DQ (4/23/2021): I think it is a problem that the statement is not marked as a transformation so that we
1376 // know how to handle it with the token-based unparsing.
1377 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1378 ROSE_ASSERT(associatedStatement != NULL);
1379 associatedStatement->setTransformation();
1380#endif
1381#if 0
1382 // DQ (11/13/2018): Mark the statement associated with this SgVarRefExp (see test9 in UnparseHeaders_tests).
1383 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1384 ROSE_ASSERT(associatedStatement != NULL);
1385 // associatedStatement->set_isModified(true);
1386 // associatedStatement->set_containsTransformation(true);
1387 associatedStatement->setTransformation();
1388#endif
1389 }
1390 }
1391
1392 RoseVisitor(SgSymbol* symbol_parmeter) : counter(0), symbol(symbol_parmeter)
1393 {
1394#if 0
1395 printf ("roseVisitor::visit: counter %4d node = %s \n",counter,symbol_parmeter->class_name().c_str());
1396#endif
1397 counter++;
1398 }
1399 };
1400
1401 // RoseVisitor visitor;
1402 // visitor.traverseMemoryPool();
1403 RoseVisitor t1(associated_symbol);
1405#endif
1406
1407#if DEBUG_SET_NAME
1408 printf ("Leaving SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s (return 1) \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1409#endif
1410
1411 // DQ (4/23/2021): I think that we should be returning zero for no error
1412 // and one for an error, this function appears to have this detail reversed.
1413 return 1;
1414 }
1415
1416
1417void
1419 {
1420 printf ("In SageInterface::listHeaderFiles(): includeFile filename = %s \n",includeFile->get_filename().str());
1421
1422 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
1423 class PrefixTraversal : public AstSimpleProcessing
1424 {
1425 public:
1426 void visit (SgNode* node)
1427 {
1428 printf ("In listHeaderFiles visit(): node = %p = %s \n",node,node->class_name().c_str());
1429 SgIncludeFile* includeFile = isSgIncludeFile(node);
1430 if (includeFile != NULL)
1431 {
1432 printf ("include file: filename = %s \n",includeFile->get_filename().str());
1433 }
1434 }
1435 };
1436
1437 // Now buid the traveral object and call the traversal (preorder) on the function definition.
1438 PrefixTraversal traversal;
1439 traversal.traverse(includeFile, preorder);
1440
1441 }
1442
1443
1444bool
1446 {
1447 // DQ (5/9/2021): Adding support for detection of statements in a scope that must be unparsed.
1448 // This function supports the token-based unparsing when used with unparsing of header files
1449 // to know when the scope can be unparsed via it's token stream, even though a statement from
1450 // a header file may contain a transformation.
1451 // returns true if there is a statement in the scope that has to be unparsed (is from the same file as the scope).
1452 // returns false if the scope is empty or contains only statements associated with one or more header files.
1453 // When the scope has statements from the same file, then if there is a transformation contained in any of
1454 // those statements then we have to unparse the scope one statement at a time when using the token-based
1455 // unparsing. If the scope has no statements from the same file, then the existance of any statement that
1456 // contains a transformation does not case the statements to be unparsed individually.
1457
1458 ROSE_ASSERT(scope != NULL);
1459 int scope_file_id = scope->get_file_info()->get_physical_file_id();
1460
1461 bool return_value = false;
1462
1463 if (scope->containsOnlyDeclarations() == true)
1464 {
1465 SgDeclarationStatementPtrList & declarationStatementList = scope->getDeclarationList();
1466#if 1
1467 printf ("In scopeHasStatementsFromSameFile(): DeclarationStatementList not implemented \n");
1468#endif
1469#if 1
1470 printf ("declarationStatementList.size() = %zu \n",declarationStatementList.size());
1471#endif
1472 SgDeclarationStatementPtrList::iterator i = declarationStatementList.begin();
1473
1474 while (i != declarationStatementList.end() && return_value == false)
1475 {
1476 SgDeclarationStatement* statement = *i;
1477 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1478
1479 if (statement_file_id == scope_file_id)
1480 {
1481 return_value = true;
1482 }
1483
1484 i++;
1485 }
1486#if 0
1487 printf ("Exiting as a test! \n");
1488 ROSE_ASSERT(false);
1489#endif
1490 }
1491 else
1492 {
1493 SgStatementPtrList & statementList = scope->getStatementList();
1494#if 1
1495 printf ("In scopeHasStatementsFromSameFile(): StatementList not implemented \n");
1496#endif
1497 SgStatementPtrList::iterator i = statementList.begin();
1498
1499 while (i != statementList.end() && return_value == false)
1500 {
1501 SgStatement* statement = *i;
1502 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1503
1504 if (statement_file_id == scope_file_id)
1505 {
1506 return_value = true;
1507 }
1508
1509 i++;
1510 }
1511 }
1512
1513 return return_value;
1514 }
1515
1516
1517namespace
1518{
1519 template <class SageDecl>
1520 std::string genericGetName(SageDecl* dcl)
1521 {
1522 ROSE_ASSERT(dcl);
1523 return dcl->get_name();
1524 }
1525}
1526
1527
1528
1529
1530string
1532 {
1533 string name = "undefined_name";
1534
1535 ROSE_ASSERT(directive != NULL);
1536
1537 name = directive->class_name();
1538
1539#if 1
1540 // I don't think we need this code now!
1541 switch (directive->variantT())
1542 {
1543 // Separate out these cases...
1544 case V_SgIncludeDirectiveStatement:
1545 case V_SgDefineDirectiveStatement:
1546 case V_SgUndefDirectiveStatement:
1547 case V_SgIfdefDirectiveStatement:
1548 case V_SgIfndefDirectiveStatement:
1549 case V_SgDeadIfDirectiveStatement:
1550 case V_SgIfDirectiveStatement:
1551 case V_SgElseDirectiveStatement:
1552 case V_SgElseifDirectiveStatement:
1553 case V_SgLineDirectiveStatement:
1554 case V_SgWarningDirectiveStatement:
1555 case V_SgErrorDirectiveStatement:
1556 case V_SgEmptyDirectiveStatement:
1557 {
1558 name = directive->class_name();
1559 break;
1560 }
1561
1562 // case ClinkageDeclarationStatement:
1563 case V_SgClinkageStartStatement:
1564 case V_SgClinkageEndStatement:
1565 {
1566 name = directive->class_name();
1567 break;
1568 }
1569
1570 case V_SgFortranIncludeLine:
1571 {
1572 name = directive->class_name();
1573 break;
1574 }
1575
1576 default:
1577 // name = "default name (default case reached: not handled)";
1578 printf ("Warning: default case reached in SageInterface::get_name ( const SgC_PreprocessorDirectiveStatement* directive ), directive = %p = %s \n",
1579 directive,directive->class_name().c_str());
1580 ROSE_ABORT();
1581#if 0 // [Robb Matzke 2021-03-24]: unreachable
1582 name = "directive_default_name_case_reached_not_handled";
1583 break;
1584#endif
1585 }
1586#endif
1587
1588 return name;
1589 }
1590
1591string
1593 {
1594 string name = "undefined_name";
1595
1596 ROSE_ASSERT(declaration != NULL);
1597
1598 // DQ (11/23/2008): Handle the case of a Cpp directive...
1599 const SgC_PreprocessorDirectiveStatement* directive = isSgC_PreprocessorDirectiveStatement(declaration);
1600 if (directive != NULL)
1601 {
1602 return SageInterface::get_name (directive);
1603 }
1604
1605 switch (declaration->variantT())
1606 {
1607 case V_SgTemplateMemberFunctionDeclaration:
1608 name = isSgTemplateMemberFunctionDeclaration(declaration)->get_name().str();
1609 break;
1610
1611 case V_SgTemplateFunctionDeclaration:
1612 name = isSgTemplateFunctionDeclaration(declaration)->get_name().str();
1613 break;
1614
1615 case V_SgTemplateClassDeclaration:
1616 name = isSgTemplateClassDeclaration(declaration)->get_name().str();
1617 break;
1618
1619 case V_SgTemplateDeclaration:
1620 name = isSgTemplateDeclaration(declaration)->get_name().str();
1621 break;
1622
1623 case V_SgTemplateInstantiationDecl:
1624 name = isSgTemplateInstantiationDecl(declaration)->get_templateName().str();
1625 break;
1626
1627 case V_SgClassDeclaration:
1628 case V_SgDerivedTypeStatement:
1629 case V_SgJovialTableStatement:
1630 name = isSgClassDeclaration(declaration)->get_name().str();
1631 break;
1632
1633 // Rasmussen (8/2/2019): Added SgJovialDefineDeclaration and SgJovialDirectiveStatement
1634 // I'm not sure class_name() is correct. Probably get_name() should be fixed.
1635 case V_SgJovialDefineDeclaration:
1636 case V_SgJovialDirectiveStatement:
1637 case V_SgJovialCompoolStatement:
1638 name = "__" + declaration->class_name() + "_";
1639 name += StringUtility::numberToString(declaration);
1640 break;
1641
1642 case V_SgJovialLabelDeclaration:
1643 name = isSgJovialLabelDeclaration(declaration)->get_label();
1644 break;
1645
1646 case V_SgEnumDeclaration:
1647 name = isSgEnumDeclaration(declaration)->get_name().str();
1648 break;
1649
1650 // DQ (11/5/2014): Adding support for template typedef declarations (C++11 feature).
1651 case V_SgTemplateInstantiationTypedefDeclaration:
1652 // DQ (11/3/2014): Adding support for template typedef declarations (C++11 feature).
1653 case V_SgTemplateTypedefDeclaration:
1654 case V_SgTypedefDeclaration:
1655 name = isSgTypedefDeclaration(declaration)->get_name().str();
1656 break;
1657
1658 case V_SgFunctionDeclaration:
1659 case V_SgProgramHeaderStatement:
1660 case V_SgProcedureHeaderStatement:
1661 case V_SgMemberFunctionDeclaration:
1662 case V_SgTemplateInstantiationFunctionDecl:
1663 case V_SgTemplateInstantiationMemberFunctionDecl:
1664 case V_SgAdaFunctionRenamingDecl:
1665 case V_SgAdaEntryDecl:
1666 name = isSgFunctionDeclaration(declaration)->get_name().str();
1667 break;
1668
1669 case V_SgNamespaceDeclarationStatement:
1670 name = isSgNamespaceDeclarationStatement(declaration)->get_name().str();
1671 break;
1672
1673 // DQ (2/12/2006): Added support to get name of SgFunctionParameterList
1674 case V_SgFunctionParameterList:
1675 {
1676 // Parents should be set prior to calling these functions (if not we might have to implement that case)
1677 ROSE_ASSERT(declaration->get_parent() != NULL);
1678
1679 if (SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration->get_parent()))
1680 {
1681 name = get_name(functionDeclaration);
1682 }
1683 else if (SgScopeStatement* scopeStmt = isSgScopeStatement(declaration->get_parent()))
1684 {
1685 name = get_name(scopeStmt);
1686 }
1687 else ROSE_ABORT();
1688
1689 name += "_parameter_list_";
1690 break;
1691 }
1692
1693 // DQ (2/10/2012): Added support for template variable declarations (using base class support).
1694 case V_SgTemplateVariableDeclaration:
1695 case V_SgTemplateVariableInstantiation:
1696
1697 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1698 case V_SgVariableDeclaration:
1699 {
1700 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1701 // because we use this mechanism to generate names for unnamed structs and enums).
1702 name = "_variable_declaration_";
1703 const SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(declaration);
1704 ROSE_ASSERT(variableDeclaration != NULL);
1705 SgInitializedNamePtrList::const_iterator i = variableDeclaration->get_variables().begin();
1706
1707 // Make sure that we have at least one variable in the list
1708 ROSE_ASSERT(i != variableDeclaration->get_variables().end());
1709 do {
1710 // name += string(" ") + string((*i)->get_name().str());
1711 name += string((*i)->get_name().str());
1712 i++;
1713 }
1714 while (i != variableDeclaration->get_variables().end());
1715 break;
1716 }
1717
1718
1719 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1720 case V_SgVariableDefinition:
1721 {
1722 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1723 // because we use this mechanism to generate names for unnamed structs and enums).
1724 name = "_variable_definition_";
1725 const SgVariableDefinition* variableDefinition = isSgVariableDefinition(declaration);
1726 ROSE_ASSERT(variableDefinition != NULL);
1727
1728 // define this in terms of the associated SgInitializedName
1729 ROSE_ASSERT(variableDefinition->get_vardefn() != NULL);
1730 name += get_name(variableDefinition->get_vardefn());
1731 break;
1732 }
1733
1734 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
1735 case V_SgPragmaDeclaration:
1736 {
1737 name = "_pragma_declaration_";
1738 const SgPragmaDeclaration* pragmaDeclaration = isSgPragmaDeclaration(declaration);
1739 ROSE_ASSERT(pragmaDeclaration != NULL);
1740 ROSE_ASSERT(pragmaDeclaration->get_pragma() != NULL);
1741 name += get_name(pragmaDeclaration->get_pragma());
1742 break;
1743 }
1744
1745 // DQ (4/15/2007): Implemented case for using directive statement (forgot this case)
1746 case V_SgUsingDirectiveStatement:
1747 {
1748 name = "_using_directive_statement_";
1749 const SgUsingDirectiveStatement* usingDeclaration = isSgUsingDirectiveStatement(declaration);
1750 ROSE_ASSERT(usingDeclaration != NULL);
1751 ROSE_ASSERT(usingDeclaration->get_namespaceDeclaration() != NULL);
1752 name += get_name(usingDeclaration->get_namespaceDeclaration());
1753 break;
1754 }
1755
1756 // DQ (6/20/2007): Added new case!
1757 case V_SgNamespaceAliasDeclarationStatement:
1758 {
1759 name = "_namespace_alias_directive_statement_";
1760 const SgNamespaceAliasDeclarationStatement* namespaceAliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
1761 ROSE_ASSERT(namespaceAliasDeclaration != NULL);
1762 ROSE_ASSERT(namespaceAliasDeclaration->get_name().is_null() == false);
1763 name += namespaceAliasDeclaration->get_name();
1764 break;
1765 }
1766
1767 // DQ (6/20/2007): Added new case!
1768 case V_SgUsingDeclarationStatement:
1769 {
1770 name = "_using_declaration_statement_";
1771 const SgUsingDeclarationStatement* usingDeclaration = isSgUsingDeclarationStatement(declaration);
1772 ROSE_ASSERT(usingDeclaration != NULL);
1773 if (usingDeclaration->get_declaration() != NULL)
1774 {
1775 name += get_name(usingDeclaration->get_declaration());
1776 }
1777 else
1778 {
1779 ROSE_ASSERT(usingDeclaration->get_initializedName() != NULL);
1780 name += get_name(usingDeclaration->get_initializedName());
1781 }
1782 break;
1783 }
1784
1785 // DQ (6/20/2007): Added new case!
1786 case V_SgTemplateInstantiationDirectiveStatement:
1787 {
1788 name = "_template_instantiation_directive_statement_";
1789 ROSE_ASSERT(declaration != NULL);
1790 const SgTemplateInstantiationDirectiveStatement* templateInstantiationDirective = isSgTemplateInstantiationDirectiveStatement(declaration);
1791 ROSE_ASSERT(templateInstantiationDirective != NULL);
1792 ROSE_ASSERT(templateInstantiationDirective->get_declaration() != NULL);
1793#if 0
1794 printf ("declaration->get_declaration() = %p = %s \n",templateInstantiationDirective->get_declaration(),templateInstantiationDirective->get_declaration()->class_name().c_str());
1795#endif
1796 name += get_name(templateInstantiationDirective->get_declaration());
1797 break;
1798 }
1799
1800 case V_SgCtorInitializerList:
1801 {
1802 name = "_ctor_list_";
1803 const SgCtorInitializerList* ctorDeclaration = isSgCtorInitializerList(declaration);
1804 ROSE_ASSERT(ctorDeclaration != NULL);
1805 ROSE_ASSERT(ctorDeclaration->get_parent() != NULL);
1806 name += get_name(ctorDeclaration->get_parent());
1807 break;
1808 }
1809
1810 // DQ (8/9/2007): Added case for SgAsmStmt
1811 case V_SgAsmStmt:
1812 {
1813 name = "_asm_stmt_";
1814 const SgAsmStmt* asmStatement = isSgAsmStmt(declaration);
1815 ROSE_ASSERT(asmStatement != NULL);
1816 ROSE_ASSERT(asmStatement->get_parent() != NULL);
1817 name += StringUtility::numberToString(const_cast<SgAsmStmt*>(asmStatement));
1818 break;
1819 }
1820
1821 // DQ (8/22/2007): Added case for SgImplicitStatement
1822 case V_SgImplicitStatement:
1823 {
1824 name = "_fortran_implicit_";
1825 const SgImplicitStatement* implicitStatement = isSgImplicitStatement(declaration);
1826 ROSE_ASSERT(implicitStatement != NULL);
1827 ROSE_ASSERT(implicitStatement->get_parent() != NULL);
1828 name += StringUtility::numberToString(const_cast<SgImplicitStatement*>(implicitStatement));
1829 break;
1830 }
1831
1832 // DQ (8/22/2007): Added case for SgNamelistStatement
1833 case V_SgNamelistStatement:
1834 {
1835 name = "_fortran_namelist_";
1836 const SgNamelistStatement* namelistStatement = isSgNamelistStatement(declaration);
1837 ROSE_ASSERT(namelistStatement != NULL);
1838 ROSE_ASSERT(namelistStatement->get_parent() != NULL);
1839 name += StringUtility::numberToString(const_cast<SgNamelistStatement*>(namelistStatement));
1840 break;
1841 }
1842
1843 // DQ (11/21/2007): Added case for SgEquivalenceStatement
1844 case V_SgEquivalenceStatement:
1845 {
1846 name = "_fortran_equivalence_";
1847 const SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(declaration);
1848 ROSE_ASSERT(equivalenceStatement != NULL);
1849 ROSE_ASSERT(equivalenceStatement->get_parent() != NULL);
1850 name += StringUtility::numberToString(const_cast<SgEquivalenceStatement*>(equivalenceStatement));
1851 break;
1852 }
1853
1854
1855 // DQ (11/21/2007): Added case for SgCommonBlock
1856 case V_SgCommonBlock:
1857 {
1858 name = "_fortran_common_block_";
1859 const SgCommonBlock* commonBlockStatement = isSgCommonBlock(declaration);
1860 ROSE_ASSERT(commonBlockStatement != NULL);
1861 ROSE_ASSERT(commonBlockStatement->get_parent() != NULL);
1862 name += StringUtility::numberToString(const_cast<SgCommonBlock*>(commonBlockStatement));
1863 break;
1864 }
1865
1866 // DQ (11/21/2007): Added case for SgImportStatement
1867 case V_SgImportStatement:
1868 {
1869 name = "_fortran_import_stmt_";
1870 const SgImportStatement* importStatement = isSgImportStatement(declaration);
1871 ROSE_ASSERT(importStatement != NULL);
1872 ROSE_ASSERT(importStatement->get_parent() != NULL);
1873 name += StringUtility::numberToString(const_cast<SgImportStatement*>(importStatement));
1874 break;
1875 }
1876
1877 // DQ (11/21/2007): Added case for SgFormatStatement
1878 case V_SgFormatStatement:
1879 {
1880 name = "_fortran_format_stmt_";
1881 const SgFormatStatement* formatStatement = isSgFormatStatement(declaration);
1882 ROSE_ASSERT(formatStatement != NULL);
1883 ROSE_ASSERT(formatStatement->get_parent() != NULL);
1884 name += StringUtility::numberToString(const_cast<SgFormatStatement*>(formatStatement));
1885 break;
1886 }
1887
1888 // DQ (12/27/2007): Added case for SgModuleStatement
1889 case V_SgModuleStatement:
1890 {
1891 name = "_fortran_module_stmt_";
1892 const SgModuleStatement* moduleStatement = isSgModuleStatement(declaration);
1893 ROSE_ASSERT(moduleStatement != NULL);
1894 ROSE_ASSERT(moduleStatement->get_parent() != NULL);
1895 name += StringUtility::numberToString(const_cast<SgModuleStatement*>(moduleStatement));
1896 break;
1897 }
1898
1899 // DQ (12/27/2007): Added case for SgUseStatement
1900 case V_SgUseStatement:
1901 {
1902 name = "_fortran_use_stmt_";
1903 const SgUseStatement* useStatement = isSgUseStatement(declaration);
1904 ROSE_ASSERT(useStatement != NULL);
1905 ROSE_ASSERT(useStatement->get_parent() != NULL);
1906 name += StringUtility::numberToString(const_cast<SgUseStatement*>(useStatement));
1907 break;
1908 }
1909
1910 // DQ (12/28/2007): Added case for SgContainsStatement
1911 case V_SgContainsStatement:
1912 {
1913 name = "_fortran_contains_stmt_";
1914 const SgContainsStatement* containsStatement = isSgContainsStatement(declaration);
1915 ROSE_ASSERT(containsStatement != NULL);
1916 ROSE_ASSERT(containsStatement->get_parent() != NULL);
1917 name += StringUtility::numberToString(const_cast<SgContainsStatement*>(containsStatement));
1918 break;
1919 }
1920
1921 // DQ (1/20/2008): Added case for SgEntryStatement
1922 case V_SgEntryStatement:
1923 {
1924 name = "_fortran_entry_stmt_";
1925 const SgEntryStatement* entryStatement = isSgEntryStatement(declaration);
1926 ROSE_ASSERT(entryStatement != NULL);
1927 ROSE_ASSERT(entryStatement->get_parent() != NULL);
1928 name += StringUtility::numberToString(const_cast<SgEntryStatement*>(entryStatement));
1929 break;
1930 }
1931
1932 // DQ (1/23/2008): Added case for SgAttributeSpecificationStatement
1933 case V_SgAttributeSpecificationStatement:
1934 {
1935 name = "_fortran_attribute_specification_stmt_";
1936 const SgAttributeSpecificationStatement* statement = isSgAttributeSpecificationStatement(declaration);
1937 ROSE_ASSERT(statement != NULL);
1938 ROSE_ASSERT(statement->get_parent() != NULL);
1940 break;
1941 }
1942
1943 case V_SgInterfaceStatement:
1944 {
1945 name = "_fortran_interface_stmt_";
1946 const SgInterfaceStatement* statement = isSgInterfaceStatement(declaration);
1947 ROSE_ASSERT(statement != NULL);
1948 ROSE_ASSERT(statement->get_parent() != NULL);
1949 name += StringUtility::numberToString(const_cast<SgInterfaceStatement*>(statement));
1950 break;
1951 }
1952
1953 case V_SgFortranIncludeLine:
1954 {
1955 name = "_fortran_include_line_stmt_";
1956 const SgFortranIncludeLine* statement = isSgFortranIncludeLine(declaration);
1957 ROSE_ASSERT(statement != NULL);
1958 ROSE_ASSERT(statement->get_parent() != NULL);
1959 name += StringUtility::numberToString(const_cast<SgFortranIncludeLine*>(statement));
1960 break;
1961 }
1962
1963 // DQ (4/16/2011): Added Java import statment support.
1964 case V_SgJavaImportStatement:
1965 {
1966 name = "_java_import_stmt_";
1967 const SgJavaImportStatement* statement = isSgJavaImportStatement(declaration);
1968 ROSE_ASSERT(statement != NULL);
1969 ROSE_ASSERT(statement->get_parent() != NULL);
1970 name += StringUtility::numberToString(const_cast<SgJavaImportStatement*>(statement));
1971 break;
1972 }
1973
1974 case V_SgJavaPackageDeclaration:
1975 {
1976 name = "_java_package_declaration_";
1977 const SgJavaPackageDeclaration* package_declaration = isSgJavaPackageDeclaration(declaration);
1978 ROSE_ASSERT(package_declaration != NULL);
1979 ROSE_ASSERT(package_declaration->get_parent() != NULL);
1980 name += StringUtility::numberToString(const_cast<SgJavaPackageDeclaration*>(package_declaration));
1981 break;
1982 }
1983
1984 case V_SgJavaPackageStatement:
1985 {
1986 name = "_java_package_stmt_";
1987 const SgJavaPackageStatement* statement = isSgJavaPackageStatement(declaration);
1988 ROSE_ASSERT(statement != NULL);
1989 ROSE_ASSERT(statement->get_parent() != NULL);
1990 name += StringUtility::numberToString(const_cast<SgJavaPackageStatement*>(statement));
1991 break;
1992 }
1993
1994 // DQ (1/21/2018): Added case for C++11 SgStaticAssertionDeclaration
1995 case V_SgStaticAssertionDeclaration:
1996 {
1997 name = "_static_assertion_declaration_stmt_";
1998 const SgStaticAssertionDeclaration* statement = isSgStaticAssertionDeclaration(declaration);
1999 ROSE_ASSERT(statement != NULL);
2000 ROSE_ASSERT(statement->get_parent() != NULL);
2001 name += StringUtility::numberToString(const_cast<SgStaticAssertionDeclaration*>(statement));
2002 break;
2003 }
2004
2005 case V_SgNonrealDecl:
2006 {
2007 const SgNonrealDecl * nrdecl = isSgNonrealDecl(declaration);
2008 ROSE_ASSERT(nrdecl != NULL);
2009 name = nrdecl->get_name();
2010 break;
2011 }
2012
2013 // DQ (3/26/2019): Adding support for new declaration.
2014 case V_SgEmptyDeclaration:
2015 {
2016 const SgEmptyDeclaration * emptyDeclaration = isSgEmptyDeclaration(declaration);
2017 ROSE_ASSERT(emptyDeclaration != NULL);
2018 name = string("emptyDeclaration") + StringUtility::numberToString(const_cast<SgDeclarationStatement*>(declaration));
2019 break;
2020 }
2021
2022 case V_SgAdaPackageSpecDecl:
2023 {
2024 name = genericGetName(isSgAdaPackageSpecDecl(declaration));
2025 break;
2026 }
2027
2028 case V_SgAdaPackageBodyDecl:
2029 {
2030 name = genericGetName(isSgAdaPackageBodyDecl(declaration));
2031 break;
2032 }
2033
2034 case V_SgAdaFormalTypeDecl:
2035 {
2036 name = genericGetName(isSgAdaFormalTypeDecl(declaration));
2037 break;
2038 }
2039
2040 case V_SgAdaGenericDecl:
2041 {
2042 // need to look inside the declaration wrapped by the generic.
2043 const SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(declaration);
2044 name = get_name(gendcl->get_declaration());
2045 break;
2046#if OBSOLETE_CODE
2047 if (isSgFunctionDeclaration(dcl->get_declaration())) {
2048 name = "_ada_generic_decl_" + genericGetName(isSgFunctionDeclaration(dcl->get_declaration()));
2049 break;
2050 }
2051 if (isSgAdaPackageSpecDecl(dcl->get_declaration())) {
2052 name = "_ada_generic_decl_" + genericGetName(isSgAdaPackageSpecDecl(dcl->get_declaration()));
2053 break;
2054 }
2055
2056 // something malformed in the tree if we get here
2057 ROSE_ABORT();
2058 break;
2059#endif /* OBSOLETE_CODE */
2060 }
2061
2062 case V_SgAdaDiscriminatedTypeDecl:
2063 {
2064 const SgAdaDiscriminatedTypeDecl* dcl = isSgAdaDiscriminatedTypeDecl(declaration);
2065 ROSE_ASSERT(dcl);
2066
2067 if (const SgDeclarationStatement* discrDcl = dcl->get_discriminatedDecl())
2068 {
2069 name = get_name(discrDcl);
2070 }
2071 else
2072 {
2073 name = "_incomplete_Ada_discriminated_type_";
2074 }
2075
2076 break;
2077 }
2078
2079 case V_SgAdaVariantDecl:
2080 {
2081 name = "_ada_variant_decl_";
2082 break;
2083 }
2084
2085 case V_SgAdaAttributeClause:
2086 {
2087 name = "_ada_attribute_clause_";
2088 break;
2089 }
2090
2091 case V_SgAdaRepresentationClause:
2092 {
2093 name = "_ada_representation_clause_";
2094 break;
2095 }
2096
2097 case V_SgAdaEnumRepresentationClause:
2098 {
2099 name = "_ada_enum_representation_clause_";
2100 break;
2101 }
2102
2103 case V_SgAdaComponentClause:
2104 {
2105 name = "_ada_component_clause_";
2106 break;
2107 }
2108
2109 case V_SgAdaTaskTypeDecl:
2110 {
2111 name = genericGetName(isSgAdaTaskTypeDecl(declaration));
2112 break;
2113 }
2114
2115 case V_SgAdaProtectedTypeDecl:
2116 {
2117 name = genericGetName(isSgAdaProtectedTypeDecl(declaration));
2118 break;
2119 }
2120
2121 case V_SgAdaTaskBodyDecl:
2122 {
2123 name = genericGetName(isSgAdaTaskBodyDecl(declaration));
2124 break;
2125 }
2126
2127 case V_SgAdaProtectedBodyDecl:
2128 {
2129 name = genericGetName(isSgAdaProtectedBodyDecl(declaration));
2130 break;
2131 }
2132
2133 case V_SgAdaRenamingDecl:
2134 {
2135 name = genericGetName(isSgAdaRenamingDecl(declaration));
2136 break;
2137 }
2138
2139 case V_SgAdaTaskSpecDecl:
2140 {
2141 name = genericGetName(isSgAdaTaskSpecDecl(declaration));
2142 break;
2143 }
2144
2145 case V_SgAdaProtectedSpecDecl:
2146 {
2147 name = genericGetName(isSgAdaProtectedSpecDecl(declaration));
2148 break;
2149 }
2150
2151 case V_SgAdaGenericInstanceDecl:
2152 {
2153 name = genericGetName(isSgAdaGenericInstanceDecl(declaration));
2154 break;
2155 }
2156
2157 case V_SgAdaFormalPackageDecl:
2158 {
2159 name = genericGetName(isSgAdaFormalPackageDecl(declaration));
2160 break;
2161 }
2162
2163 case V_SgAdaParameterList:
2164 {
2165 const SgAdaParameterList* plst = isSgAdaParameterList(declaration);
2166 ROSE_ASSERT(plst);
2167
2168 name = std::accumulate( plst->get_parameters().begin(), plst->get_parameters().end(),
2169 std::string{"_ada_parameter_list_"},
2170 [](std::string n, SgDeclarationStatement* rhs) -> std::string
2171 {
2172 n += SageInterface::get_name(rhs);
2173 return n;
2174 }
2175 );
2176 break;
2177 }
2178
2179 // Note that the case for SgVariableDeclaration is not implemented
2180 default:
2181 printf ("Warning: default case reached in SageInterface::get_name ( const SgDeclarationStatement* declaration ), declaration = %p = %s \n",
2182 declaration,declaration->class_name().c_str());
2183 ROSE_ABORT();
2184 }
2185
2186 return name;
2187 }
2188
2189string
2191 {
2192 string name = "undefined_name";
2193
2194 ROSE_ASSERT(scope != NULL);
2195
2196 switch (scope->variantT())
2197 {
2198 // DQ (6/11/2011): Added support for new template IR nodes.
2199 case V_SgTemplateClassDefinition:
2200 name = get_name(isSgTemplateClassDefinition(scope)->get_declaration());
2201 break;
2202
2203 case V_SgClassDefinition:
2204 case V_SgTemplateInstantiationDefn:
2205 name = get_name(isSgClassDefinition(scope)->get_declaration());
2206 break;
2207
2208 // DQ (9/8/2012): Added missing case for SgTemplateFunctionDefinition.
2209 case V_SgTemplateFunctionDefinition:
2210 case V_SgFunctionDefinition:
2211 name = get_name(isSgFunctionDefinition(scope)->get_declaration());
2212 break;
2213
2214 case V_SgNamespaceDefinitionStatement:
2215 name = get_name(isSgNamespaceDefinitionStatement(scope)->get_namespaceDeclaration());
2216 break;
2217 case V_SgJavaLabelStatement:
2218 name = (isSgJavaLabelStatement(scope)->get_label()).getString();
2219 break;
2220
2221 // DQ (7/18/2017): Added support for the new declaration scope.
2222 case V_SgDeclarationScope:
2223
2224 // DQ (11/30/2007): Added more fortran support.
2225 case V_SgAssociateStatement:
2226 case V_SgJavaForEachStatement:
2227
2228 case V_SgFunctionParameterScope:
2229 case V_SgAdaPackageSpec:
2230 case V_SgAdaPackageBody:
2231 case V_SgAdaTaskSpec:
2232 case V_SgAdaTaskBody:
2233 case V_SgAdaProtectedSpec:
2234 case V_SgAdaProtectedBody:
2235 case V_SgAdaGenericDefn:
2236 case V_SgAdaAcceptStmt:
2237 case V_SgJovialForThenStatement: //Rasmussen: Jovial for statement
2238 case V_SgMatlabForStatement: //SK: Matlab for statement
2239 case V_SgBasicBlock:
2240 case V_SgCatchOptionStmt:
2241 case V_SgDoWhileStmt:
2242 case V_SgForStatement:
2243 case V_SgGlobal:
2244 case V_SgIfStmt:
2245 case V_SgSwitchStatement:
2246 case V_SgWhileStmt:
2247 case V_SgFortranDo:
2248 case V_SgForAllStatement:
2249 case V_SgRangeBasedForStatement:
2250 name = StringUtility::numberToString(const_cast<SgScopeStatement*>(scope));
2251 break;
2252
2253 default:
2254 printf ("Error: undefined case (SgScopeStatement) in SageInterface::get_name(): node = %s \n",scope->class_name().c_str());
2255 ROSE_ABORT();
2256 }
2257
2258 return name;
2259 }
2260
2261string
2263 {
2264 string name = "undefined_name";
2265
2266 ROSE_ASSERT(stmt != NULL);
2267
2268 const SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
2269 if (declaration != NULL)
2270 {
2271 name = get_name(declaration);
2272 }
2273 else
2274 {
2275 const SgScopeStatement* scope = isSgScopeStatement(stmt);
2276 if (scope != NULL)
2277 {
2278 name = get_name(scope);
2279 }
2280 else
2281 {
2282 // DQ (10/25/2007): This is better since it names the SgLabelStatement case
2283 switch (stmt->variantT())
2284 {
2285#if 0
2286 case V_SgBreakStmt:
2287 case V_SgCaseOptionStmt:
2288 case V_SgCatchStatementSeq:
2289 case V_SgClinkageStartStatement:
2290 case V_SgContinueStmt:
2291 case V_SgDefaultOptionStmt:
2292 case V_SgExprStmt:
2293 case V_SgForInitStmt:
2294 case V_SgFunctionTypeTable:
2295 case V_SgGotoStatement:
2296 case V_SgReturnStmt:
2297 case V_SgSpawnStmt:
2298 case V_SgTryStmt:
2299 name = stmt->class_name();
2300 break;
2301#endif
2302 case V_SgLabelStatement:
2303 {
2304 const SgLabelStatement* labelStatement = isSgLabelStatement(stmt);
2305 name = labelStatement->get_label().str();
2306 break;
2307 }
2308
2309 default:
2310 {
2311 // printf ("Default reached in switch \n");
2312 // name = "default name";
2313 name = stmt->class_name();
2314 break;
2315 }
2316 }
2317 }
2318 }
2319
2320 return name;
2321 }
2322
2323string
2325 {
2326 // This function is useful for debugging
2327 // This is the most general case of a function to return a name for an IR node.
2328 ROSE_ASSERT(node != NULL);
2329
2330 string name = "undefined_name";
2331
2332 ROSE_ASSERT(node != NULL);
2333
2334 switch (node->variantT())
2335 {
2336 case V_SgInitializedName:
2337 {
2338 const SgInitializedName* initializedName = isSgInitializedName(node);
2339 if (initializedName != NULL)
2340 {
2341 name = initializedName->get_name().str();
2342 }
2343 break;
2344 }
2345#if 1
2346 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
2347 case V_SgPragma:
2348 {
2349 name = "_pragma_string_";
2350 const SgPragma* pragma = isSgPragma(node);
2351 ROSE_ASSERT(pragma != NULL);
2352 name += pragma->get_pragma();
2353 break;
2354 }
2355#endif
2356
2357 // DQ (5/31/2007): Implemented case for SgProject
2358 case V_SgProject:
2359 {
2360 name = "_project_";
2361 break;
2362 }
2363
2364 // DQ (5/31/2007): Implemented case for SgFile
2365 // case V_SgFile:
2366 case V_SgSourceFile:
2367#ifdef ROSE_ENABLE_BINARY_ANALYSIS
2368 case V_SgBinaryComposite:
2369#endif
2370 {
2371 name = "_file_";
2372
2373 // DQ (3/1/2009): Added support to include the file name.
2374 const SgFile* file = isSgFile(node);
2375 ROSE_ASSERT(file != NULL);
2376
2377 name += file->getFileName();
2378 break;
2379 }
2380
2381 // DQ (5/31/2007): Implemented case for SgSymbolTable
2382 case V_SgSymbolTable:
2383 {
2384 name = "_symbol_table_";
2385 break;
2386 }
2387
2388 // DQ (5/31/2007): Implemented case for SgStorageModifier
2389 case V_SgStorageModifier:
2390 {
2391 name = "_storage_modifier_";
2392 break;
2393 }
2394
2395
2396 // DQ (5/31/2007): Implemented case for Sg_File_Info
2397 case V_Sg_File_Info:
2398 {
2399 name = "_file_info_";
2400 break;
2401 }
2402
2403 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2404 case V_SgTemplateArgument:
2405 {
2406 name = "_template_argument_";
2407 const SgTemplateArgument* templateArgument = isSgTemplateArgument(node);
2408 ROSE_ASSERT(templateArgument != NULL);
2409 switch(templateArgument->get_argumentType())
2410 {
2412 {
2413 SgType* t = templateArgument->get_type();
2414 ROSE_ASSERT(t != NULL);
2415 name += get_name(t);
2416 break;
2417 }
2418
2420 {
2421 SgExpression* t = templateArgument->get_expression();
2422
2423 // DQ (8/11/2013): Adding support for including an initializedName instead of an expression (for template parameters used as expressions).
2424 // ROSE_ASSERT(t != NULL);
2425 // name += get_name(t);
2426 if (t != NULL)
2427 {
2428 ROSE_ASSERT(templateArgument->get_initializedName() == NULL);
2429 name += get_name(t);
2430 }
2431 else
2432 {
2433 ROSE_ASSERT(t == NULL);
2434 SgInitializedName* initializedName = templateArgument->get_initializedName();
2435 ROSE_ASSERT(initializedName != NULL);
2436
2437 name += get_name(initializedName);
2438 }
2439 break;
2440 }
2441
2443 {
2444 // SgTemplateDeclaration* t = templateArgument->get_templateDeclaration();
2445 SgDeclarationStatement* t = templateArgument->get_templateDeclaration();
2446 ROSE_ASSERT(t != NULL);
2447 name += get_name(t);
2448 break;
2449 }
2450
2451 default:
2452 {
2453 printf ("Error: default case reached in switch on templateArgument->get_argumentType() \n");
2454 ROSE_ABORT();
2455 }
2456 }
2457 break;
2458 }
2459
2460
2461 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2462 case V_SgTypeModifier:
2463 {
2464 const SgTypeModifier* typeModifier = isSgTypeModifier(node);
2465 ROSE_ASSERT(typeModifier != NULL);
2466 name = "_type_modifier_" + typeModifier->displayString();
2467 break;
2468 }
2469
2470 // DQ (11/19/2007): Implemented case for SgNameGroup
2471 case V_SgNameGroup:
2472 {
2473 const SgNameGroup* nameGroup = isSgNameGroup(node);
2474 ROSE_ASSERT(nameGroup != NULL);
2475 name = "_name_group_" + nameGroup->get_group_name();
2476 break;
2477 }
2478
2479 // DQ (11/20/2007): Implemented case for Fortran data statement support
2480 case V_SgDataStatementGroup:
2481 {
2482 const SgDataStatementGroup* dataGroup = isSgDataStatementGroup(node);
2483 ROSE_ASSERT(dataGroup != NULL);
2484 name = "_data_statement_group_";
2485 break;
2486 }
2487
2488 // DQ (11/20/2007): Implemented case for Fortran data statement support
2489 case V_SgDataStatementObject:
2490 {
2491 const SgDataStatementObject* dataObject = isSgDataStatementObject(node);
2492 ROSE_ASSERT(dataObject != NULL);
2493 name = "_data_statement_object_";
2494 break;
2495 }
2496
2497 // DQ (11/20/2007): Implemented case for Fortran data statement support
2498 case V_SgDataStatementValue:
2499 {
2500 const SgDataStatementValue* dataValue = isSgDataStatementValue(node);
2501 ROSE_ASSERT(dataValue != NULL);
2502 name = "_data_statement_value_";
2503 break;
2504 }
2505
2506 // DQ (11/19/2007): Implemented case for SgCommonBlock
2507 case V_SgCommonBlockObject:
2508 {
2509 const SgCommonBlockObject* commonBlockObject = isSgCommonBlockObject(node);
2510 ROSE_ASSERT(commonBlockObject != NULL);
2511 name = "_common_block_object_" + commonBlockObject->get_block_name();
2512 break;
2513 }
2514
2515 // DQ (12/23/2007): Added support for repeat_specification
2516 case V_SgFormatItem:
2517 {
2518 const SgFormatItem* formatItem = isSgFormatItem(node);
2519 ROSE_ASSERT(formatItem != NULL);
2520 name = "_format_item_";
2521 break;
2522 }
2523
2524 // DQ (12/23/2007): Added support for repeat_specification
2525 case V_SgFormatItemList:
2526 {
2527 const SgFormatItemList* formatItemList = isSgFormatItemList(node);
2528 ROSE_ASSERT(formatItemList != NULL);
2529 name = "_format_item_list_";
2530 break;
2531 }
2532
2533 // DQ (12/23/2007): Added support for repeat_specification
2534 case V_SgRenamePair:
2535 {
2536 const SgRenamePair* renamePair = isSgRenamePair(node);
2537 ROSE_ASSERT(renamePair != NULL);
2538 name = renamePair->get_local_name() + "__" + renamePair->get_use_name() + "_rename_pair_";
2539 break;
2540 }
2541
2542 // DQ (12/2/2010): Implemented case for SgName
2543 case V_SgName:
2544 {
2545 const SgName* name_node = isSgName(node);
2546 ROSE_ASSERT(name_node != NULL);
2547 name = "_name_" + name_node->getString();
2548 break;
2549 }
2550
2551 // DQ (8/8/2013): Implemented case for SgTemplateParameter
2552 case V_SgTemplateParameter:
2553 {
2554 const SgTemplateParameter* template_parameter_node = isSgTemplateParameter(node);
2555 ROSE_ASSERT(template_parameter_node != NULL);
2556 name = "_template_parameter_";
2557
2558 switch(template_parameter_node->get_parameterType())
2559 {
2561 {
2562 name += "type_parameter_";
2563 break;
2564 }
2565
2567 {
2568 name += "nontype_parameter_";
2569#if 1
2570 name += template_parameter_node->unparseToString();
2571#else
2572 if (template_parameter_node->get_expression() != NULL)
2573 {
2574 name += template_parameter_node->get_expression()->unparseToString();
2575 }
2576 else
2577 {
2578 ROSE_ASSERT(template_parameter_node->get_initializedName() != NULL);
2579
2580 // DQ (8/8/2013): This does not handle the case of "template <void (foo::*M)()> void test() {}"
2581 // since what is unparsed is: "_template_parameter_nontype_parameter_M"
2582 // instead of a string to represent what is in "void (foo::*M)()"
2583 // and differentiate it from: "int foo::*M" in: "template <void (foo::*M)()> void test() {}"
2584 name += template_parameter_node->get_initializedName()->unparseToString();
2585 }
2586#endif
2587 break;
2588 }
2589
2591 {
2592 name += "template_parameter_";
2593 break;
2594 }
2595
2596 default:
2597 {
2598 printf ("Error: default reached \n");
2599 ROSE_ABORT();
2600 }
2601 }
2602 break;
2603 }
2604
2605 // DQ (1/21/2019): Implemented case for SgBaseClass
2606 case V_SgBaseClass:
2607 {
2608 const SgBaseClass* base_class_node = isSgBaseClass(node);
2609 ROSE_ASSERT(base_class_node != NULL);
2610 ROSE_ASSERT(base_class_node->get_base_class() != NULL);
2611
2612 // Add the access modifier to the output.
2613 string access = "";
2614 const SgBaseClassModifier* baseClassModifier = base_class_node->get_baseClassModifier();
2615 ROSE_ASSERT(baseClassModifier != NULL);
2616 access = baseClassModifier->displayString();
2617
2618 name = "_base_class_" + access + "_" + get_name(base_class_node->get_base_class());
2619 break;
2620 }
2621
2622 default:
2623 {
2624 printf ("Default reached in switch for SgSupport IR node = %s \n",node->class_name().c_str());
2625 name = "default name";
2626 // ROSE_ASSERT(false);
2627 break;
2628 }
2629 }
2630
2631 return name;
2632 }
2633
2634
2635string
2637 {
2638 // This function is useful for debugging
2639 // This is the most general case of a function to return a name for an IR node.
2640 ROSE_ASSERT(symbol != NULL);
2641
2642 string aliasSymbolPrefix = "";
2643 if (isSgAliasSymbol(symbol) != NULL)
2644 {
2645 aliasSymbolPrefix = "_ALIAS";
2646 }
2647
2648 // printf ("In SageInterface::get_name(): symbol->get_symbol_basis() = %p = %s \n",symbol->get_symbol_basis(),symbol->get_symbol_basis()->class_name().c_str());
2649 // printf ("In SageInterface::get_name(): symbol->get_declaration() = %p = %s \n",symbol->get_declaration(),symbol->get_declaration()->class_name().c_str());
2650
2651 // This is a call to the "get_name()" virtual function
2652 return symbol->get_name() + aliasSymbolPrefix + "_symbol_";
2653 }
2654
2655string
2657 {
2658 // This function is useful for debugging
2659 // This is the most general case of a function to return a name for an IR node.
2660 ROSE_ASSERT(type != NULL);
2661
2662 string returnName;
2663
2664 const SgNamedType* namedType = isSgNamedType(type);
2665 if (namedType != NULL)
2666 {
2667 returnName = "named_type_";
2668 returnName = namedType->get_name().getString();
2669 }
2670 else
2671 {
2672 switch(type->variantT())
2673 {
2674 case V_SgPointerType:
2675 {
2676 const SgPointerType* pointerType = isSgPointerType(type);
2677 returnName = "pointer_to_";
2678 returnName += get_name(pointerType->get_base_type());
2679 break;
2680 }
2681
2682 case V_SgReferenceType:
2683 {
2684 const SgReferenceType* referenceType = isSgReferenceType(type);
2685 returnName = "reference_to_";
2686 returnName += get_name(referenceType->get_base_type());
2687 break;
2688 }
2689
2690 case V_SgArrayType:
2691 {
2692 const SgArrayType* arrayType = isSgArrayType(type);
2693 returnName = "array_of_";
2694 returnName += get_name(arrayType->get_base_type());
2695 break;
2696 }
2697
2698 case V_SgModifierType:
2699 {
2700 const SgModifierType* modifierType = isSgModifierType(type);
2701 returnName = get_name(&(modifierType->get_typeModifier()));
2702 returnName += get_name(modifierType->get_base_type());
2703 break;
2704 }
2705
2706 // DQ (8/26/2012): Added case to support template declaration work.
2707 case V_SgTemplateType:
2708 {
2709 const SgTemplateType* templateType = isSgTemplateType(type);
2710 returnName = "templateType_";
2711 returnName += templateType->get_name();
2712 break;
2713 }
2714
2715 default:
2716 {
2717 returnName = type->class_name();
2718 }
2719 }
2720 }
2721
2722 return returnName;
2723 }
2724
2725string
2727 {
2728 string name = "undefined_name";
2729
2730 // ROSE_ASSERT(expr != NULL);
2731 switch(expr->variantT())
2732 {
2733 case V_SgVarRefExp:
2734 {
2735 const SgVarRefExp* varRef = isSgVarRefExp(expr);
2736 name = "var_ref_of_";
2737 ROSE_ASSERT(varRef != NULL);
2738 ROSE_ASSERT(varRef->get_symbol() != NULL);
2739 name += varRef->get_symbol()->get_name();
2740 break;
2741 }
2742
2743 // DQ (2/2/2011): Added case to support fortran use of label references in alternate return parameters.
2744 case V_SgLabelRefExp:
2745 {
2746 const SgLabelRefExp* labelRef = isSgLabelRefExp(expr);
2747 name = "label_ref_of_";
2748 ROSE_ASSERT(labelRef != NULL);
2749 ROSE_ASSERT(labelRef->get_symbol() != NULL);
2750 name += labelRef->get_symbol()->get_name();
2751 break;
2752 }
2753
2754 case V_SgPntrArrRefExp:
2755 {
2756 const SgPntrArrRefExp* arrayRef = isSgPntrArrRefExp(expr);
2757 name = "array_ref_of_";
2758 name += get_name(arrayRef->get_lhs_operand());
2759 name += "_at_";
2760 name += get_name(arrayRef->get_rhs_operand());
2761 break;
2762 }
2763
2764 case V_SgFunctionCallExp:
2765 {
2766 const SgFunctionCallExp* functionCall = isSgFunctionCallExp(expr);
2767 name = "function_call_";
2768 name += get_name(functionCall->get_function());
2769 break;
2770 }
2771
2772 case V_SgFunctionRefExp:
2773 {
2774 const SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(expr);
2775 name = "function_ref_";
2776 name += functionRefExp->get_symbol()->get_name();
2777 break;
2778 }
2779
2780 // DQ (4/19/2013): Added support for SgMemberFunctionRefExp.
2781 case V_SgMemberFunctionRefExp:
2782 {
2783 const SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(expr);
2784 name = "member_function_ref_";
2785 name += memberFunctionRefExp->get_symbol()->get_name();
2786 break;
2787 }
2788
2789 case V_SgIntVal:
2790 {
2791 const SgIntVal* valueExp = isSgIntVal(expr);
2792 name = "integer_value_exp_";
2793 name += StringUtility::numberToString(valueExp->get_value());
2794 break;
2795 }
2796
2797 case V_SgStringVal:
2798 {
2799 const SgStringVal* valueExp = isSgStringVal(expr);
2800 name = "string_value_exp_";
2801 name += valueExp->get_value();
2802 break;
2803 }
2804
2805 case V_SgSubscriptExpression:
2806 {
2807 const SgSubscriptExpression* subscriptExpression = isSgSubscriptExpression(expr);
2808 name = "subscript_exp_";
2809 // name += StringUtility::numberToString(subscriptExpression->get_lowerBound());
2810 name += get_name(subscriptExpression->get_lowerBound());
2811 name += "_";
2812 // name += StringUtility::numberToString(subscriptExpression->get_upperBound());
2813 name += get_name(subscriptExpression->get_upperBound());
2814 name += "_";
2815 // name += StringUtility::numberToString(subscriptExpression->get_stride());
2816 name += get_name(subscriptExpression->get_stride());
2817 break;
2818 }
2819
2820 case V_SgNullExpression:
2821 {
2822 name = "null_expression";
2823 break;
2824 }
2825
2826 // DQ (1/17/2011): Added support for SgExprListExp (to support debugging).
2827 case V_SgExprListExp:
2828 {
2829 const SgExprListExp* exprListExp = isSgExprListExp(expr);
2830 name = "expr_list_exp_";
2831 for (size_t i = 0; i < exprListExp->get_expressions().size(); i++)
2832 {
2833 name += get_name(exprListExp->get_expressions()[i]);
2834 }
2835 break;
2836 }
2837
2838 // DQ (1/31/2011): Added to support Fortran debugging.
2839 case V_SgActualArgumentExpression:
2840 {
2841 const SgActualArgumentExpression* actualArgExp = isSgActualArgumentExpression(expr);
2842 name = "actual_arg_exp_name_";
2843 name += actualArgExp->get_argument_name();
2844 name = "_exp_";
2845 name += get_name(actualArgExp->get_expression());
2846 break;
2847 }
2848
2849 // DQ (7/25/2012): Added support for new template IR nodes.
2850 case V_SgTemplateParameterVal:
2851 {
2852 const SgTemplateParameterVal* valueExp = isSgTemplateParameterVal(expr);
2853 name = "template_parameter_value_expression_number_";
2854 // name += valueExp->get_value();
2855 // name += get_name(valueExp);
2856 name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2857 break;
2858 }
2859
2860 // DQ (4/19/2013): Added support for SgDotExp.
2861 case V_SgDotExp:
2862 {
2863 const SgDotExp* dotExp = isSgDotExp(expr);
2864 ROSE_ASSERT(dotExp != NULL);
2865
2866 name = "_dot_exp_lhs_";
2867 name += get_name(dotExp->get_lhs_operand());
2868 name += "_dot_exp_rhs_";
2869 name += get_name(dotExp->get_rhs_operand());
2870 // name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2871 break;
2872 }
2873
2874 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2875 case V_SgLambdaExp:
2876 {
2877 const SgLambdaExp* lambdaExp = isSgLambdaExp(expr);
2878 ROSE_ASSERT (lambdaExp != NULL);
2879 name = "lambda_expression_";
2880 break;
2881 }
2882
2883 // DQ (1/3/2020): Added support for SgThisExp.
2884 case V_SgThisExp:
2885 {
2886 const SgThisExp* thisExp = isSgThisExp(expr);
2887 ROSE_ASSERT(thisExp != NULL);
2888
2889 name = "_this_exp_for_";
2890
2891 SgClassSymbol* classSymbol = thisExp->get_class_symbol();
2892 ROSE_ASSERT(classSymbol != NULL);
2893 // name += get_name(classSymbol->get_name());
2894 // string class_name = classSymbol->get_name();
2895 // name += class_name;
2896 name += classSymbol->get_name();
2897 break;
2898 }
2899
2900 default:
2901 {
2902 // Nothing to do for other IR nodes
2903#if 0
2904 // DQ (7/25/2012): Make this an error.
2905 printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2906 ROSE_ABORT();
2907#endif
2908 // DQ (4/8/2010): define something specific to this function to make debugging more clear.
2909 // printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2910 // name = "undefined_expression_name";
2911 name = expr->class_name() + "_undef_name";
2912 break;
2913 }
2914 }
2915
2916 return name;
2917 }
2918
2919string
2921 {
2922 // This function is useful for debugging
2923 // This is the most general case of a function to return a name for an IR node.
2924 ROSE_ASSERT(node != NULL);
2925
2926 string returnName;
2927
2928 switch(node->variantT())
2929 {
2930 case V_SgRenamePair:
2931 {
2932 const SgRenamePair* n = isSgRenamePair(node);
2933 returnName = "rename_pair_";
2934 returnName += n->get_local_name().str();
2935 returnName += "_from_";
2936 returnName += n->get_use_name().str();
2937 break;
2938 }
2939
2940 case V_SgInitializedName:
2941 {
2942 const SgInitializedName* n = isSgInitializedName(node);
2943 ROSE_ASSERT (n != NULL);
2944 returnName = "initialized_name_";
2945 returnName += n->get_name().str();
2946 break;
2947 }
2948
2949 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2950 case V_SgLambdaCapture:
2951 {
2952 const SgLambdaCapture* n = isSgLambdaCapture(node);
2953 ROSE_ASSERT (n != NULL);
2954 returnName = "lambda_capture_";
2955 // returnName += n->get_name().str();
2956 break;
2957 }
2958
2959#if 0
2960 case V_SgInterfaceBody:
2961 {
2962 const SgInterfaceBody* n = isSgInterfaceBody(node);
2963 returnName = "interface_body";
2964 break;
2965 }
2966#endif
2967 default:
2968 {
2969 returnName = node->class_name();
2970 }
2971 }
2972
2973 return returnName;
2974 }
2975
2976string
2978 {
2979 // This function is useful for debugging
2980 // This is the most general case of a function to return a name for an IR node.
2981 // Later this function will handle expressions, etc.
2982
2983 string name = "undefined_name";
2984
2985 ROSE_ASSERT(node != NULL);
2986
2987 const SgLocatedNode* locatedNode = isSgLocatedNode(node);
2988 if (locatedNode != NULL)
2989 {
2990 const SgStatement* statement = isSgStatement(node);
2991 if (statement != NULL)
2992 {
2993 name = get_name(statement);
2994 }
2995 else
2996 {
2997 const SgExpression* expression = isSgExpression(node);
2998 if (expression != NULL)
2999 {
3000 name = get_name(expression);
3001 }
3002 else
3003 {
3004 const SgLocatedNodeSupport* locatedNodeSupport = isSgLocatedNodeSupport(node);
3005 if (locatedNodeSupport != NULL)
3006 {
3007 name = get_name(locatedNodeSupport);
3008 }
3009 else
3010 {
3011 const SgToken* token = isSgToken(node);
3012 if (token != NULL)
3013 {
3014 name = get_name(token);
3015 }
3016 else
3017 {
3018 printf ("Unknown SgLocatedNode = %p = %s \n",node,node->class_name().c_str());
3019 ROSE_ABORT();
3020 }
3021 }
3022 }
3023 }
3024 }
3025 else
3026 {
3027 const SgSupport* supportNode = isSgSupport(node);
3028 if (supportNode != NULL)
3029 {
3030 name = get_name(supportNode);
3031 }
3032 else
3033 {
3034 // DQ (9/21/2005): I think this is good enough for the more general case (for now)
3035 const SgSymbol* symbol = isSgSymbol(node);
3036 if (symbol != NULL)
3037 {
3038 name = get_name(symbol);
3039 }
3040 else
3041 {
3042 // DQ (8/7/2007): Added support to get names of types (usefult for SgNamedType objects).
3043 const SgType* type = isSgType(node);
3044 if (type != NULL)
3045 {
3046 name = get_name(type);
3047 }
3048 else
3049 {
3050 name = node->class_name();
3051 }
3052 }
3053 }
3054 }
3055
3056 return name;
3057 }
3058
3059
3060string
3062 {
3063 // This function is useful for debugging
3064 string name = "undefined_name";
3065
3066 ROSE_ASSERT(token != NULL);
3067 name = token->get_lexeme_string();
3068
3069 // Handle special cases
3070 if (name == " ")
3071 name = "<space>";
3072 else if (name == "\n")
3073 name = "<eol>";
3074 else if (name == "\t")
3075 name = "<tab>";
3076
3077 return name;
3078 }
3079
3080
3081void
3088
3089
3090string
3092 {
3093 // DQ (3/20/2016): Adding support for generating a unique name from a declaration that
3094 // can be used as an identifier. This functionality is used in the DSL infrastructure
3095 // support (refactored to this location in ROSE). The point of this mechanism is that
3096 // unlike mangled names that are compressed in a way that allows them to only be used
3097 // within a single translation unit, names generated by this function can be used across
3098 // multiple translation units. These names are also easier to interprete in debugging
3099 // (since they explicitly contain the scope, function name, and coding to interprete
3100 // function overloading.
3101
3102 // At present it only supports class declarations, and function declarations (all others
3103 // are trapped as errors).
3104
3105 // Name collision testing, it might be that this should be external to this function.
3106 // static std::map<std::string,int> dsl_attribute_name_collision_map;
3107 // static std::map<std::string,int> local_name_collision_map;
3108
3109 string s;
3110
3111 // string scope = SageInterface::get_name(classDeclaration->get_scope());
3112 string scope = isSgGlobal(declaration->get_scope()) == NULL ? SageInterface::get_name(declaration->get_scope()) : "global";
3113
3114 switch (declaration->variantT())
3115 {
3116 case V_SgClassDeclaration:
3117 case V_SgTemplateClassDeclaration:
3118 // case V_SgTemplateInstantiationDecl:
3119 {
3120 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declaration);
3121 ROSE_ASSERT(classDeclaration != NULL);
3122
3123 string type_name = classDeclaration->get_name();
3124#if 0
3125 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case class or template type: type_name = %s \n",type_name.c_str());
3126#endif
3127 string className = string("scope_") + scope + "_type_name_" + type_name;
3128#if 0
3129 printf ("classDeclaration->get_scope() = %p = %s scope = %s \n",classDeclaration->get_scope(),classDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3130#endif
3131 s = className;
3132 break;
3133 }
3134
3135 // DQ (3/29/2016): Seperate out the case of the SgTemplateInstantiationDecl.
3136 case V_SgTemplateInstantiationDecl:
3137 {
3138 SgTemplateInstantiationDecl* templateInstantiationDeclaration = isSgTemplateInstantiationDecl(declaration);
3139 ROSE_ASSERT(templateInstantiationDeclaration != NULL);
3140
3141 // Note that we can't use the mangled name because they might not be unique across multiple translation units if seperately compiled).
3142 // string type_name = templateInstantiationDeclaration->get_name();
3143 // string type_name = templateInstantiationDeclaration->get_mangled_name();
3144 // string type_name = templateInstantiationDeclaration->get_templateName();
3145 string type_name = templateInstantiationDeclaration->get_name();
3146#if 0
3147 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgTemplateInstantiationDecl: type_name = %s \n",type_name.c_str());
3148#endif
3149 string className = string("scope_") + scope + "_type_name_" + type_name;
3150
3151 // Note that trimSpaces is defined in the name mangling support.
3152 // string compressedClassName = trimSpaces(className);
3153 // string compressedClassName = SageInterface::get_name(templateInstantiationDeclaration);
3154 // ROSE_UTIL_API std::string copyEdit(const std::string& inputString, const std::string & oldToken, const std::string & newToken);
3155
3156 // We need to turn this template instatiation name into a name that can be used as a C++ identifier.
3157 string compressedClassName = StringUtility::copyEdit(className," ","");
3158 compressedClassName = StringUtility::copyEdit(compressedClassName,"<","_abs_");
3159 compressedClassName = StringUtility::copyEdit(compressedClassName,">","_abe_");
3160 compressedClassName = StringUtility::copyEdit(compressedClassName,",","_comma_");
3161 compressedClassName = StringUtility::copyEdit(compressedClassName,"*","_star_");
3162 compressedClassName = StringUtility::copyEdit(compressedClassName,"&","_ref_");
3163#if 0
3164 printf ("className = %s compressedClassName = %s \n",className.c_str(),compressedClassName.c_str());
3165#endif
3166#if 0
3167 printf ("templateInstantiationDeclaration->get_scope() = %p = %s scope = %s \n",
3168 templateInstantiationDeclaration->get_scope(),templateInstantiationDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3169#endif
3170 // s = className;
3171 s = compressedClassName;
3172#if 0
3173 printf ("Exiting as a test! \n");
3174 ROSE_ABORT();
3175#endif
3176 break;
3177 }
3178
3179 case V_SgFunctionDeclaration:
3180 case V_SgTemplateFunctionDeclaration:
3181 case V_SgTemplateInstantiationFunctionDecl:
3182 {
3183 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration);
3184 ROSE_ASSERT(functionDeclaration != NULL);
3185#if 0
3186 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgFunctionDeclaration: not implemented \n");
3187#endif
3188 // We might at some point want the qualified name.
3189 string original_name = functionDeclaration->get_name();
3190
3191 string function_name_part = mangleFunctionName(original_name,"return_type");
3192 string function_name = string("scope_") + scope + "_function_name_" + function_name_part;
3193
3194 // DQ (3/16/2016): Detect name collisions so that we can
3195 // std::map<std::string,int> dsl_attribute_name_collision_map;
3196 if (local_name_collision_map.find(function_name) == local_name_collision_map.end())
3197 {
3198 local_name_collision_map.insert(pair<string,int>(function_name,0));
3199 }
3200 else
3201 {
3202 local_name_collision_map[function_name]++;
3203
3204 int count = local_name_collision_map[function_name];
3205#if 0
3206 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3207#endif
3208 function_name += StringUtility::numberToString(count);
3209 }
3210
3211 s = function_name;
3212#if 0
3213 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgFunctionDeclaration: Exiting as a test! \n");
3214 ROSE_ABORT();
3215#endif
3216 break;
3217 }
3218
3219 case V_SgMemberFunctionDeclaration:
3220 case V_SgTemplateMemberFunctionDeclaration:
3221 case V_SgTemplateInstantiationMemberFunctionDecl:
3222 {
3223 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(declaration);
3224 ROSE_ASSERT(memberFunctionDeclaration != NULL);
3225#if 0
3226 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgMemberFunctionDeclaration: not implemented \n");
3227#endif
3228 // We might at some point want the qualified name.
3229 string original_name = memberFunctionDeclaration->get_name();
3230
3231 // string member_function_name = memberFunctionDeclaration->get_mangled_name();
3232 // string member_function_name = memberFunctionDeclaration->get_qualified_name();
3233 // string member_function_name = SageInterface::get_name(memberFunctionDeclaration);
3234 // string member_function_scope = SageInterface::get_name(memberFunctionDeclaration->get_scope());
3235 string member_function_name_part = mangleFunctionName(original_name,"return_type");
3236 // string member_function_name = string("scope_") + member_function_scope + "_function_name_" + member_function_name_part;
3237 string member_function_name = string("scope_") + scope + "_member_function_name_" + member_function_name_part;
3238
3239 // DQ (3/16/2016): Detect name collisions so that we can
3240 // std::map<std::string,int> dsl_attribute_name_collision_map;
3241 if (local_name_collision_map.find(member_function_name) == local_name_collision_map.end())
3242 {
3243 local_name_collision_map.insert(pair<string,int>(member_function_name,0));
3244 }
3245 else
3246 {
3247 local_name_collision_map[member_function_name]++;
3248
3249 int count = local_name_collision_map[member_function_name];
3250#if 0
3251 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3252#endif
3253 member_function_name += StringUtility::numberToString(count);
3254 }
3255
3256 s = member_function_name;
3257#if 0
3258 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgMemberFunctionDeclaration: Exiting as a test! \n");
3259 ROSE_ABORT();
3260#endif
3261 break;
3262 }
3263
3264 default:
3265 {
3266 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Unsupported declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3267// ROSE_ASSERT(false);
3268 }
3269 }
3270
3271#if 0
3272 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3273#endif
3274#if 0
3275 if (s != "")
3276 {
3277 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3278 }
3279#endif
3280
3281#if 0
3282 printf ("Exiting as a test! \n");
3283 ROSE_ABORT();
3284#endif
3285
3286 return s;
3287 }
3288
3289// Generate unique name for use as a class name for the generated attribute classes.
3290// std::string AttributeGeneratorTraversal::generateUniqueNameForUseAsIdentifier ( SgDeclarationStatement* declaration )
3291// std::string AttributeGeneratorTraversal::generateUniqueName ( SgDeclarationStatement* declaration )
3292std::string
3294 {
3295 // DQ (3/21/2016): The support for unique name generation for use across translation
3296 // units is not refactored into the SageInterface.
3297 // string s = SageInterface::generateUniqueNameForUseAsIdentifier(declaration);
3298 string s;
3299
3300#if 0
3301 printf ("In generateUniqueNameForUseAsIdentifier(): evaluating declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3302#endif
3303
3304 ROSE_ASSERT(local_node_to_name_map.empty() == false);
3305 ROSE_ASSERT(local_name_to_node_map.empty() == false);
3306
3308 {
3310 }
3311 else
3312 {
3313 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3314 if (definingDeclaration != NULL)
3315 {
3316#if 0
3317 printf ("In generateUniqueName(): Using the defining declaration = %p since %p was not in the map \n",definingDeclaration,declaration);
3318#endif
3319 // s = generateUniqueName(definingDeclaration);
3320 s = generateUniqueNameForUseAsIdentifier_support(definingDeclaration);
3321 }
3322 else
3323 {
3324 // Note that builtin functions will not have a defining declaration.
3325 printf ("Warning: defining declaration not in SageInterface::local_node_to_name_map: declaration = %p = %s using name = %s \n",
3326 declaration,declaration->class_name().c_str(),SageInterface::get_name(declaration).c_str());
3327 // ROSE_ASSERT(false);
3328
3329 // If there is no defining declaration then go ahead and use the non-defining one.
3330 // s = SageInterface::get_name(declaration);
3331 SgDeclarationStatement* nondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3332 ROSE_ASSERT(nondefiningDeclaration != NULL);
3333 s = generateUniqueNameForUseAsIdentifier_support(nondefiningDeclaration);
3334 }
3335 }
3336
3337#if 0
3338 printf ("Exiting as a test! \n");
3339 ROSE_ABORT();
3340#endif
3341
3342 return s;
3343 }
3344
3345
3346void
3348 {
3349 ROSE_ASSERT(astNode != NULL);
3350
3351 ROSE_ASSERT(local_name_collision_map.empty() == true);
3352 ROSE_ASSERT(local_name_to_node_map.empty() == true);
3353 ROSE_ASSERT(local_node_to_name_map.empty() == true);
3354
3355 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
3356 class UniqueNameTraversal : public AstSimpleProcessing
3357 {
3358 public:
3359 void visit (SgNode* node)
3360 {
3361 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
3362 if (decl != NULL)
3363 {
3364 SgClassDeclaration* classDeclaration = isSgClassDeclaration(decl);
3365 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(decl);
3366 if (classDeclaration != NULL || functionDeclaration != NULL)
3367 {
3369 local_name_to_node_map.insert(pair<string,SgNode*>(s,decl));
3370 local_node_to_name_map.insert(pair<SgNode*,string>(decl,s));
3371 }
3372 }
3373 }
3374 };
3375
3376 // Now buid the traveral object and call the traversal (preorder) on the function definition.
3377 UniqueNameTraversal traversal;
3378 traversal.traverse(astNode, preorder);
3379 }
3380
3381
3382
3385 {
3386 SgMemberFunctionDeclaration* defaultConstructor = NULL;
3387
3388 ROSE_ASSERT(classDeclaration != NULL);
3389 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3390 ROSE_ASSERT(definingDeclaration != NULL);
3391 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3392
3393 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3394 // would be associated with a class declaration but no definition would exist).
3395 if (definingClassDeclaration != NULL)
3396 {
3397 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3398 ROSE_ASSERT(classDefinition != NULL);
3399
3400 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3401 while ( i != classDefinition->get_members().end() )
3402 {
3403 // Check the parent pointer to make sure it is properly set
3404 ROSE_ASSERT( (*i)->get_parent() != NULL);
3405 ROSE_ASSERT( (*i)->get_parent() == classDefinition);
3406
3407 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3408 if (memberFunction != NULL)
3409 {
3410 // printf ("memberFunction = %p = %s \n",memberFunction,memberFunction->get_name().str());
3411 if ( memberFunction->get_specialFunctionModifier().isConstructor() == true )
3412 defaultConstructor = memberFunction;
3413 }
3414
3415 // iterate through the class members
3416 i++;
3417 }
3418 }
3419
3420 // This should be true for the specific case that we are currently debugging!
3421 // ROSE_ASSERT(defaultConstructor != NULL);
3422
3423 return defaultConstructor;
3424 }
3425
3428 {
3429 SgMemberFunctionDeclaration* defaultDestructor = NULL;
3430
3431 ROSE_ASSERT(classDeclaration != NULL);
3432 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3433 if (definingDeclaration != NULL)
3434 {
3435 ROSE_ASSERT(definingDeclaration != NULL);
3436 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3437
3438 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3439 // would be associated with a class declaration but no definition would exist).
3440 if (definingClassDeclaration != NULL)
3441 {
3442 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3443 ROSE_ASSERT(classDefinition != NULL);
3444
3445 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3446 while ( i != classDefinition->get_members().end() )
3447 {
3448 // Check the parent pointer to make sure it is properly set
3449 SgNode* i_parent = (*i)->get_parent();
3450 ROSE_ASSERT(i_parent != NULL);
3451
3452 // DQ (11/1/2005): Note that a template instantiation can have a parent which is the
3453 // variable which forced it's instantiation. Since it does not really exist in the
3454 // source code explicitly (it is compiler generated) this is as reasonable as anything else.
3455 if ( i_parent != classDefinition )
3456 {
3457 printf ("Error: (*i)->get_parent() = %p = %s \n",i_parent,i_parent->class_name().c_str());
3458 printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),(*i)->unparseToString().c_str());
3459 (*i)->get_file_info()->display("Called from SageInterface::getDefaultDestructor: debug");
3460 }
3461 ROSE_ASSERT( i_parent == classDefinition);
3462
3463 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3464 if (memberFunction != NULL)
3465 {
3466 if ( memberFunction->get_specialFunctionModifier().isDestructor() == true )
3467 defaultDestructor = memberFunction;
3468 }
3469
3470 // iterate through the class members
3471 i++;
3472 }
3473 }
3474 }
3475
3476 return defaultDestructor;
3477 }
3478
3479
3480
3481bool
3482SageInterface::addDefaultConstructorIfRequired ( SgClassType* classType, int physical_file_id /* = Sg_File_Info::TRANSFORMATION_FILE_ID */ )
3483 {
3484 // DQ (11/9/2020): Added function to support adding a default constructor definition to a class
3485 // if it does not have a default constructor, but has any other constructor that would prevent
3486 // a compiler generated default constructor from being generated by the compiler.
3487
3488#define DEBUG_ADD_DEFAULT_CONSTRUCTOR 0
3489
3490 // Note the physical_file_id is so that it can be marked to be unparsed when header file unparsing is active.
3491
3492 ASSERT_not_null(classType);
3493
3494 bool returnValue = false;
3495
3496 // To setup this transformation we need to see if there is a default constructor in the associated class.
3497 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
3498 ROSE_ASSERT(classDeclaration != NULL);
3499 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(classDeclaration->get_definingDeclaration());
3500 ROSE_ASSERT(definingClassDeclaration != NULL);
3501 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3502 ROSE_ASSERT(classDefinition != NULL);
3503
3504 SgDeclarationStatementPtrList & declarationList = classDefinition->get_members();
3505
3506 bool foundConstructor = false;
3507 bool foundDefaultConstructor = false;
3508
3509#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3510 printf ("In addDefaultConstructorIfRequired(): class name = %s \n",classDeclaration->get_name().str());
3511#endif
3512
3513 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
3514 while (i != declarationList.end())
3515 {
3516 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(*i);
3517 if (memberFunctionDeclaration != NULL)
3518 {
3519 bool isConstructor = memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
3520 if (isConstructor == true)
3521 {
3522 foundConstructor = true;
3523
3524#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3525 printf ("Found a constructor! \n");
3526#endif
3527 SgFunctionParameterList* functionParameterList = memberFunctionDeclaration->get_parameterList();
3528 ROSE_ASSERT(functionParameterList != NULL);
3529
3530 // DQ (7/19/2021): Fixed to allow for previously found default constructor to be registered as found.
3531 // foundDefaultConstructor = (functionParameterList->get_args().size() == 0);
3532 foundDefaultConstructor = ((foundDefaultConstructor == true) || (functionParameterList->get_args().size() == 0));
3533
3534#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3535 if (foundDefaultConstructor == true)
3536 {
3537 printf ("Found a default constructor! \n");
3538 }
3539 else
3540 {
3541 printf ("This is not a default constructor: functionParameterList->get_args().size() = %zu \n",functionParameterList->get_args().size());
3542 }
3543#endif
3544 }
3545 else
3546 {
3547#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3548 printf ("This is not a constructor \n");
3549#endif
3550 }
3551 }
3552
3553 i++;
3554 }
3555
3556#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3557 printf ("foundConstructor = %s \n",foundConstructor ? "true" : "false");
3558 printf ("foundDefaultConstructor = %s \n",foundDefaultConstructor ? "true" : "false");
3559#endif
3560
3561 if (foundConstructor == true)
3562 {
3563 // Since there is at least one constructor, we can't rely on compiler generated constructors.
3564#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3565 printf ("Since there is at least one constructor, we can't rely on compiler generated constructors \n");
3566#endif
3567 if (foundDefaultConstructor == true)
3568 {
3569 // We can use the existing default constructor.
3570#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3571 printf ("We can use the existing default constructor (no need to build one) \n");
3572#endif
3573 }
3574 else
3575 {
3576 // We don't have a default constructor, so we need to build one explicitly, and insert it into the class definition.
3577
3578#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3579 printf ("########################################################### \n");
3580 printf ("Need to build a default constructor in the associated class \n");
3581#endif
3582 SgMemberFunctionDeclaration* constructorDeclaration = SageBuilder::buildDefaultConstructor(classType);
3583 ROSE_ASSERT(constructorDeclaration != NULL);
3584
3585#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3586 printf (" --- constructorDeclaration = %p = %s name = %s \n",constructorDeclaration,constructorDeclaration->class_name().c_str(),constructorDeclaration->get_name().str());
3587#endif
3588 ROSE_ASSERT (constructorDeclaration->get_declarationModifier().get_accessModifier().isPublic() == true);
3589
3590 classDefinition->prepend_statement(constructorDeclaration);
3591
3592 // constructorDeclaration->set_parent(classDefinition);
3593 ROSE_ASSERT(constructorDeclaration->get_parent() != NULL);
3594
3595 // int physical_file_id = variableDeclaration->get_startOfConstruct()->get_physical_file_id();
3596 markSubtreeToBeUnparsed(constructorDeclaration,physical_file_id);
3597
3598 returnValue = true;
3599#if 0
3600 constructorDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3601 constructorDeclaration->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3602
3603 // We also need to set the source position of the function definition, else the
3604 // function declaration will not be output.
3605 ROSE_ASSERT(constructorDeclaration->get_definition() != NULL);
3606 ROSE_ASSERT(constructorDeclaration->get_definition()->get_startOfConstruct() != NULL);
3607 ROSE_ASSERT(constructorDeclaration->get_definition()->get_endOfConstruct() != NULL);
3608 constructorDeclaration->get_definition()->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3609 constructorDeclaration->get_definition()->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3610#endif
3611
3612#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3613 printf ("DONE: Need to build a default constructor in the associated class \n");
3614 printf ("################################################################# \n");
3615#endif
3616#if 0
3617 printf ("Exiting as a test! \n");
3618 ROSE_ABORT();
3619#endif
3620 }
3621 }
3622 else
3623 {
3624 // No constructors found, so we don't need to add an explicit default constructor.
3625
3626#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3627 printf ("No constructors found, so we don't need to add an explicit default constructor \n");
3628#endif
3629 }
3630
3631#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3632 printf ("Leaving addDefaultConstructorIfRequired(): returnValue = %s \n",returnValue ? "true" : "false");
3633#endif
3634
3635 return returnValue;
3636 }
3637
3638
3639
3640
3641void
3643 {
3644 // DQ (6/27/2005): This function outputs the global table of function type symbols
3645 // it is built during the EDG/Sage translation phase, and it built initially with
3646 // the EDG names of all instantiated templates. At a later phase (incomplete at
3647 // the moment) the AST fixup rebuilds the table to use the modified template names
3648 // (that is mangled names built from the modified template names used in Sage III).
3649
3650 // DQ (1/31/2006): Modified to build all types in the memory pools
3651 // extern SgFunctionTypeTable Sgfunc_type_table;
3652 // Sgfunc_type_table.print_functypetable();
3653 ROSE_ASSERT(SgNode::get_globalFunctionTypeTable() != NULL);
3654 SgNode::get_globalFunctionTypeTable()->print_functypetable();
3655 }
3656
3657void
3659 {
3660 // This simplifies how the traversal is called!
3661 OutputLocalSymbolTables astTraversal;
3662
3663 // I think the default should be preorder so that the interfaces would be more uniform
3664 astTraversal.traverse(node,preorder);
3665 }
3666
3667void
3669 {
3670 // DQ (6/27/2005): Output the local symbol table from each scope.
3671 // printf ("node = %s \n",node->sage_class_name());
3672
3673#if 0
3674 printf ("Exiting as a test! \n");
3675 ROSE_ABORT();
3676#endif
3677
3678 SgScopeStatement* scope = isSgScopeStatement(node);
3679 if (scope != NULL)
3680 {
3681 // SgSymbolTable* symbolTable = scope->get_symbol_table();
3682 // ROSE_ASSERT(symbolTable != NULL);
3683
3684 printf ("Symbol Table from %p = %s at: \n",scope,scope->sage_class_name());
3685 scope->get_file_info()->display("Symbol Table Location (Called from SageInterface::OutputLocalSymbolTables::visit())");
3686 // symbolTable->print("Called from SageInterface::OutputLocalSymbolTables::visit()");
3687 scope->print_symboltable("Called from SageInterface::OutputLocalSymbolTables::visit()");
3688 }
3689 }
3690
3691#if 0
3692// DQ (8/28/2005): This is already a member function of the SgFunctionDeclaration
3693// (so that it can handle template functions and member functions)
3694
3695// DQ (8/27/2005):
3696bool
3697SageInterface::isTemplateMemberFunction( SgTemplateInstantiationMemberFunctionDecl* memberFunctionDeclaration )
3698 {
3699 // This function determines if the member function is associated with a template
3700 // or just a template class (where it is a normal non-template member function).
3701
3702 bool result = false;
3703
3704 result = memberFunctionDeclaration->isTemplateFunction();
3705
3706 return result;
3707 }
3708#endif
3709
3710// DQ (8/27/2005):
3711bool
3713 {
3714 // This function determines if the template declaration associated withthis member function instantiation is
3715 // defined in the class or outside of the class.
3716
3717 bool result = false;
3718
3719#if 0
3720 // Check if this is a template or non-template member function
3721 if (isTemplateMemberFunction(memberFunctionDeclaration) == true)
3722 {
3723 SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3724 printf ("templateDeclaration = %p parent of templateDeclaration = %p \n",templateDeclaration,templateDeclaration->get_parent());
3725
3726 // SgTemplateInstantiationDecl* classTemplateInstantiation = memberFunctionDeclaration->get_class_scope()->get_declaration();
3727 SgClassDeclaration* classDeclaration = memberFunctionDeclaration->get_class_scope()->get_declaration();
3728 ROSE_ASSERT(classDeclaration != NULL);
3729 SgTemplateInstantiationDecl* classTemplateInstantiation = isSgTemplateInstantiationDecl(classDeclaration);
3730
3731 if (classTemplateInstantiation != NULL)
3732 {
3733 SgTemplateDeclaration* classTemplateDeclaration = classTemplateInstantiation->get_templateDeclaration();
3734 if (classTemplateDeclaration != NULL && classTemplateDeclaration != templateDeclaration)
3735 {
3736 result = true;
3737 }
3738 }
3739 }
3740#endif
3741
3742 // Alternative approach
3743 // SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3744 SgDeclarationStatement* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3745// printf ("In templateDefinitionIsInClass(): templateDeclaration = %p parent of templateDeclaration = %p = %s \n",templateDeclaration,
3746// templateDeclaration->get_parent(),templateDeclaration->get_parent()->class_name().c_str());
3747
3748 if (templateDeclaration != NULL && templateDeclaration->get_parent() != NULL)
3749 {
3750 SgScopeStatement* parentScope = isSgScopeStatement(templateDeclaration->get_parent());
3751 if (isSgClassDefinition(parentScope) != NULL)
3752 {
3753 result = true;
3754 }
3755 }
3756
3757 return result;
3758 }
3759#if 0
3761generateUniqueDeclaration ( SgDeclarationStatement* declaration )
3762 {
3763 // DQ (10/11/2007): This is no longer used.
3764 printf ("Error: This is no longer used. \n");
3765 ROSE_ABORT();
3766
3767 // Get the defining or first non-defining declaration so that we can use it as a key to know
3768 // when we have found the same function. So we don't count a redundant forward declaration
3769 // found outside of the class as matching the first non-defining declaration or the defining
3770 // declaration in the class by mistake. All declarations share the same firstNondefining
3771 // declaration and defining declaration so either could be a key declaration, but there are
3772 // times when either one of then (but not both) can be NULL (function defined withouth forward
3773 // declaration or not defined at all).
3774 SgDeclarationStatement* firstNondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3775 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3776 SgDeclarationStatement* keyDeclaration = NULL;
3777 if (firstNondefiningDeclaration != NULL)
3778 keyDeclaration = firstNondefiningDeclaration;
3779 else
3780 keyDeclaration = definingDeclaration;
3781 ROSE_ASSERT(keyDeclaration != NULL);
3782
3783 return keyDeclaration;
3784 }
3785#endif
3788{
3789 string pragmaString = pragmaDeclaration->get_pragma()->get_pragma();
3790 istringstream istr(pragmaString);
3791 std::string key;
3792 istr >> key;
3793 return key;
3794}
3795
3797// TODO: move all Omp*statement under a parent SgOmpStatement
3799{
3800 ROSE_ASSERT (n != NULL);
3801 bool result = false;
3802 if (isSgOmpBarrierStatement(n)||
3803 isSgOmpBodyStatement(n)||
3804 isSgOmpDeclareSimdStatement(n) ||
3805 isSgOmpFlushStatement(n)||
3806 isSgOmpThreadprivateStatement(n)||
3807 isSgOmpTaskwaitStatement(n) )
3808 result = true;
3809
3810 return result;
3811
3812}
3813// DQ (8/28/2005):
3814bool
3816 {
3817 // This function looks for any other function that might overload the input function.
3818 // for member functions we only look in the scope where the member function is defined.
3819 // for non-member functions we look only in the scope where the function is declared.
3820
3821 // Note that there are scenarios where this approach of searching only these locations
3822 // might not catch an overloaded function.
3823 // * member functions:
3824 // - overloaded functions might be declared in base classes
3825 // * non-member functions:
3826 // - function declarations might be friend functions in classes
3827 // - functions might be declared in differen namespace definitions
3828 // (SgNamespaceDefinitionStatement), since a namespace in re-entrant
3829 // and can have many namespace declarations and definitions.
3830
3831 // bool result = false;
3832 int counter = 0;
3833
3834 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
3835 if (memberFunctionDeclaration != NULL)
3836 {
3837 // This is a member function declaration
3838
3839 // DQ (10/11/2007): Fix this to NOT use the generateUniqueDeclaration() function.
3840 // Generate a key to use for comparision (avoids false positives)
3841 // SgMemberFunctionDeclaration* keyDeclaration = isSgMemberFunctionDeclaration(generateUniqueDeclaration(functionDeclaration));
3842 // ROSE_ASSERT(keyDeclaration != NULL);
3843
3844 SgScopeStatement * scope = memberFunctionDeclaration->get_scope();
3845 ROSE_ASSERT(scope != NULL);
3846
3847 // TV (09/17/2018): ROSE-1378
3848 if (isSgDeclarationScope(scope)) {
3849 printf("TODO SageInterface::isOverloaded case when scope is SgDeclarationScope. See ROSE-1378.\n");
3850 return false;
3851 }
3852
3853 // Get the class definition
3854 SgClassDefinition* classDefinition =
3855 isSgClassDefinition(memberFunctionDeclaration->get_scope());
3856 ROSE_ASSERT(classDefinition != NULL);
3857
3858 // Get the class declaration associated with the class definition
3859 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classDefinition->get_declaration());
3860 ROSE_ASSERT(classDeclaration != NULL);
3861
3862 // Get the list of member declarations in the class
3863 SgDeclarationStatementPtrList & memberList = classDefinition->get_members();
3864#if 0
3865 // DQ (10/11/2007): Fix this function better by checking for more than one member function declaration in the class definition.
3866 printf (" memberList.size() = %" PRIuPTR " \n",memberList.size());
3867#endif
3868 for (SgDeclarationStatementPtrList::iterator i = memberList.begin(); i != memberList.end(); i++)
3869 {
3870#if 0
3871 printf (" counter = %d declaration = %p = %s \n",counter,*i,(*i)->class_name().c_str());
3872#endif
3873 SgMemberFunctionDeclaration* tempMemberFunction = isSgMemberFunctionDeclaration(*i);
3874 SgTemplateDeclaration* tempTemplateDeclaration = isSgTemplateDeclaration(*i);
3875
3876 // Member functions could be overloaded
3877 if (tempMemberFunction != NULL)
3878 {
3879#if 0
3880 // DQ (10/11/2007): This is a problem for where s member function prototype from outside the class is checked to be an ovverloaded function.
3881 // Check using the key declaration
3882 if ( keyDeclaration == generateUniqueDeclaration(tempMemberFunction) )
3883 {
3884#if 0
3885 printf ("Skipping the case of keyDeclaration == generateUniqueDeclaration(tempMemberFunction) = %p \n",keyDeclaration);
3886#endif
3887 continue;
3888 }
3889#endif
3890 ROSE_ASSERT(tempMemberFunction->get_name() != "");
3891#if 0
3892 printf (" tempMemberFunction = (name) %s = (qualified) %s \n",
3893 tempMemberFunction->get_name().str(),
3894 tempMemberFunction->get_qualified_name().str());
3895#endif
3896 if (tempMemberFunction->get_name() == memberFunctionDeclaration->get_name())
3897 {
3898#if 0
3899 printf (" Found a matching overloaded member function! \n");
3900#endif
3901 // result = true;
3902 counter++;
3903 }
3904 }
3905 else
3906 {
3907 // Or templates could be overloaded, but nothing else.
3908 if (tempTemplateDeclaration != NULL)
3909 {
3910 // If this is a template declaration, it could be a template
3911 // declaration for an overloaded member function of the same name.
3912#if 0
3913 // printf ("keyDeclaration->get_name() = %s \n",keyDeclaration->get_name().str());
3914 printf ("tempTemplateDeclaration->get_name() = %s \n",tempTemplateDeclaration->get_name().str());
3915#endif
3916 if (memberFunctionDeclaration->get_name() == tempTemplateDeclaration->get_name())
3917 {
3918#if 0
3919 printf (" Found a matching overloaded member function! \n");
3920#endif
3921 // result = true;
3922 counter++;
3923 }
3924 }
3925 else
3926 {
3927 // DQ (10/12/2007): Could friend functions defined in a class be overloaded? Need to check this!
3928 if (functionDeclaration->variantT() == V_SgFunctionDeclaration)
3929 {
3930 printf ("In SageInterface::isOverloaded(): could friend functions be overloaded in a class? \n");
3931 }
3932 }
3933 }
3934
3935 // If we have detected two, so we have an overloaded function.
3936 if (counter > 1)
3937 break;
3938 }
3939 }
3940 else
3941 {
3942 // This is a non-member function declaration
3943 printf ("In SageInterface::isOverloaded(): case of non-member function not yet implemented! \n");
3944 ROSE_ABORT();
3945 }
3946
3947 // DQ (10/11/2007): Fixup to use the counter and consider more than 1 function with the same name an overloaded member function.
3948 // This might be a problem for friend functions, so test this separately.
3949 // return result;
3950 return (counter > 1);
3951 }
3952
3953
3954
3955
3958 {
3959 // DQ (9/6/2005): This function builds a copy of the input function for the
3960 // construction of a forward declaration of the function. Required in the
3961 // instantiated functions definition is to be output as a specialization by ROSE.
3962 // Since the shallow copy mechanism will cause IR nodes to be shared, we have
3963 // to fix it up with deep copies of the parameter list and the CtorInitializerList.
3964
3965 ROSE_ASSERT(memberFunctionInstantiation != NULL);
3966
3967#if 0
3968 printf ("buildForwardFunctionDeclaration: Member function = %p = %s = definition = %p \n",
3969 memberFunctionInstantiation,
3970 memberFunctionInstantiation->get_name().str(),
3971 memberFunctionInstantiation->get_definition());
3972 memberFunctionInstantiation->get_file_info()->display("memberFunctionInstantiation: debug");
3973#endif
3974
3975 // This is a better implementation using a derived class from SgCopyHelp to control the
3976 // copying process (skipping the copy of any function definition). This is a variable
3977 // declaration with an explicitly declared class type.
3978 class NondefiningFunctionDeclarationCopyType : public SgCopyHelp
3979 {
3980 // DQ (9/26/2005): This class demonstrates the use of the copy mechanism
3981 // within Sage III (originally designed and implemented by Qing Yi).
3982 // One problem with it is that there is no context information permitted.
3983
3984 public:
3985 virtual SgNode *copyAst(const SgNode *n)
3986 {
3987 // If still NULL after switch then make the copy
3988 SgNode* returnValue = NULL;
3989
3990 switch(n->variantT())
3991 {
3992 // DQ (10/21/2007): Now that s bug is fixed in the SgDeclarationStatement::fixupCopy()
3993 // member function, I think we might not need this case.
3994
3995 // Don't copy the associated non-defining declaration when building a function prototype!
3996 case V_SgFunctionDeclaration:
3997 case V_SgMemberFunctionDeclaration:
3998 case V_SgTemplateInstantiationFunctionDecl:
3999 case V_SgTemplateInstantiationMemberFunctionDecl:
4000 {
4001 // printf ("Skip copying an associated non-defining declaration if it is present \n");
4002 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(n);
4003 ROSE_ASSERT(functionDeclaration != NULL);
4004 if (functionDeclaration == functionDeclaration->get_definingDeclaration())
4005 {
4006 // This is the defining declaration (make a shallow copy)
4007 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the DEFINING declaration! \n");
4008 // return const_cast<SgNode *>(n);
4009 returnValue = const_cast<SgNode *>(n);
4010 }
4011 else
4012 {
4013 // This is the non-defining declaration where we want to make a deep copy.
4014 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the NONDEFINING declaration! \n");
4015 }
4016
4017 break;
4018 }
4019
4020 // Don't copy the function definitions (roughly the body of the function)
4021 case V_SgFunctionDefinition:
4022 {
4023 printf ("Skip copying the function definition if it is present \n");
4024 // return const_cast<SgNode *>(n);
4025 returnValue = const_cast<SgNode *>(n);
4026 break;
4027 }
4028
4029 default:
4030 {
4031 // Nothing to do here
4032 break;
4033 }
4034 }
4035
4036 // return n->copy(*this);
4037
4038 // If not set at this point then make the copy!
4039 if (returnValue == NULL)
4040 returnValue = n->copy(*this);
4041
4042 ROSE_ASSERT(returnValue != NULL);
4043 return returnValue;
4044 }
4045 } nondefiningFunctionDeclarationCopy;
4046
4047 // DQ (10/20/2007): The more accurate copy mechanism now builds us a defining declaration to go with the non-defining declaration!
4048 // This is because we have to remove the pointers from non-defining declaration to the definition (which should be pointed to ONLY by the defining declaration!
4049 // delete copyOfMemberFunction->get_definingDeclaration();
4050 if (memberFunctionInstantiation->get_definition() != NULL)
4051 {
4052 printf ("\n\nNEED TO REMOVE POINTERS IN THE NON-DEFINING DECLARATION TO THE SgClassDefinition objects. \n");
4053 ROSE_ABORT();
4054
4055 // If we see the assertion above fail then we might want to use this code:
4056 ROSE_ASSERT( memberFunctionInstantiation != memberFunctionInstantiation->get_definingDeclaration() );
4057 memberFunctionInstantiation->set_definition(NULL);
4058 }
4059 SgNode* copyOfMemberFunctionNode = memberFunctionInstantiation->copy(nondefiningFunctionDeclarationCopy);
4060 SgTemplateInstantiationMemberFunctionDecl* copyOfMemberFunction = static_cast<SgTemplateInstantiationMemberFunctionDecl*>(copyOfMemberFunctionNode);
4061
4062 // printf ("\n\nHOW DO WE KNOW WHEN TO NOT COPY THE DEFINING DECLARATION SO THAT WE CAN JUST BUILD A FUNCTION PROTOTYPE! \n");
4063 // ROSE_ASSERT(false);
4064
4065#if 0
4066 printf ("copyOfMemberFunction->get_firstNondefiningDeclaration() = %p \n",copyOfMemberFunction->get_firstNondefiningDeclaration());
4067#endif
4068 // DQ (10/11/2007): The copy function sets the firstNondefiningDeclaration to itself if in the original declaration it had the
4069 // firstNondefiningDeclaration set to itself, this is incorrect in the case where we only make a copy of function declaration,
4070 // and causes the symbol table tests for get_declaration_associated_with_symbol() to fail because it uses the
4071 // firstNondefiningDeclaration which is not the one associated with the symbol in the parent scope. So reset the
4072 // firstNondefiningDeclaration in the copy of the member function.
4073 copyOfMemberFunction->set_firstNondefiningDeclaration(memberFunctionInstantiation->get_firstNondefiningDeclaration());
4074
4075#if 0
4076 printf ("memberFunctionInstantiation->get_firstNondefiningDeclaration() = %p \n",memberFunctionInstantiation->get_firstNondefiningDeclaration());
4077
4078 printf ("copyOfMemberFunction->isForward() = %s \n",copyOfMemberFunction->isForward() ? "true" : "false");
4079 printf ("memberFunctionInstantiation->isForward() = %s \n",memberFunctionInstantiation->isForward() ? "true" : "false");
4080#endif
4081#if 0
4082 printf ("memberFunctionInstantiation->isSpecialization() = %s \n",memberFunctionInstantiation->isSpecialization() ? "true" : "false");
4083 printf ("copyOfMemberFunctionNode = %p = %s = %s memberFunctionInstantiation->isSpecialization() = %s \n",
4084 copyOfMemberFunction,copyOfMemberFunction->class_name().c_str(),SageInterface::get_name(copyOfMemberFunction).c_str(),copyOfMemberFunction->isSpecialization() ? "true" : "false");
4085 copyOfMemberFunction->get_file_info()->display("copyOfMemberFunction: debug");
4086#endif
4087
4088 // Make sure that we have the same number of arguments on the copy that we build
4089 ROSE_ASSERT(memberFunctionInstantiation->get_args().size() == copyOfMemberFunction->get_args().size());
4090
4091 // DQ (11/5/2007): Additional tests
4092 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isOutputInCodeGeneration() == copyOfMemberFunction->get_startOfConstruct()->isOutputInCodeGeneration());
4093 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isCompilerGenerated() == copyOfMemberFunction->get_startOfConstruct()->isCompilerGenerated());
4094
4095 ROSE_ASSERT(copyOfMemberFunction != NULL);
4096 return copyOfMemberFunction;
4097 }
4098
4099
4100void
4101supportForBaseTypeDefiningDeclaration ( SgSymbolTable* symbolTable, SgDeclarationStatement* declarationForType )
4102 {
4103 // DQ (10/14/2007): Supporting function for
4104
4105 ROSE_ASSERT(declarationForType != NULL);
4106
4107 // DQ (11/7/2007): Added more cases...
4108 switch(declarationForType->variantT())
4109 {
4110 // DQ (12/26/2012): Added support for templates.
4111 case V_SgTemplateInstantiationDecl:
4112 case V_SgTemplateClassDeclaration:
4113
4114 case V_SgClassDeclaration:
4115 {
4116 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declarationForType);
4117 // SgSymbol* symbol = new SgClassSymbol(classDeclaration);
4118 SgSymbol* symbol = NULL;
4119 if (isSgTemplateClassDeclaration(declarationForType) != NULL)
4120 {
4121 symbol = new SgTemplateClassSymbol(classDeclaration);
4122 }
4123 else
4124 {
4125 symbol = new SgClassSymbol(classDeclaration);
4126 }
4127
4128 ROSE_ASSERT(symbol != NULL);
4129 SgName name = classDeclaration->get_name();
4130 symbolTable->insert(name,symbol);
4131 break;
4132 }
4133
4134 case V_SgEnumDeclaration:
4135 {
4136 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(declarationForType);
4137 SgSymbol* symbol = new SgEnumSymbol(enumDeclaration);
4138 ROSE_ASSERT(symbol != NULL);
4139 SgName name = enumDeclaration->get_name();
4140 symbolTable->insert(name,symbol);
4141 break;
4142 }
4143
4144 case V_SgFunctionDeclaration:
4145 {
4146 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declarationForType);
4147 SgSymbol* symbol = new SgFunctionSymbol(functionDeclaration);
4148 ROSE_ASSERT(symbol != NULL);
4149 SgName name = functionDeclaration->get_name();
4150 symbolTable->insert(name,symbol);
4151 break;
4152 }
4153
4154 case V_SgMemberFunctionDeclaration:
4155 {
4156 SgMemberFunctionDeclaration* functionDeclaration = isSgMemberFunctionDeclaration(declarationForType);
4157 SgSymbol* symbol = new SgMemberFunctionSymbol(functionDeclaration);
4158 ROSE_ASSERT(symbol != NULL);
4159
4160 // printf ("In supportForBaseTypeDefiningDeclaration(): symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4161
4162 SgName name = functionDeclaration->get_name();
4163 symbolTable->insert(name,symbol);
4164 break;
4165 }
4166
4167 default:
4168 {
4169 printf ("Default reached in evaluation of typedef inner definition = %p = %s and building a symbol for it for the symbol table \n",declarationForType,declarationForType->class_name().c_str());
4170 ROSE_ABORT();
4171 }
4172 }
4173 }
4174
4175
4176void
4177supportForVariableLists ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgInitializedNamePtrList & variableList )
4178 {
4179 // DQ (11/1/2007): Added supporting function to refactor code.
4180 SgInitializedNamePtrList::iterator i = variableList.begin();
4181 while (i != variableList.end())
4182 {
4184 ROSE_ASSERT(variable != NULL);
4185 if (variable->get_scope() == scope)
4186 {
4187 // printf ("Scopes match, OK! \n");
4188 }
4189 else
4190 {
4191 if (SgProject::get_verbose() > 0)
4192 {
4193 printf ("WARNING: Scopes do NOT match! variable = %p = %s (could this be a static variable, or has the symbol table been setup before the scopes have been set?) \n",variable,variable->get_name().str());
4194 }
4195 }
4196
4197 SgSymbol* symbol = new SgVariableSymbol(variable);
4198 ROSE_ASSERT(symbol != NULL);
4199 SgName name = variable->get_name();
4200 symbolTable->insert(name,symbol);
4201
4202 i++;
4203 }
4204 }
4205#if 0
4206// DQ (3/2/2014): Added a new interface function (used in the snippet insertion support).
4207void
4208SageInterface::supportForInitializedNameLists ( SgScopeStatement* scope, SgInitializedNamePtrList & variableList )
4209 {
4210 SgSymbolTable* symbolTable = scope->get_symbol_table();
4211 ROSE_ASSERT(symbolTable != NULL);
4212
4213 supportForVariableLists(scope,symbolTable,variableList);
4214 }
4215#endif
4216
4217void
4218supportForVariableDeclarations ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgVariableDeclaration* variableDeclaration )
4219 {
4220 // DQ (10/24/2007): Added supporting function to refactor code.
4221 SgInitializedNamePtrList & variableList = variableDeclaration->get_variables();
4222 supportForVariableLists(scope,symbolTable,variableList);
4223
4224 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4225 // that also force symbols to be built in the current scope!
4226 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4227 if (variableDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4228 {
4229 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4230 ROSE_ASSERT(symbolTable != NULL);
4231 ROSE_ASSERT(variableDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4232 supportForBaseTypeDefiningDeclaration ( symbolTable, variableDeclaration->get_baseTypeDefiningDeclaration() );
4233 }
4234 }
4235
4236void
4237supportForLabelStatements ( SgScopeStatement* scope, SgSymbolTable* symbolTable )
4238 {
4239 // Update the symbol table in SgFunctionDefinition with all the labels in the function.
4240
4241 std::vector<SgNode*> labelList = NodeQuery::querySubTree (scope,V_SgLabelStatement);
4242
4243 int numberOfLabels = labelList.size();
4244 for (int i=0; i < numberOfLabels; i++)
4245 {
4246 SgLabelStatement* labelStatement = isSgLabelStatement(labelList[i]);
4247
4248 ROSE_ASSERT(labelStatement != NULL);
4249 ROSE_ASSERT(labelStatement->get_scope() == scope);
4250
4251 SgSymbol* symbol = new SgLabelSymbol(labelStatement);
4252 ROSE_ASSERT(symbol != NULL);
4253
4254 // printf ("In SageInterface::rebuildSymbolTable() labelStatement = %p building a new SgLabelSymbol = %p \n",labelStatement,symbol);
4255
4256 SgName name = labelStatement->get_name();
4257 symbolTable->insert(name,symbol);
4258 }
4259 }
4260
4261
4262void
4264 {
4265 // This function is called from the implementation of the copy member functions.
4266
4267 ROSE_ASSERT(scope != NULL);
4268#if 0
4269 printf ("In SageInterface::rebuildSymbolTable(): Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4270#endif
4271#if 0
4272 printf ("Exiting as a test \n");
4273 ROSE_ABORT();
4274#endif
4275
4276 SgSymbolTable* symbolTable = scope->get_symbol_table();
4277
4278 if (symbolTable != NULL)
4279 {
4280 // This must be an empty symbol table!
4281 if (symbolTable->size() != 0)
4282 {
4283 printf ("symbolTable->size() = %d \n",symbolTable->size());
4284 }
4285 ROSE_ASSERT(symbolTable->size() == 0);
4286#if 0
4287 printf ("Symbol Table from %p = %s of size = %" PRIuPTR " \n",scope,scope->class_name().c_str(),symbolTable->size());
4288 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
4289#endif
4290 }
4291 else
4292 {
4293#if 0
4294 printf ("In SageInterface::rebuildSymbolTable(): No symbol table found \n");
4295#endif
4296 ROSE_ASSERT(symbolTable == NULL);
4297
4298 // DQ (10/8/2007): Build a new symbol table if there was not already one built.
4299 symbolTable = new SgSymbolTable();
4300
4301 ROSE_ASSERT(symbolTable != NULL);
4302 ROSE_ASSERT(symbolTable->get_table() != NULL);
4303
4304 // DQ (2/16/2006): Set this parent directly (now tested)
4305 symbolTable->set_parent(scope);
4306 ROSE_ASSERT(symbolTable->get_parent() != NULL);
4307
4308 scope->set_symbol_table(symbolTable);
4309 }
4310
4311 // DQ (10/8/2007): If there is already a symbol table then don't over write it. This fixes copies generated with more than one symbol table.
4312 ROSE_ASSERT(scope->get_symbol_table() != NULL);
4313 ROSE_ASSERT(scope->get_symbol_table()->get_table() != NULL);
4314
4315 // This implements SgScopeStatement specific details (e.g function declarations have parameters and their declaration causes variable
4316 // symbols to be placed into the SgFunctionDefinition scope (but only for defining declarations).
4317 switch(scope->variantT())
4318 {
4319 case V_SgForStatement:
4320 {
4321 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4322 // printf ("Symbol tables could contain symbols outside of the inclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4323
4324 SgForStatement* forStatement = isSgForStatement(scope);
4325
4326 SgStatementPtrList::iterator i = forStatement->get_init_stmt().begin();
4327
4328 // printf ("i != forStatement->get_init_stmt().end() = %s \n",i != forStatement->get_init_stmt().end() ? "true" : "false");
4329
4330 while (i != forStatement->get_init_stmt().end())
4331 {
4332 // printf ("For statement initialization list: *i = %p = %s \n",*i,(*i)->class_name().c_str());
4333 SgVariableDeclaration* variableDeclarationInitializer = isSgVariableDeclaration(*i);
4334 if (variableDeclarationInitializer != NULL)
4335 {
4336 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4337 // printf ("There is a variable declaration in the for statement initializer, it needs to be added to the symbol table scope = %p = %s \n",scope,scope->class_name().c_str());
4338 // ROSE_ASSERT(false);
4339 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationInitializer );
4340 }
4341
4342 i++;
4343 }
4344
4345 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(forStatement->get_test());
4346 if (variableDeclarationCondition != NULL)
4347 {
4348 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4349 // printf ("There is a variable declaration in the for statement test, it needs to be added to the symbol table scope = %p = %s \n",scope,scope->class_name().c_str());
4350 // ROSE_ASSERT(false);
4351 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4352 }
4353
4354 return;
4355 break;
4356 }
4357
4358 case V_SgJovialForThenStatement:
4359 case V_SgMatlabForStatement:
4360 {
4361 return;
4362 break;
4363 }
4364
4365
4366 // DQ (12/23/2012): Added support for templates.
4367 case V_SgTemplateFunctionDefinition:
4368
4369 case V_SgFunctionDefinition:
4370 {
4371 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4372 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4373
4374 // DQ (10/8/2007): If this is a SgFunctionDefinition, then include the parameters in the SgFunctionDeclaration.
4375 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
4376 if (functionDefinition != NULL)
4377 {
4378 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
4379 // printf ("In SageInterface::rebuildSymbolTable(): functionDefinition = %p functionDeclaration = %p \n",functionDefinition,functionDeclaration);
4380
4381 // DQ (10/8/2007): It turns out that this is always NULL, because the parent of the functionDeclaration has not yet been set in the copy mechanism!
4382 if (functionDeclaration != NULL)
4383 {
4384 // DQ (3/28/2014): After a call with Philippe, this Java specific issues is fixed and we don't seem to see this problem any more.
4385 if (functionDeclaration->isForward() == true)
4386 {
4387 printf ("ERROR: functionDeclaration = %p = %s = %s \n",functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
4388 printf (" --- functionDeclaration (get_name()) = %s \n",get_name(functionDeclaration).c_str());
4389 printf (" --- functionDeclaration (mangled name) = %s \n",functionDeclaration->get_mangled_name().str());
4390 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
4391 if (memberFunctionDeclaration != NULL)
4392 {
4393 printf ("memberFunctionDeclaration != NULL \n");
4394 }
4395 }
4396 ROSE_ASSERT(functionDeclaration->isForward() == false);
4397 SgInitializedNamePtrList & argumentList = functionDeclaration->get_args();
4398 supportForVariableLists(scope,symbolTable,argumentList);
4399 }
4400 else
4401 {
4402 // This happens in the copy function because the function definition is copied from the SgFunctionDeclaration
4403 // and only after the copy is made is the parent of the definition set to be the function declaration. Thus
4404 // the get_declaration() member function returns NULL.
4405 // printf ("There is no function declaration associated with this function definition! \n");
4406 // ROSE_ASSERT(functionDeclaration->isForward() == true);
4407 }
4408 }
4409
4410 // DQ (10/25/2007): Label symbols are now places into the SgFunctionDefinition (they have to be collected from the function).
4411 supportForLabelStatements(scope,symbolTable);
4412
4413 return;
4414 break;
4415 }
4416
4417 case V_SgIfStmt:
4418 {
4419 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4420 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4421
4422 SgIfStmt* ifStatement = isSgIfStmt(scope);
4423 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(ifStatement->get_conditional());
4424 if (variableDeclarationCondition != NULL)
4425 {
4426 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4427 // printf ("There is a variable declaration in the conditional, it needs to be added to the symbol table \n");
4428 // ROSE_ASSERT(false);
4429 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4430 }
4431 return;
4432 break;
4433 }
4434
4435 case V_SgSwitchStatement:
4436 {
4437 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4438 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4439
4440 SgSwitchStatement* switchStatement = isSgSwitchStatement(scope);
4441 SgVariableDeclaration* variableDeclarationSelector = isSgVariableDeclaration(switchStatement->get_item_selector());
4442 if (variableDeclarationSelector != NULL)
4443 {
4444 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4445 // printf ("There is a variable declaration in the item selector of the switch statement, it needs to be added to the symbol table \n");
4446
4447 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationSelector );
4448 }
4449 return;
4450 break;
4451 }
4452
4453 case V_SgWhileStmt:
4454 {
4455 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4456 // commented out like for others, otherwise show up each time a While is being copied. Liao, 1/31/2008
4457 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4458
4459 SgWhileStmt* whileStatement = isSgWhileStmt(scope);
4460 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(whileStatement->get_condition());
4461 if (variableDeclarationCondition != NULL)
4462 {
4463 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4464 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4465 // ROSE_ASSERT(false);
4466
4467 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4468 }
4469 return;
4470 break;
4471 }
4472
4473 case V_SgCatchOptionStmt:
4474 case V_SgDoWhileStmt:
4475 {
4476 // These scopes contain a SgBasicBlock as a data member and the scope is held there.
4477 // printf ("Symbol tables can must be computed by the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4478 return;
4479 break;
4480 }
4481
4482 // DQ (12/24/2012): Added support for templates.
4483 case V_SgTemplateClassDefinition:
4484
4485 case V_SgBasicBlock:
4486 case V_SgClassDefinition:
4487 case V_SgTemplateInstantiationDefn:
4488 case V_SgGlobal:
4489 case V_SgNamespaceDefinitionStatement:
4490 case V_SgFortranDo: // Liao 12/19/2008, My understanding is that Fortran do loop header does not introduce new symbols like a C/C++ for loop does
4491 {
4492 // printf ("Used the list of statements/declarations that are held deirectly by this scope \n");
4493 break;
4494 }
4495
4496 // DQ (3/29/2014): Added support for SgJavaForEachStatement.
4497 case V_SgJavaForEachStatement:
4498 {
4499 SgJavaForEachStatement* javaForEachStatement = isSgJavaForEachStatement(scope);
4500 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(javaForEachStatement->get_element());
4501 if (variableDeclarationCondition != NULL)
4502 {
4503 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4504 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4505 // ROSE_ASSERT(false);
4506
4507 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4508 }
4509 return;
4510 break;
4511 }
4512
4513 default:
4514 {
4515 printf ("Default reached in SageInterface::rebuildSymbolTable() scope = %p = %s \n",scope,scope->class_name().c_str());
4516 ROSE_ABORT();
4517 }
4518 }
4519
4520#if 0
4521 printf ("In SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4522#endif
4523
4524 // Generate a copy of the statement list (this is simpler than handling the cases of a
4525 // declaration list and a statement list separately for the scopes that contain one or the other.
4526 SgStatementPtrList statementList = scope->generateStatementList();
4527
4528 // Loop through the statements and for each declaration build a symbol and add it to the symbol table
4529 for (SgStatementPtrList::iterator i = statementList.begin(); i != statementList.end(); i++)
4530 {
4531 // At some point we should move this mechanism in to a factory patterns for SgSymbol
4532
4533 // printf ("Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4534
4535 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
4536 if (declaration != NULL)
4537 {
4538 // DQ (11/7/2007): Where there can be multiple declaration (e.g. function declarations with prototypes) only use one of them.
4539 bool useThisDeclaration = (declaration->get_firstNondefiningDeclaration() == declaration) ||
4540 ( (declaration->get_firstNondefiningDeclaration() == NULL) && (declaration->get_definingDeclaration() == declaration) );
4541
4542 list<SgSymbol*> symbolList;
4543 switch(declaration->variantT())
4544 {
4545 case V_SgTemplateInstantiationMemberFunctionDecl:
4546 {
4547 SgTemplateInstantiationMemberFunctionDecl* derivedDeclaration = isSgTemplateInstantiationMemberFunctionDecl(declaration);
4548 // DQ (11/6/2007): Don't build a symbol for the defining declaration defined in another scope and put the resulting symbol into the wrong scope
4549 if (scope == derivedDeclaration->get_scope())
4550 {
4551 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4552 ROSE_ASSERT(symbol != NULL);
4553
4554 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4555
4556 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s inserting a symbol = %p \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str(),symbol);
4557
4558 SgName name = derivedDeclaration->get_name();
4559 symbolTable->insert(name,symbol);
4560 }
4561 else
4562 {
4563 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4564
4565 // These IR nodes might only exist as a template declaration and thus not be structureally present in their scope.
4566 // So we would never traverse them in the correct scope and so never build sysmbols for them and add the symbols
4567 // to the correct symbol table. This is a fundamental problem. So we have to try to add these sorts of symbols
4568 // to the scope were they belong.
4569 SgScopeStatement* derivedDeclarationScope = derivedDeclaration->get_scope();
4570 ROSE_ASSERT(derivedDeclarationScope != NULL);
4571
4572 // If this is a copy then it would be nice to make sure that the scope has been properly set.
4573 // Check this by looking for the associated template declaration in the scope.
4574 // SgTemplateDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4575 // SgDeclarationStatement* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4576 SgTemplateMemberFunctionDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4577 ROSE_ASSERT(templateDeclaration != NULL);
4578 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_name());
4579
4580 // DQ (8/13/2013): Fixed the interface to avoid use of lookup_template_symbol() (removed).
4581 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
4582 // In this case these are unavailable from this point.
4583 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name());
4584 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4585 SgType* functionType = templateDeclaration->get_type();
4586 SgTemplateParameterPtrList & templateParameterList = templateDeclaration->get_templateParameters();
4587 // SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4588 SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_member_function_symbol(templateDeclaration->get_template_name(),functionType,&templateParameterList);
4589 if (templateSymbol != NULL)
4590 {
4591 // The symbol is not present, so we have to build one and add it.
4592#if 0
4593 printf ("Building a symbol for derivedDeclaration = %p = %s to an alternative symbol table in derivedDeclarationScope = %p \n",
4594 derivedDeclaration,get_name(derivedDeclaration).c_str(),derivedDeclarationScope);
4595#endif
4596 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4597 ROSE_ASSERT(symbol != NULL);
4598 SgName name = derivedDeclaration->get_name();
4599 derivedDeclarationScope->insert_symbol(name,symbol);
4600 }
4601 else
4602 {
4603 // printf ("The symbol was already present in the derivedDeclarationScope = %p \n",derivedDeclarationScope);
4604 }
4605 }
4606 break;
4607 }
4608
4609 // DQ (12/26/2012): Added support for templates.
4610 case V_SgTemplateMemberFunctionDeclaration:
4611
4612 case V_SgMemberFunctionDeclaration:
4613 {
4614 SgMemberFunctionDeclaration* derivedDeclaration = isSgMemberFunctionDeclaration(declaration);
4615
4616 // DQ (11/6/2007): Don't build a symbol for the defining declaration defined in another scope and put the resulting symbol into the wrong scope
4617 if (scope == derivedDeclaration->get_scope())
4618 {
4619 // SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4620 SgSymbol* symbol = NULL;
4621 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4622 symbol = new SgTemplateMemberFunctionSymbol(derivedDeclaration);
4623 else
4624 symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4625
4626 ROSE_ASSERT(symbol != NULL);
4627
4628 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4629
4630 SgName name = derivedDeclaration->get_name();
4631 symbolTable->insert(name,symbol);
4632 }
4633 else
4634 {
4635 // This happens when a defining declaration is located outside of the class where it is associated.
4636 // printf ("SgMemberFunctionDeclaration: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4637 }
4638 break;
4639 }
4640
4641 // DQ (2/26/2009): These have to be reformatted from where someone removed the formatting previously.
4642 case V_SgTemplateInstantiationFunctionDecl:
4643 {
4644 SgTemplateInstantiationFunctionDecl* derivedDeclaration = isSgTemplateInstantiationFunctionDecl(declaration);
4645 // DQ (10/21/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4646 if (scope == derivedDeclaration->get_scope())
4647 {
4648 SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4649 ROSE_ASSERT(symbol != NULL);
4650 SgName name = derivedDeclaration->get_name();
4651 symbolTable->insert(name,symbol);
4652 }
4653 else
4654 {
4655 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4656 {
4657#if PRINT_DEVELOPER_WARNINGS
4658 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4659#endif
4660 }
4661 }
4662
4663 break;
4664 }
4665
4666 // DQ (12/24/2012): Added support for templates.
4667 case V_SgTemplateFunctionDeclaration:
4668
4669 case V_SgFunctionDeclaration:
4670 {
4671 SgFunctionDeclaration* derivedDeclaration = isSgFunctionDeclaration(declaration);
4672
4673 // DQ (10/20/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4674
4675 if (useThisDeclaration == true)
4676 {
4677 if (scope == derivedDeclaration->get_scope())
4678 {
4679 // DQ (12/24/2012): Added support for templates.
4680 // SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4681 SgSymbol* symbol = NULL;
4682 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4683 symbol = new SgTemplateFunctionSymbol(derivedDeclaration);
4684 else
4685 symbol = new SgFunctionSymbol(derivedDeclaration);
4686
4687 ROSE_ASSERT(symbol != NULL);
4688 SgName name = derivedDeclaration->get_name();
4689 symbolTable->insert(name,symbol);
4690 }
4691 else
4692 {
4693 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4694 {
4695#if PRINT_DEVELOPER_WARNINGS
4696 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4697#endif
4698 }
4699 }
4700 }
4701 break;
4702 }
4703
4704 // DQ (12/28/2012): Adding support for templates.
4705 case V_SgTemplateVariableDeclaration:
4706
4707 case V_SgVariableDeclaration:
4708 {
4709 SgVariableDeclaration* derivedDeclaration = isSgVariableDeclaration(declaration);
4710 SgInitializedNamePtrList & variableList = derivedDeclaration->get_variables();
4711 SgInitializedNamePtrList::iterator i = variableList.begin();
4712 while ( i != variableList.end() )
4713 {
4715 ROSE_ASSERT(variable != NULL);
4716
4717 // DQ (10/20/2007): static data members declared outside the class scope don't generate symbols.
4718 if (variable->get_scope() == scope)
4719 {
4720 SgSymbol* symbol = new SgVariableSymbol(variable);
4721 ROSE_ASSERT(symbol != NULL);
4722
4723 // printf ("In SageInterface::rebuildSymbolTable() variable = %p building a new SgVariableSymbol = %p \n",variable,symbol);
4724
4725 SgName name = variable->get_name();
4726 symbolTable->insert(name,symbol);
4727 }
4728 else
4729 {
4730 // I think there is nothing to do in this case
4731 // printf ("In SageInterface::rebuildSymbolTable() This variable has a scope inconsistant with the symbol table: variable->get_scope() = %p scope = %p \n",variable->get_scope(),scope);
4732 }
4733
4734 i++;
4735 }
4736
4737 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4738 // that also force symbols to be built in the current scope!
4739 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4740 if (derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4741 {
4742 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4743 ROSE_ASSERT(symbolTable != NULL);
4744 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4745 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4746 }
4747
4748 // ROSE_ASSERT(symbolList.empty() == false);
4749 break;
4750 }
4751
4752 case V_SgTemplateInstantiationDecl:
4753 {
4754 SgTemplateInstantiationDecl* derivedDeclaration = isSgTemplateInstantiationDecl(declaration);
4755#if 1
4756 // printf ("case SgTemplateInstantiationDecl: derivedDeclaration name = %s derivedDeclaration->get_declarationModifier().isFriend() = %s \n",
4757 // derivedDeclaration->get_name().str(),derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4758
4759 if (scope == derivedDeclaration->get_scope())
4760 {
4761 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4762 // printf ("Inserting SgClassSymbol = %p into scope = %p = %s \n",symbol,scope,scope->class_name().c_str());
4763 ROSE_ASSERT(symbol != NULL);
4764 SgName name = derivedDeclaration->get_name();
4765#if 0
4766 // DQ (10/21/2007): The scopes should match
4767 if (scope != derivedDeclaration->get_scope())
4768 {
4769 printf ("Error: scopes don't match for derivedDeclaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4770 }
4771 ROSE_ASSERT(scope == derivedDeclaration->get_scope());
4772#endif
4773 symbolTable->insert(name,symbol);
4774 }
4775 else
4776 {
4777 // printf ("SgTemplateInstantiationDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4778
4779 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4780 {
4781#if PRINT_DEVELOPER_WARNINGS
4782 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4783#endif
4784 }
4785 }
4786#else
4787 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4788 ROSE_ASSERT(symbol != NULL);
4789 SgName name = derivedDeclaration->get_name();
4790 symbolTable->insert(name,symbol);
4791#endif
4792 break;
4793 }
4794
4795
4796 // DQ (12/24/2012): Added support for templates.
4797 case V_SgTemplateClassDeclaration:
4798
4799 case V_SgClassDeclaration:
4800 {
4801 SgClassDeclaration* derivedDeclaration = isSgClassDeclaration(declaration);
4802#if 1
4803 if (scope == derivedDeclaration->get_scope())
4804 {
4805 SgSymbol* symbol = NULL;
4806 if (isSgTemplateClassDeclaration(declaration) != NULL)
4807 symbol = new SgTemplateClassSymbol(derivedDeclaration);
4808 else
4809 symbol = new SgClassSymbol(derivedDeclaration);
4810
4811 ROSE_ASSERT(symbol != NULL);
4812 SgName name = derivedDeclaration->get_name();
4813 symbolTable->insert(name,symbol);
4814 }
4815 else
4816 {
4817 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4818 {
4819#if PRINT_DEVELOPER_WARNINGS
4820 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4821#endif
4822 }
4823 }
4824#else
4825 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4826 ROSE_ASSERT(symbol != NULL);
4827 SgName name = derivedDeclaration->get_name();
4828 symbolTable->insert(name,symbol);
4829#endif
4830 break;
4831 }
4832
4833 case V_SgEnumDeclaration:
4834 {
4835 SgEnumDeclaration* derivedDeclaration = isSgEnumDeclaration(declaration);
4836 ROSE_ASSERT(derivedDeclaration != NULL);
4837 SgSymbol* symbol = new SgEnumSymbol(derivedDeclaration);
4838 ROSE_ASSERT(symbol != NULL);
4839 SgName name = derivedDeclaration->get_name();
4840 symbolTable->insert(name,symbol);
4841
4842 // DQ (10/18/2007): Fixed construction of symbol tabel to include enum fields.
4843 SgInitializedNamePtrList & enumFieldList = derivedDeclaration->get_enumerators();
4844 SgInitializedNamePtrList::iterator i = enumFieldList.begin();
4845
4846 // Iterate over enum fields and add each one to the symbol table.
4847 while (i != enumFieldList.end())
4848 {
4849 SgSymbol* enum_field_symbol = new SgEnumFieldSymbol(*i);
4850 ROSE_ASSERT(enum_field_symbol != NULL);
4851 SgName enum_field_name = (*i)->get_name();
4852 symbolTable->insert(enum_field_name,enum_field_symbol);
4853
4854 i++;
4855 }
4856
4857 break;
4858 }
4859
4860
4861 // DQ (2/18/2017): Added support for C++11 SgTemplateTypedefDeclaration.
4862 case V_SgTemplateTypedefDeclaration:
4863
4864 case V_SgTypedefDeclaration:
4865 {
4866 SgTypedefDeclaration* derivedDeclaration = isSgTypedefDeclaration(declaration);
4867 SgSymbol* symbol = new SgTypedefSymbol(derivedDeclaration);
4868 ROSE_ASSERT(symbol != NULL);
4869 SgName name = derivedDeclaration->get_name();
4870 symbolTable->insert(name,symbol);
4871#if 0
4872 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration \n");
4873#endif
4874 // DQ (10/13/2007): Need to look into typedefs to see if there are defining declaration
4875 // that also force symbols to be built in the current scope!
4876 // ROSE_ASSERT(derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == false);
4877 if (derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == true)
4878 {
4879 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4880 ROSE_ASSERT(symbolTable != NULL);
4881 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4882#if 0
4883 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == true calling supportForBaseTypeDefiningDeclaration() \n");
4884#endif
4885 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4886 }
4887 else
4888 {
4889 // DQ (11/7/2007): If the typedef has a definition (e.g. function pointer) then build a symbol.
4890 SgDeclarationStatement* declaration = derivedDeclaration->get_declaration();
4891 if (declaration != NULL)
4892 {
4893#if 0
4894 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false calling supportForBaseTypeDefiningDeclaration() \n");
4895#endif
4896 // DQ (12/27/2012): Debugging the support for copytest_2007_40_cpp.C (we don't want to build this symbol since it is associated with an outer scope).
4897 // supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_declaration() );
4898
4899 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false: skipping call to supportForBaseTypeDefiningDeclaration() \n");
4900 }
4901 }
4902#if 0
4903 printf ("In SageInterface::rebuildSymbolTable(): Leaving case of SgTypedefDeclaration \n");
4904#endif
4905 break;
4906 }
4907
4908 case V_SgTemplateDeclaration:
4909 {
4910 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4911#if 1
4912 // DQ (10/21/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4913#if 0
4914 printf ("case V_SgTemplateDeclaration: derivedDeclaration = %p \n",derivedDeclaration);
4915 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_declarationModifier().isFriend() = %s \n",derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4916 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_name() = %s \n",derivedDeclaration->get_name().str());
4917 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_string() = %s \n",derivedDeclaration->get_string().str());
4918#endif
4919 if (scope == derivedDeclaration->get_scope())
4920 {
4921 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4922 ROSE_ASSERT(symbol != NULL);
4923 SgName name = derivedDeclaration->get_name();
4924 symbolTable->insert(name,symbol);
4925 }
4926 else
4927 {
4928 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4929 {
4930#if PRINT_DEVELOPER_WARNINGS
4931 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4932#endif
4933 }
4934 }
4935#else
4936 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4937 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4938 ROSE_ASSERT(symbol != NULL);
4939 SgName name = derivedDeclaration->get_name();
4940 symbolTable->insert(name,symbol);
4941#endif
4942 break;
4943 }
4944
4945 // Does this cause a symbol to be built? Seems that it should,
4946 // unless we always reference the non-aliased symbol (reuse it)!
4947 case V_SgNamespaceAliasDeclarationStatement:
4948 {
4949 SgNamespaceAliasDeclarationStatement* aliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
4950 ROSE_ASSERT(aliasDeclaration != NULL);
4951 ROSE_ASSERT(aliasDeclaration->get_namespaceDeclaration() != NULL);
4952
4953 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(aliasDeclaration->get_namespaceDeclaration());
4954 ROSE_ASSERT(derivedDeclaration != NULL);
4955
4956 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4957 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4958 ROSE_ASSERT(symbol != NULL);
4959 SgName name = derivedDeclaration->get_name();
4960 symbolTable->insert(name,symbol);
4961 // symbolList.push_back(symbol);
4962 // ROSE_ASSERT(symbolList.empty() == false);
4963 break;
4964 }
4965
4966 // Does this cause a symbol to be built? Seems that it should,
4967 // unless we always reference the non-aliased symbol (reuse it)!
4968 case V_SgNamespaceDeclarationStatement:
4969 {
4970 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(declaration);
4971 ROSE_ASSERT(derivedDeclaration != NULL);
4972
4973 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4974 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4975 ROSE_ASSERT(symbol != NULL);
4976 SgName name = derivedDeclaration->get_name();
4977 symbolTable->insert(name,symbol);
4978 // symbolList.push_back(symbol);
4979 // ROSE_ASSERT(symbolList.empty() == false);
4980 break;
4981 }
4982
4983 case V_SgUsingDirectiveStatement:
4984 case V_SgPragmaDeclaration:
4985 case V_SgTemplateInstantiationDirectiveStatement:
4986 case V_SgUsingDeclarationStatement:
4987 {
4988 // DQ (10/22/2005): Not sure if we have to worry about this declaration's appearance in the symbol table!
4989#if 0
4990 printf ("This declaration is ignored in rebuilding symbol table %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4991#endif
4992 break;
4993 }
4994
4995 case V_SgAsmStmt:
4996 {
4997 // DQ (8/13/2006): This is not really a declaration (I think). This will be fixed later.
4998#if 0
4999 printf ("An ASM statement (SgAsmStmt) declaration is not really a declaration %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5000#endif
5001 break;
5002 }
5003
5004 // Cases where declations are not used or referenced and so symbols are not required!
5005 case V_SgVariableDefinition:
5006 case V_SgFunctionParameterList:
5007 case V_SgCtorInitializerList:
5008 // These are not referenced so they don't need a symbol!
5009 {
5010 printf ("Special cases not handled %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5011 ROSE_ABORT();
5012 }
5013
5014 case V_SgStaticAssertionDeclaration:
5015 {
5016 // DQ (2/18/2017): This is not really a declaration (I think). This will be fixed later.
5017#if 0
5018 printf ("A static assertion statement (SgStaticAssertionDeclaration) declaration is not really a declaration %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5019#endif
5020 break;
5021 }
5022
5023 default:
5024 {
5025 printf ("Error: Default reached in rebuildSymbolTable declaration = %p = %s \n",declaration,declaration->class_name().c_str());
5026 ROSE_ABORT();
5027 }
5028 }
5029
5030 ROSE_ASSERT(symbolTable != NULL);
5031 ROSE_ASSERT(symbolTable->get_table() != NULL);
5032 }
5033 // printf ("DONE: Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5034
5035 }
5036
5037 ROSE_ASSERT(symbolTable != NULL);
5038 ROSE_ASSERT(symbolTable->get_table() != NULL);
5039
5040#if 0
5041 printf ("Leaving SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
5042#endif
5043
5044#if 0
5045 printf ("Symbol Table from %p = %s at: \n",scope,scope->class_name().c_str());
5046 scope->get_file_info()->display("Symbol Table Location");
5047 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
5048#endif
5049 }
5050
5051
5052// #ifndef USE_ROSE
5053
5054void
5056 {
5057 // This function is called by the SageInterface::rebuildSymbolTable().
5058 // It resets references to old symbols to the new symbols (just built).
5059 // All pairs of old/new symbols are also saved in the object:
5060 // SgCopyHelp::copiedNodeMapType copiedNodeMap
5061
5062#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
5063 ROSE_ASSERT(this_scope != NULL);
5064 ROSE_ASSERT(copy_scope != NULL);
5065
5066#if 0
5067 printf ("In fixupReferencesToSymbols(this_scope = %p = %s = %s, copy_scope = %p = %s = %s) \n",
5068 this_scope,this_scope->class_name().c_str(),get_name(this_scope).c_str(),
5069 copy_scope,copy_scope->class_name().c_str(),get_name(copy_scope).c_str());
5070#endif
5071
5072 SgSymbolTable* this_symbolTable = this_scope->get_symbol_table();
5073 SgSymbolTable* copy_symbolTable = copy_scope->get_symbol_table();
5074#if 0
5075 printf ("Before fixup: this scope = %p = %s this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_scope,this_scope->class_name().c_str(),this_symbolTable->get_table()->size());
5076 printf ("Before fixup: copy scope = %p = %s copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_scope,copy_scope->class_name().c_str(),copy_symbolTable->get_table()->size());
5077#endif
5078
5079 // DQ (3/4/2009): For now just output a warning, but this might be a more serious problem.
5080 // Since the symbol table size of the copy is larger than that of the original it might
5081 // be that a symbol is enterted twice by the copy mechanism. If so I want to fix this.
5082 if (this_symbolTable->get_table()->size() != copy_symbolTable->get_table()->size())
5083 {
5084 if (SgProject::get_verbose() > 0)
5085 {
5086 printf ("Before fixup: this scope = %p = %s this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_scope,this_scope->class_name().c_str(),this_symbolTable->get_table()->size());
5087 printf ("Before fixup: copy scope = %p = %s copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_scope,copy_scope->class_name().c_str(),copy_symbolTable->get_table()->size());
5088 printf ("Warning the symbols tables in these different scopes are different sizes \n");
5089 }
5090 }
5091 // ROSE_ASSERT(this_symbolTable->get_table()->size() <= copy_symbolTable->get_table()->size());
5092
5093 SgSymbolTable::hash_iterator i = this_symbolTable->get_table()->begin();
5094
5095 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
5096 std::map<SgNode*, SgNode*> replacementMap;
5097 int counter = 0;
5098 while (i != this_symbolTable->get_table()->end())
5099 {
5100 ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL );
5101
5102 SgName name = (*i).first;
5103 // SgSymbol* symbol = isSgSymbol((*i).second);
5104 SgSymbol* symbol = (*i).second;
5105 ROSE_ASSERT ( symbol != NULL );
5106
5107 SgSymbol* associated_symbol = NULL;
5108#if 0
5109 printf ("Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) = %p sage_class_name() = %s \n",counter,i->first.str(),i->second,i->second->class_name().c_str());
5110#endif
5111 // Look for the associated symbol in the copy_scope's symbol table.
5112 SgSymbolTable::hash_iterator associated_symbol_iterator = copy_symbolTable->get_table()->find(name);
5113
5114 // Note that this is a multi-map and for C++ a number of symbols can have the same name
5115 // (though not the same type of symbol) so we have to iterator over the symbols of the
5116 // same name so that we can identify the associated symbol.
5117 while (associated_symbol_iterator != copy_symbolTable->get_table()->end() && associated_symbol_iterator->first == name)
5118 {
5119 if ( associated_symbol_iterator->second->variantT() == symbol->variantT() )
5120 {
5121 associated_symbol = associated_symbol_iterator->second;
5122 }
5123
5124 associated_symbol_iterator++;
5125 }
5126
5127 if (associated_symbol != NULL)
5128 {
5129 ROSE_ASSERT ( associated_symbol != NULL );
5130
5131 // Check to make sure that this is correct
5132 ROSE_ASSERT(copy_scope->symbol_exists(associated_symbol) == true);
5133
5134 // Add the SgGlobal referenece to the replacementMap
5135 // replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
5136 // DQ (23/1/2009): Find the reference to symbol and replace it with associated_symbol.
5137 replacementMap.insert(pair<SgNode*,SgNode*>(symbol,associated_symbol));
5138
5139 // DQ (3/1/2009): This is backwards
5140 // replacementMap.insert(pair<SgNode*,SgNode*>(associated_symbol,symbol));
5141
5142 // DQ (3/2/2009): accumulate the symbol pair into the SgCopyHelp object (to support the outliner).
5143 // Actually this should also improve the robustness of the outliner.
5144 help.get_copiedNodeMap().insert(pair<const SgNode*,SgNode*>(symbol,associated_symbol));
5145 }
5146 else
5147 {
5148 // DQ (3/4/2009): This case was broken out because copytest2007_14.C fails here.
5149 if (SgProject::get_verbose() > 0)
5150 {
5151 printf ("Warning: Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) = %p sage_class_name() = %s \n",counter,i->first.str(),i->second,i->second->class_name().c_str());
5152 printf ("Warning: associated_symbol == NULL, need to investigate this (ignoring for now) \n");
5153 }
5154 }
5155
5156 counter++;
5157
5158 i++;
5159 }
5160
5161#if 0
5162 printf ("\n\n************************************************************\n");
5163 printf ("fixupReferencesToSymbols(this_scope = %p copy_scope = %p = %s = %s): calling Utils::edgePointerReplacement() \n",this_scope,copy_scope,copy_scope->class_name().c_str(),get_name(copy_scope).c_str());
5164#endif
5165
5166 Rose::AST::Utility::edgePointerReplacement(copy_scope,replacementMap);
5167
5168#if 0
5169 printf ("fixupReferencesToSymbols(): calling Utils::edgePointerReplacement(): DONE \n");
5170 printf ("************************************************************\n\n");
5171
5172 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
5173 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
5174
5175 printf ("After fixup: this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_symbolTable->get_table()->size());
5176 printf ("After fixup: copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_symbolTable->get_table()->size());
5177#endif
5178
5179 // DQ (3/1/2009): find a case where this code is tested.
5180 // ROSE_ASSERT(this_symbolTable->get_table()->size() == 0);
5181 // ROSE_ASSERT(isSgClassDefinition(copy_scope) == NULL);
5182#endif
5183
5184#if 0
5185 printf ("Exiting as a test in fixupReferencesToSymbols() \n");
5186 ROSE_ABORT();
5187#endif
5188 }
5189
5190// #endif
5191
5192#ifndef USE_ROSE
5193
5194std::vector<SgFile*>
5196 {
5197 // This function uses a memory pool traversal specific to the SgFile IR nodes
5198 class FileTraversal : public ROSE_VisitTraversal
5199 {
5200 public:
5201 vector<SgFile*> fileList;
5202 void visit ( SgNode* node)
5203 {
5204 SgFile* file = isSgFile(node);
5205 ROSE_ASSERT(file != NULL);
5206 if (file != NULL)
5207 {
5208 fileList.push_back(file);
5209 }
5210 };
5211
5212 virtual ~FileTraversal() {}
5213 };
5214
5215 FileTraversal fileTraversal;
5216
5217 // traverse just the SgFile nodes (both the SgSourceFile and SgBinaryComposite IR nodes)!
5218 // SgFile::visitRepresentativeNode(fileTraversal);
5220#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5222#endif
5223
5224 // This would alternatively traverse all IR nodes in thememory pool!
5225 // fileTraversal.traverseMemoryPool();
5226
5227 // TV (06/24/2013): This fail when calling SageBuilder::buildVariableDeclaration(...) without any file created.
5228 // DQ (10/11/2014): This is allowed to be empty (required for new aterm support).
5229 // ROSE_ASSERT(fileTraversal.fileList.empty() == false);
5230
5231 return fileTraversal.fileList;
5232 }
5233
5234#endif
5235
5236// #ifndef USE_ROSE
5237
5238// DQ (4/17/2015): I think this function should be removed since it interferes
5239// with the concept of having more than one SgProject node.
5240// This function uses a memory pool traversal specific to the SgProject IR nodes
5241SgProject*
5243{
5244#if 0
5245 class ProjectTraversal : public ROSE_VisitTraversal
5246 {
5247 public:
5248 SgProject * project;
5249 void visit ( SgNode* node)
5250 {
5251 project = isSgProject(node);
5252 ROSE_ASSERT(project!= NULL);
5253 };
5254 virtual ~ProjectTraversal() {}
5255 };
5256
5257 ProjectTraversal projectTraversal;
5258 SgProject::visitRepresentativeNode(projectTraversal);
5259 return projectTraversal.project;
5260#endif
5261 std::vector<SgProject* > resultlist = getSgNodeListFromMemoryPool<SgProject>();
5262 if (resultlist.empty())
5263 return NULL;
5264 ROSE_ASSERT(resultlist.size()==1);
5265 return resultlist[0];
5266}
5267
5268SgProject*
5270 return getEnclosingNode<SgProject>(node, true /*includingSelf*/);
5271}
5272
5274 SgFunctionDeclaration * ret = NULL;
5275 if (isSgFunctionRefExp(func))
5276 {
5277 return isSgFunctionRefExp(func)->get_symbol()->get_declaration();
5278 }
5279 else if (isSgDotExp(func) || isSgArrowExp(func))
5280 {
5281 SgExpression* func2 = isSgBinaryOp(func)->get_rhs_operand();
5282 if (isSgMemberFunctionRefExp(func2))
5283 return isSgMemberFunctionRefExp(func2)->get_symbol()->get_declaration();
5284 else
5285 {
5286 cerr<<"Warning in SageInterface::getDeclarationOfNamedFunction(): rhs operand of dot or arrow operations is not a member function, but a "<<func2->class_name()<<endl;
5287 }
5288 }
5289
5290 return ret;
5291}
5292
5294 SgExprListExp* el = stmt->get_forall_header();
5295 const SgExpressionPtrList& ls = el->get_expressions();
5296 if (ls.empty()) return 0;
5297 if (isSgAssignOp(ls.back())) return 0;
5298 return ls.back();
5299}
5300
5301//Find all SgPntrArrRefExp under astNode, add the referenced dim_info SgVarRefExp (if any) into NodeList_t
5302void SageInterface::addVarRefExpFromArrayDimInfo(SgNode * astNode, Rose_STL_Container<SgNode *>& NodeList_t)
5303{
5304 ASSERT_not_null(astNode);
5305 Rose_STL_Container<SgNode*> arr_exp_list = NodeQuery::querySubTree(astNode,V_SgPntrArrRefExp);
5306 for (SgNode* expr : arr_exp_list)
5307 {
5308 SgPntrArrRefExp* arr_exp = isSgPntrArrRefExp(expr);
5309 ASSERT_not_null(arr_exp);
5310 Rose_STL_Container<SgNode*> refList = NodeQuery::querySubTree(arr_exp->get_lhs_operand(),V_SgVarRefExp);
5311 for (SgNode* ref : refList)
5312 {
5313 SgVarRefExp* cur_ref = isSgVarRefExp(ref);
5314 ASSERT_not_null(cur_ref);
5315 SgVariableSymbol * sym = cur_ref->get_symbol();
5316 ASSERT_not_null(sym);
5317 SgInitializedName * iname = sym->get_declaration();
5318 ASSERT_not_null(iname);
5319 SgArrayType * a_type = isSgArrayType(iname->get_typeptr());
5320 if (a_type && a_type->get_dim_info())
5321 {
5322 Rose_STL_Container<SgNode*> dim_ref_list = NodeQuery::querySubTree(a_type->get_dim_info(),V_SgVarRefExp);
5323 for (Rose_STL_Container<SgNode*>::iterator iter2 = dim_ref_list.begin(); iter2 != dim_ref_list.end(); iter2++)
5324 {
5325 SgVarRefExp* dim_ref = isSgVarRefExp(*iter2);
5326 NodeList_t.push_back(dim_ref);
5327 }
5328 }
5329 }
5330 } // end for
5331}
5332
5333
5334// DQ (11/25/2020): This disables these non-inlined functions in favor of
5335// inlined versions of the functions in the sageInterface.h (header file).
5336#if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5337bool
5339 {
5340#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5341 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5342 return Rose::is_Ada_language;
5343#else
5344 bool returnValue = false;
5345
5346 vector<SgFile*> fileList = generateFileList();
5347
5348 int size = (int)fileList.size();
5349 for (int i = 0; i < size; i++)
5350 {
5351 if (fileList[i]->get_Ada_only() == true)
5352 returnValue = true;
5353 }
5354
5355 return returnValue;
5356#endif
5357 }
5358
5359bool
5361 {
5362#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5363 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5364 return Rose::is_C_language;
5365#else
5366 bool returnValue = false;
5367
5368 vector<SgFile*> fileList = generateFileList();
5369
5370 int size = (int)fileList.size();
5371 for (int i = 0; i < size; i++)
5372 {
5373 if (fileList[i]->get_C_only() == true)
5374 returnValue = true;
5375 }
5376
5377 return returnValue;
5378#endif
5379 }
5380
5381bool
5383 {
5384#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5385 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5386 return Rose::is_OpenMP_language;
5387#else
5388 bool returnValue = false;
5389
5390 vector<SgFile*> fileList = generateFileList();
5391
5392 int size = (int)fileList.size();
5393 for (int i = 0; i < size; i++)
5394 {
5395 if (fileList[i]->get_openmp() == true)
5396 returnValue = true;
5397 }
5398
5399 return returnValue;
5400#endif
5401 }
5402
5403bool
5405 {
5406#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5407 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5408 return Rose::is_UPC_language;
5409#else
5410 bool returnValue = false;
5411
5412 vector<SgFile*> fileList = generateFileList();
5413
5414 int size = (int)fileList.size();
5415 for (int i = 0; i < size; i++)
5416 {
5417 if (fileList[i]->get_UPC_only() == true)
5418 returnValue = true;
5419 }
5420
5421 return returnValue;
5422#endif
5423 }
5424
5425//FMZ
5426bool
5428 {
5429#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5430 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5431 return Rose::is_CAF_language;
5432#else
5433 bool returnValue = false;
5434
5435 vector<SgFile*> fileList = generateFileList();
5436
5437 int size = (int)fileList.size();
5438 for (int i = 0; i < size; i++)
5439 {
5440 if (fileList[i]->get_CoArrayFortran_only()==true)
5441 returnValue = true;
5442 }
5443
5444 return returnValue;
5445#endif
5446 }
5447
5448
5449// true if any of upc_threads is set to >0 via command line: -rose:upc_threads n
5450bool
5452 {
5453#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5454 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5455 return Rose::is_UPC_dynamic_threads;
5456#else
5457 bool returnValue = false;
5458
5459 vector<SgFile*> fileList = generateFileList();
5460
5461 int size = (int)fileList.size();
5462 for (int i = 0; i < size; i++)
5463 {
5464 if (fileList[i]->get_upc_threads() > 0)
5465 returnValue = true;
5466 }
5467
5468 return returnValue;
5469#endif
5470 }
5471
5472
5473
5474bool
5476 {
5477#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5478 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5479 return Rose::is_C99_language;
5480#else
5481 bool returnValue = false;
5482
5483 vector<SgFile*> fileList = generateFileList();
5484
5485 int size = (int)fileList.size();
5486 for (int i = 0; i < size; i++)
5487 {
5488 if (fileList[i]->get_C99_only() == true)
5489 returnValue = true;
5490 }
5491
5492 return returnValue;
5493#endif
5494 }
5495
5496bool
5498 {
5499#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5500 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5501 return Rose::is_Cxx_language;
5502#else
5503 bool returnValue = false;
5504
5505 vector<SgFile*> fileList = generateFileList();
5506
5507 int size = (int)fileList.size();
5508 for (int i = 0; i < size; i++)
5509 {
5510 // DQ (8/19/2007): Make sure this is not a Fortran code!
5511 if (fileList[i]->get_Cxx_only() == true)
5512 {
5513 ROSE_ASSERT(fileList[i]->get_Fortran_only() == false && fileList[i]->get_C99_only() == false && fileList[i]->get_C_only() == false && fileList[i]->get_binary_only() == false);
5514
5515 returnValue = true;
5516 }
5517 }
5518
5519 return returnValue;
5520#endif
5521 }
5522
5523bool
5525 {
5526#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5527 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5528 return Rose::is_Java_language;
5529#else
5530 bool returnValue = false;
5531
5532 vector<SgFile*> fileList = generateFileList();
5533
5534 int size = (int)fileList.size();
5535 for (int i = 0; i < size; i++)
5536 {
5537 if (fileList[i]->get_Java_only() == true)
5538 returnValue = true;
5539 }
5540
5541 return returnValue;
5542#endif
5543 }
5544
5545bool
5547 {
5548#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5549 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5550 return Rose::is_Jvm_language;
5551#else
5552 bool returnValue = false;
5553
5554 vector<SgFile*> fileList = generateFileList();
5555
5556 int size = (int)fileList.size();
5557 for (int i = 0; i < size; i++)
5558 {
5559 if (fileList[i]->get_Jvm_only() == true)
5560 returnValue = true;
5561 }
5562
5563 return returnValue;
5564#endif
5565 }
5566
5567// Rasmussen (4/4/2018): Added Jovial
5568bool
5570 {
5571#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5572 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5573 return Rose::is_Jovial_language;
5574#else
5575 bool returnValue = false;
5576
5577 vector<SgFile*> fileList = generateFileList();
5578
5579 int size = (int)fileList.size();
5580 for (int i = 0; i < size; i++)
5581 {
5582 if (fileList[i]->get_Jovial_only() == true)
5583 returnValue = true;
5584 }
5585
5586 return returnValue;
5587#endif
5588 }
5589
5590
5591bool
5593 {
5594#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5595 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5596 return Rose::is_Fortran_language;
5597#else
5598 bool returnValue = false;
5599
5600 vector<SgFile*> fileList = generateFileList();
5601
5602 int size = (int)fileList.size();
5603 for (int i = 0; i < size; i++)
5604 {
5605 if (fileList[i]->get_Fortran_only() == true)
5606 returnValue = true;
5607 }
5608
5609 return returnValue;
5610#endif
5611 }
5612
5613
5614bool
5616 {
5617#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5618 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5619 return Rose::is_binary_executable;
5620#else
5621 bool returnValue = false;
5622
5623 vector<SgFile*> fileList = generateFileList();
5624
5625 int size = (int)fileList.size();
5626 for (int i = 0; i < size; i++)
5627 {
5628 if (fileList[i]->get_binary_only() == true)
5629 returnValue = true;
5630 }
5631
5632 return returnValue;
5633#endif
5634 }
5635
5636bool
5638 {
5639#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5640 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5641 return Rose::is_PHP_language;
5642#else
5643 bool returnValue = false;
5644
5645 vector<SgFile*> fileList = generateFileList();
5646
5647 int size = (int)fileList.size();
5648 for (int i = 0; i < size; i++)
5649 {
5650 if (fileList[i]->get_PHP_only() == true)
5651 returnValue = true;
5652 }
5653
5654 return returnValue;
5655#endif
5656 }
5657
5658bool
5660 {
5661#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5662 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5663 return Rose::is_Python_language;
5664#else
5665 bool returnValue = false;
5666
5667 vector<SgFile*> fileList = generateFileList();
5668
5669 int size = (int)fileList.size();
5670 for (int i = 0; i < size; i++)
5671 {
5672 if (fileList[i]->get_Python_only() == true)
5673 returnValue = true;
5674 }
5675
5676 return returnValue;
5677#endif
5678 }
5679
5680bool
5682 {
5683#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5684 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5685 return Rose::is_Cuda_language;
5686#else
5687 bool returnValue = false;
5688
5689 vector<SgFile*> fileList = generateFileList();
5690
5691 int size = (int)fileList.size();
5692 for (int i = 0; i < size; i++)
5693 {
5694 if (fileList[i]->get_Cuda_only() == true)
5695 returnValue = true;
5696 }
5697
5698 return returnValue;
5699#endif
5700 }
5701
5702bool
5704 {
5705#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5706 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5707 return Rose::is_OpenCL_language;
5708#else
5709 bool returnValue = false;
5710
5711 vector<SgFile*> fileList = generateFileList();
5712
5713 int size = (int)fileList.size();
5714 for (int i = 0; i < size; i++)
5715 {
5716 if (fileList[i]->get_OpenCL_only() == true)
5717 returnValue = true;
5718 }
5719
5720 return returnValue;
5721#endif
5722 }
5723
5724// for if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5725#endif
5726
5731
5736
5741
5746
5751
5752// Languages that may have scopes that contain statements that are not only declarations.
5753// For Fortran and Jovial (at least), function definitions may be declared at the end of procedures.
5758
5759// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5760// labels for scopes in a function (as required for name mangling).
5761void
5763 {
5764 ASSERT_not_null(functionDefinition);
5765 std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5766
5767 // Clear the cache of stored (scope,integer) pairs
5768 scopeMap.erase(scopeMap.begin(),scopeMap.end());
5769
5770 ASSERT_require(scopeMap.empty() == true);
5771 ASSERT_require(functionDefinition->get_scope_number_list().empty() == true);
5772 }
5773
5774#ifndef USE_ROSE
5775
5776// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5777// labels for scopes in a function (as required for name mangling).
5778void
5780 {
5781 ROSE_ASSERT(functionDefinition != NULL);
5782 // std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5783 // ROSE_ASSERT(scopeMap.empty() == true);
5784 ROSE_ASSERT(functionDefinition->get_scope_number_list().empty() == true);
5785
5786 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5787 class ScopeNumberingTraversal : public AstSimpleProcessing
5788 {
5789 public:
5790 ScopeNumberingTraversal() : count (0), storedFunctionDefinition(NULL) {}
5791 void visit (SgNode* node)
5792 {
5793 SgScopeStatement* scope = isSgScopeStatement (node);
5794 if (scope != NULL)
5795 {
5796 // Set the function definition
5797 SgFunctionDefinition* testFunctionDefinition = isSgFunctionDefinition(scope);
5798 if (testFunctionDefinition != NULL && storedFunctionDefinition == NULL)
5799 {
5800 ROSE_ASSERT(storedFunctionDefinition == NULL);
5801 storedFunctionDefinition = testFunctionDefinition;
5802 }
5803
5804 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5805 ROSE_ASSERT(storedFunctionDefinition != NULL);
5806
5807 count++;
5808
5809 std::map<SgNode*,int> & scopeMap = storedFunctionDefinition->get_scope_number_list();
5810 scopeMap.insert(pair<SgNode*,int>(scope,count));
5811#if 0
5812 string functionName = storedFunctionDefinition->get_declaration()->get_name().str();
5813 printf ("In function = %s insert scope = %p = %s with count = %d into local map (size = %d) \n",
5814 functionName.c_str(),scope,scope->class_name().c_str(),count,scopeMap.size());
5815#endif
5816 }
5817 }
5818
5819 private:
5820 int count; // running total of scopes found in the input function
5821 SgFunctionDefinition* storedFunctionDefinition;
5822 };
5823
5824 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5825 ScopeNumberingTraversal traversal;
5826 traversal.traverse(functionDefinition, preorder);
5827 }
5828
5829#endif
5830
5831#ifndef USE_ROSE
5832
5833#if 0
5834// DQ (6/26/2007): These are removed and the support is added to SgNode to support a single mangled name cache.
5835// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5836// labels for scopes in a function (as required for name mangling).
5837void
5839 {
5840 ROSE_ASSERT(globalScope != NULL);
5841 std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5842
5843 // Clear the cache of stored (scope,integer) pairs
5844 mangledNameCache.erase(mangledNameCache.begin(),mangledNameCache.end());
5845
5846 ROSE_ASSERT(mangledNameCache.empty() == true);
5847 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5848 }
5849
5850// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5851// labels for scopes in a function (as required for name mangling).
5852void
5854 {
5855 ROSE_ASSERT(globalScope != NULL);
5856 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5857
5858 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5859 class MangledNameTraversal : public AstSimpleProcessing
5860 {
5861 public:
5862 MangledNameTraversal() : storedGlobalScope(NULL) {}
5863 void visit (SgNode* node)
5864 {
5865 SgFunctionDeclaration* mangleableNode = isSgFunctionDeclaration(node);
5866 if ( (mangleableNode != NULL) || (isSgGlobal(node) != NULL) )
5867 {
5868 // Set the global scope
5869 SgGlobal* testGlobalScope = isSgGlobal(mangleableNode);
5870 if (testGlobalScope != NULL && storedGlobalScope == NULL)
5871 {
5872 ROSE_ASSERT(storedGlobalScope == NULL);
5873 storedGlobalScope = testGlobalScope;
5874 }
5875
5876 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5877 ROSE_ASSERT(storedGlobalScope != NULL);
5878
5879 string mangledName = mangleableNode->get_mangled_name();
5880 // printf ("mangledName = %s \n",mangledName.c_str());
5881
5882 std::map<SgNode*,std::string> & mangledNameCache = storedGlobalScope->get_mangledNameCache();
5883 mangledNameCache.insert(pair<SgNode*,std::string>(mangleableNode,mangledName));
5884#if 0
5885 string nodeName = get_name(mangleableNode);
5886 printf ("At node = %p = %s = %s in local map (size = %d) \n",
5887 mangleableNode,mangleableNode->class_name().c_str(),nodeName.c_str(),mangledNameCache.size());
5888#endif
5889 }
5890 }
5891
5892 private:
5893 SgGlobal* storedGlobalScope;
5894 };
5895
5896 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5897 MangledNameTraversal traversal;
5898 traversal.traverse(globalScope, preorder);
5899 }
5900#endif
5901
5902
5903string
5905 {
5906 // The TransformationSupport is not defined yet (I forget the
5907 // details but I recall that there is a reason why this is this way).
5908 // SgGlobal* globalScope = TransformationSupport::getGlobalScope(astNode);
5909#if 0
5910 SgGlobal* globalScope = isSgGlobal(astNode);
5911
5912 if (globalScope == NULL && isSgFile(astNode) != NULL)
5913 {
5914 globalScope = isSgFile(astNode)->get_globalScope();
5915 ROSE_ASSERT(globalScope != NULL);
5916 }
5917
5918 if (globalScope == NULL && isSgProject(astNode) != NULL)
5919 {
5920 // Check to make sure that the SgFile can be uniquely determined
5921 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5922 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5923 ROSE_ASSERT(globalScope != NULL);
5924 }
5925
5926 SgNode* temp = astNode;
5927 while (temp->get_parent() != NULL && globalScope == NULL)
5928 {
5929 temp = temp->get_parent();
5930 globalScope = isSgGlobal(temp);
5931 }
5932 ROSE_ASSERT(globalScope != NULL);
5933#endif
5934
5935 // std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5936 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
5937
5938 // Build an iterator
5939 std::map<SgNode*,std::string>::iterator i = mangledNameCache.find(astNode);
5940
5941 string mangledName;
5942 if (i != mangledNameCache.end())
5943 {
5944 // get the precomputed mangled name!
5945 //~ printf ("Mangled name IS found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5946 mangledName = i->second;
5947 }
5948 else
5949 {
5950 // mangled name not found in cache!
5951 //~ printf ("Mangled name NOT found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5952 }
5953
5954 return mangledName;
5955 }
5956
5957#define DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE 0
5958#define DEBUG_MANGLED_SHORTNAME 1
5959
5960//#ifdef DEBUG_MANGLED_SHORTNAME
5961//std::unordered_map<uint64_t, std::string> SageInterface::mangledNameHashCollisionCheckMap;
5962//#endif
5963
5964std::string
5965SageInterface::addMangledNameToCache( SgNode* astNode, const std::string & oldMangledName)
5966 {
5967#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
5968 printf ("In SageInterface::addMangledNameToCache(): TOP: astNode = %p = %s oldMangledName = %s \n",astNode,astNode->class_name().c_str(),oldMangledName.c_str());
5969#endif
5970
5971//#define DEBUG_MANGLED_SHORTNAME 1
5972#ifdef DEBUG_MANGLED_SHORTNAME
5973 static std::unordered_map<uint64_t, std::string> mangledNameHashCollisionCheckMap;
5974#endif
5975
5976
5977#if 0
5978 SgGlobal* globalScope = isSgGlobal(astNode);
5979
5980 if (globalScope == NULL && isSgFile(astNode) != NULL)
5981 {
5982 globalScope = isSgFile(astNode)->get_globalScope();
5983 ROSE_ASSERT(globalScope != NULL);
5984 }
5985
5986 if (globalScope == NULL && isSgProject(astNode) != NULL)
5987 {
5988 // Check to make sure that the SgFile can be uniquely determined
5989 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5990 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5991 ROSE_ASSERT(globalScope != NULL);
5992 }
5993
5994 SgNode* temp = astNode;
5995 while (temp->get_parent() != NULL && globalScope == NULL)
5996 {
5997 temp = temp->get_parent();
5998 globalScope = isSgGlobal(temp);
5999 }
6000 ROSE_ASSERT(globalScope != NULL);
6001#endif
6002
6003 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
6004
6005 std::string mangledName;
6006
6007 if (SgProject::get_mangled_noshortname() == false) {
6008 std::map<std::string, uint64_t> & shortMangledNameCache = SgNode::get_shortMangledNameCache();
6009
6010 if (oldMangledName.size() > 40) {
6011 std::map<std::string, uint64_t>::const_iterator shortMNIter = shortMangledNameCache.find(oldMangledName);
6012 uint64_t idNumber = 0;
6013 if (shortMNIter != shortMangledNameCache.end())
6014 {
6015 idNumber = shortMNIter->second;
6016
6017#ifdef DEBUG_MANGLED_SHORTNAME
6018 //Check for hash colisions, if we found an idNumber, but the long mangled name is different, we have a problem
6019 auto collisionIt = mangledNameHashCollisionCheckMap.find(idNumber);
6020 if(collisionIt != mangledNameHashCollisionCheckMap.end() &&
6021 oldMangledName != shortMNIter->first)
6022 {
6023 mlog[Sawyer::Message::Common::ERROR] <<" Got a short mangled name collision. \n "<<
6024 oldMangledName << " and \n " << shortMNIter->first << " \n" <<
6025 "have the same idNumber of: " << Combinatorics::toBase62String(idNumber) << " " << shortMNIter->second << endl;
6026 exit(12);
6027 } else {
6028 mangledNameHashCollisionCheckMap[idNumber] = oldMangledName;
6029 }
6030#endif //DEBUG_MANGLED_SHORTNAME
6031
6032 }
6033 else
6034 {
6036 hasher.insert(oldMangledName);
6037 hasher.digest();
6038 idNumber = hasher.make64Bits();
6039 shortMangledNameCache.insert(std::pair<std::string, uint64_t>(oldMangledName, idNumber));
6040 }
6041
6042 std::ostringstream mn;
6043 mn << 'L' << Combinatorics::toBase62String(idNumber) << 'R';
6044 mangledName = mn.str();
6045 } else {
6046 mangledName = oldMangledName;
6047 }
6048 } else {
6049
6050 // DQ (7/24/2012): Note that using this option can cause some test codes using operators that have
6051 // difficult names (conversion operators to user-defined types) to fail. See test2004_141.C for example.
6052 // The conversion operator "operator T&() const;" will fail because the character "&" will remain in
6053 // mangled name. The substring coding changes the strings for the mangled names and this effectively
6054 // removes the special characters, but there could be cases where they might remain.
6055
6056 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
6057 static unsigned long counter = 0;
6058
6059 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
6060 // This supports debugging the new EDG 4.x interface...
6061 if (counter++ % 500 == 0)
6062 {
6063 printf ("WARNING: In SageInterface::addMangledNameToCache(): Using longer forms of mangled names (can cause some function names with embedded special characters to fail; test2004_141.C) \n");
6064 }
6065 mangledName = oldMangledName;
6066}
6067
6068 // DQ (6/26/2007): Output information useful for understanding Jeremiah's shortended name merge caching.
6069 // std::cerr << "Changed MN " << oldMangledName << " to " << mangledName << std::endl;
6070
6071#if 0
6072 printf ("Updating mangled name cache for node = %p = %s with mangledName = %s \n",astNode,astNode->class_name().c_str(),mangledName.c_str());
6073#endif
6074
6075#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
6076 SgStatement* statement = isSgStatement(astNode);
6077 if (statement != NULL && statement->hasExplicitScope() == true)
6078 {
6079 if (statement->get_scope() == NULL)
6080 {
6081 printf ("Warning: SageInterface::addMangledNameToCache(): In it might be premature to add this IR node and name to the mangledNameCache: statement = %p = %s oldMangledName = %s \n",
6082 statement,statement->class_name().c_str(),oldMangledName.c_str());
6083 }
6084 }
6085#endif
6086
6087 mangledNameCache.insert(pair<SgNode*,string>(astNode,mangledName));
6088
6089#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
6090 printf ("In SageInterface::addMangledNameToCache(): returning mangledName = %s \n",mangledName.c_str());
6091#endif
6092
6093 return mangledName;
6094 }
6095
6096
6097// #endif
6098
6099#ifndef USE_ROSE
6100
6101bool
6103 {
6104 // This function is used in the unparser, but might be more generally useful. Since it is
6105 // related to general AST tests, I have put it here. It might be alternatively put in the
6106 // src/backend/unparser or related utility directory.
6107
6108 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6109 // declarations in the preorder traversal of the AST.
6110 class DeclarationOrderTraversal : public AstSimpleProcessing
6111 {
6112 public:
6113 DeclarationOrderTraversal( SgDeclarationStatement* nonDefiningDeclaration, SgDeclarationStatement* definingDeclaration )
6114 : storedNondefiningDeclaration(nonDefiningDeclaration),
6115 storedDefiningDeclaration(definingDeclaration)
6116 {
6117 storedDeclarationFound = false;
6118 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6119 }
6120
6121 void visit (SgNode* node)
6122 {
6123 ROSE_ASSERT(storedNondefiningDeclaration != NULL);
6124 ROSE_ASSERT(storedDefiningDeclaration != NULL);
6125 ROSE_ASSERT(storedNondefiningDeclaration != storedDefiningDeclaration);
6126 // ROSE_ASSERT(storedNondefiningDeclaration->get_definingDeclaration() == storedDefiningDeclaration);
6127
6128 // Even though we only care about the SgClassDeclaration IR nodes we have to traverse them
6129 // in the AST in the order defined by the traversal (order of apprearance in the AST). We
6130 // also can't just search the declarations of a single scope (since the nondefining declaration
6131 // can appear in a different scope than the defining declaration).
6132 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6133 if ( declaration != NULL )
6134 {
6135 if (storedDeclarationFound == false)
6136 {
6137 if (declaration == storedDefiningDeclaration)
6138 {
6139 storedDeclarationFound = true;
6140 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6141 }
6142 if (declaration == storedNondefiningDeclaration)
6143 {
6144 storedDeclarationFound = true;
6145 nonDefiningDeclarationPreceedsDefiningDeclaration = true;
6146 }
6147 }
6148 }
6149 }
6150
6151 public:
6152 bool storedDeclarationFound;
6153 bool nonDefiningDeclarationPreceedsDefiningDeclaration;
6154
6155 private:
6156 SgDeclarationStatement* storedNondefiningDeclaration;
6157 SgDeclarationStatement* storedDefiningDeclaration;
6158 };
6159
6160 ROSE_ASSERT(nonDefiningDeclaration != NULL);
6161#if 0
6162 printf ("In SageInterface::declarationPreceedsDefinition(): \n");
6163 printf (" nondefiningDeclaration = %p = %s \n",nonDefiningDeclaration,nonDefiningDeclaration->class_name().c_str());
6164 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6165 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6166 printf (" definingDeclaration = %p = %s \n",definingDeclaration,definingDeclaration->class_name().c_str());
6167 definingDeclaration->get_file_info()->display("definingDeclaration");
6168 printf ("************************************************************* \n");
6169#endif
6170
6171#if 0
6172 // The nonDefiningDeclaration can be a different type of declaration than the definingDeclaration
6173 if (nonDefiningDeclaration->get_definingDeclaration() != definingDeclaration)
6174 {
6175 printf ("In SageInterface::declarationPreceedsDefinition() (warning): \n");
6176 printf (" nondefiningDeclaration = %p \n",nonDefiningDeclaration);
6177 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6178 printf (" definingDeclaration = %p \n",definingDeclaration);
6179 }
6180#endif
6181
6182 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6183 bool returnResult = false;
6184 if (nonDefiningDeclaration != definingDeclaration)
6185 {
6186 // Get the global scope from a traversal back (up) through the AST.
6187 SgGlobal* globalScope = TransformationSupport::getGlobalScope(definingDeclaration);
6188 ROSE_ASSERT(globalScope != NULL);
6189
6190 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6191 DeclarationOrderTraversal traversal (nonDefiningDeclaration,definingDeclaration);
6192
6193#if 0
6194 traversal.traverse(globalScope, preorder);
6195#else
6196 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6197 printf ("Skipping traversal within SageInterface::declarationPreceedsDefinition() \n");
6198 traversal.storedDeclarationFound = true;
6199 traversal.nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6200#endif
6201
6202 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6203 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6204 // nondefining declarations that are not in the traversal).
6205
6206 if (traversal.storedDeclarationFound == false)
6207 {
6208#if 0
6209 printf ("In SageInterface::declarationPreceedsDefinition(): warning, nonDefiningDeclaration not found in the AST \n");
6210 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6211 definingDeclaration->get_file_info()->display("definingDeclaration");
6212 printf ("---------------------------------------------------- \n\n");
6213#endif
6214 // Set this error case to return true so that we will not assume incorrectly
6215 // that the classNonDefiningDeclaration apears after the classDefiningDeclaration.
6216 returnResult = true;
6217 }
6218 else
6219 {
6220 returnResult = traversal.nonDefiningDeclarationPreceedsDefiningDeclaration;
6221 }
6222
6223 // ROSE_ASSERT(traversal.storedDeclarationFound == true);
6224 }
6225#if 0
6226 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6227 printf ("************************************************************* \n\n");
6228#endif
6229 return returnResult;
6230 }
6231
6232
6233bool
6235 {
6236 // This function is used in the unparser, but might be more generally useful. Since it is
6237 // related to general AST tests, I have put it here. It might be alternatively put in the
6238 // src/backend/unparser or related utility directory.
6239
6240 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6241 // declarations in the preorder traversal of the AST.
6242 class DeclarationOrderTraversal : public AstSimpleProcessing
6243 {
6244 public:
6245 DeclarationOrderTraversal( SgFunctionCallExp* functionCall )
6246 : storedFunctionCall(functionCall)
6247 {
6248 ROSE_ASSERT(functionCall != NULL);
6249 ROSE_ASSERT(functionCall->get_function() != NULL);
6250 SgExpression* functionExpression = functionCall->get_function();
6251
6252 switch (functionExpression->variantT())
6253 {
6254 // these are the acceptable cases
6255 case V_SgDotExp:
6256 case V_SgDotStarOp:
6257 case V_SgArrowExp:
6258 case V_SgArrowStarOp:
6259 case V_SgPointerDerefExp:
6260 {
6261 // These are the acceptable cases, but not handled yet.
6262 printf ("These are the acceptable cases, but not handled yet... \n");
6263 ROSE_ABORT();
6264 }
6265
6266 case V_SgFunctionRefExp:
6267 {
6268 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionExpression);
6269 ROSE_ASSERT(functionRefExp != NULL);
6270 SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol();
6271 ROSE_ASSERT(functionSymbol != NULL);
6272
6273 // Make sure that the function has a valid declaration
6274 ROSE_ASSERT(functionSymbol->get_declaration() != NULL);
6275 storedFunctionDeclaration = functionSymbol->get_declaration();
6276 break;
6277 }
6278
6279 case V_SgMemberFunctionRefExp:
6280 {
6281 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(functionExpression);
6282 ROSE_ASSERT(memberFunctionRefExp != NULL);
6283 SgMemberFunctionSymbol* memberFunctionSymbol = memberFunctionRefExp->get_symbol();
6284 ROSE_ASSERT(memberFunctionSymbol != NULL);
6285
6286 storedFunctionDeclaration = memberFunctionSymbol->get_declaration();
6287
6288 printf ("V_SgMemberFunctionRefExp case not handled yet... \n");
6289 ROSE_ABORT();
6290 }
6291
6292 default:
6293 {
6294 printf ("default reached in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() functionExpression = %s \n",
6295 functionExpression->class_name().c_str());
6296 ROSE_ABORT();
6297 }
6298 }
6299 // ROSE_ASSERT(functionCall->get_declaration() != NULL);
6300 // ROSE_ASSERT(functionCall->get_function()->get_firstNondefiningDeclaration() != NULL);
6301 // storedFunctionDeclaration = functionCall->get_declaration()->get_firstNondefiningDeclaration();
6302 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6303
6304 storedFunctionCallFound = false;
6306 }
6307
6308 void visit (SgNode* node)
6309 {
6310 ROSE_ASSERT(storedFunctionCall != NULL);
6311 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6312 // ROSE_ASSERT(storedFunctionCall != storedFunctionDeclaration);
6313
6314 if (storedFunctionCallFound == false)
6315 {
6316 SgFunctionCallExp* functionCall = isSgFunctionCallExp(node);
6317 if ( functionCall != NULL )
6318 {
6319 if (functionCall == storedFunctionCall)
6320 {
6321 storedFunctionCallFound = true;
6322
6323 // A declaration for the function in a scope where the function could be defined
6324 // (and a scope associated with it) has not been found so the function call
6325 // preceeds such a declaration (if it even exists).
6327 }
6328 }
6329
6330 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6331 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6332
6333 // Note that all firstNondefiningDeclaration are set to the same declaration (for all associated declarations).
6334 // Need to check the result of get_firstNondefiningDeclaration() since this will be the same for all declarations
6335 // of the same function and thus can be used to match that we have an associated declaration for the same function.
6336 if ( declaration != NULL && declaration->get_firstNondefiningDeclaration() == storedFunctionDeclaration->get_firstNondefiningDeclaration())
6337 {
6338 // Test if this is a declaration is a scope where the existance of the forward
6339 // declaration will define the scope fo the function declaration.
6340 SgScopeStatement* parentScopeOfDeclaration = isSgScopeStatement(declaration->get_parent());
6341 if (parentScopeOfDeclaration != NULL && parentScopeOfDeclaration->supportsDefiningFunctionDeclaration() == true)
6342 {
6343 // We are done so we can skip further testing
6344 storedFunctionCallFound = true;
6345
6346 // We have found a declaration which will associated the scope of a function declaration
6347 // (so all function calls after this point can be qualified (and might have to be).
6349#if 0
6350 printf ("Found a declaration which preceeds the function \n");
6351 declaration->get_file_info()->display("Found a declaration which preceeds the function: declaration");
6352 storedFunctionCall->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionCall");
6353 storedFunctionDeclaration->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionDeclaration");
6354#endif
6355 }
6356 else
6357 {
6358 // Error checking!
6359 if (parentScopeOfDeclaration == NULL)
6360 {
6361 // This might be a function declaration (non-defining) used in a type or buried deeply in some sort of declaration!
6362 printf ("Strange case of parentScopeOfDeclaration == NULL in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6363 SgNode* parent = declaration->get_parent();
6364 if (parent != NULL) {
6365 printf ("declaration->get_parent() = %s \n",parent->class_name().c_str());
6366 }
6367 else {
6368 printf ("declaration->get_parent() = NULL \n");
6369 }
6370 declaration->get_file_info()->display("case of parentScopeOfDeclaration == NULL");
6371 ROSE_ABORT();
6372 }
6373 }
6374 }
6375 }
6376 }
6377
6378 public:
6379 bool storedFunctionCallFound;
6381
6382 private:
6383 SgFunctionCallExp* storedFunctionCall;
6384 SgDeclarationStatement* storedFunctionDeclaration;
6385 };
6386
6387 ROSE_ASSERT(functionCall != NULL);
6388#if 0
6389 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): \n");
6390 printf (" storedFunctionCall = %p = %s \n",functionCall,functionCall->class_name().c_str());
6391 functionCall->get_file_info()->display("storedFunctionCall");
6392 printf (" storedFunctionCall->get_function() = %p = %s \n",functionCall->get_function(),functionCall->get_function()->class_name().c_str());
6393 printf ("************************************************************* \n");
6394#endif
6395
6396 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6397 bool returnResult = false;
6398
6399 // Get the global scope from a traversal back (up) through the AST.
6400 SgGlobal* globalScope = TransformationSupport::getGlobalScope(functionCall);
6401 ROSE_ASSERT(globalScope != NULL);
6402
6403 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6404 DeclarationOrderTraversal traversal (functionCall);
6405
6406#if 0
6407 traversal.traverse(globalScope, preorder);
6408#else
6409 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6410 printf ("Skipping traversal within SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6411 traversal.storedFunctionCallFound = true;
6412 traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope = false;
6413#endif
6414
6415 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6416 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6417 // nondefining declarations that are not in the traversal).
6418
6419 if (traversal.storedFunctionCallFound == false)
6420 {
6421#if 0
6422 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): warning, storedFunctionCall not found in the AST \n");
6423 functionCall->get_file_info()->display("functionCall");
6424 printf ("---------------------------------------------------- \n\n");
6425#endif
6426 // Set this error case to return true so that we will not assume incorrectly
6427 // that the function call is used after a declaration that associated the scope
6428 // with the function. This still causes the global name qualifier to be omitted.
6429 returnResult = true;
6430 }
6431 else
6432 {
6433 returnResult = traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope;
6434 }
6435
6436 // I hope that this is nearly always be true!
6437 ROSE_ASSERT(traversal.storedFunctionCallFound == true);
6438#if 0
6439 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6440 printf ("************************************************************* \n\n");
6441#endif
6442 return returnResult;
6443 }
6444
6445#endif
6446
6447// #ifndef USE_ROSE
6448
6449string
6450SageInterface::generateProjectName( const SgProject* project, bool supressSuffix )
6451 {
6452 // This function generates a string to use as a unique project name for
6453 // a collection of files. The last file will include it's suffix so that
6454 // we generate proper names that communicate the source language.
6455 // Also also allows the single file case to be consistant with the previous
6456 // version of names generated for "DOT" files in the tutorial.
6457
6458 // DQ (9/6/2008): Introduced optional parameter to supresse the suffix in the
6459 // generation of the project name so that we can support more complex name
6460 // construction as required for the generation of names for the whole AST
6461 // graphs which append an additional suffix to avoid filename collision.
6462
6463 ROSE_ASSERT(project != NULL);
6464 string projectName;
6465
6466 // DQ (9/2/2008): Removed the redundant function getFileNames().
6467 // Rose_STL_Container<string> fileList = project->get_sourceFileNameList();
6468 Rose_STL_Container<string> fileList = project->getAbsolutePathFileNames();
6469
6470 Rose_STL_Container<string>::iterator i = fileList.begin();
6471
6472 // Handle the case of an empty list (e.g. for link lines).
6473 if ( fileList.empty() == true )
6474 {
6475 return "empty_file_list";
6476 }
6477
6478 do {
6479 string filename = *i;
6480
6481 // printf ("In SageInterface::generateProjectName(): absolute filename = %s \n",filename.c_str());
6482
6483 // string filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6484
6485 if (i != fileList.begin())
6486 projectName += "--";
6487
6488 i++;
6489
6490 string filenameWithoutSuffix;
6491 if ( i != fileList.end() || supressSuffix == true )
6492 filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6493 else
6494 filenameWithoutSuffix = filename;
6495
6496 string filenameWithoutPathOrSuffix = StringUtility::stripPathFromFileName(filenameWithoutSuffix);
6497
6498 // printf ("filenameWithoutSuffix = %s \n",filenameWithoutSuffix.c_str());
6499 // printf ("filenameWithoutPathOrSuffix = %s \n",filenameWithoutPathOrSuffix.c_str());
6500
6501 filename = filenameWithoutPathOrSuffix;
6502
6503 unsigned long int n = 0;
6504 while (n < filename.size())
6505 {
6506 if (filename[n] == '/')
6507 filename[n] = '_';
6508 n++;
6509 }
6510
6511 // printf ("In SageInterface:generateProjectName(): modified absolute filename = %s \n",filename.c_str());
6512
6513 projectName += filename;
6514
6515 // printf ("In SageInterface:generateProjectName(): evolving projectName = %s \n",projectName.c_str());
6516 }
6517 while (i != fileList.end());
6518
6519 // printf ("In SageInterface:generateProjectName(): projectName = %s \n",projectName.c_str());
6520
6521 return projectName;
6522 }
6523
6524// #endif
6525
6526// #ifndef USE_ROSE
6527
6530 {
6531 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6532 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6533
6534 // enable default search from top of StackScope, Liao, 1/24/2008
6535 SgFunctionSymbol* functionSymbol = NULL;
6536 if (currentScope == NULL)
6537 currentScope = SageBuilder::topScopeStack();
6538 ROSE_ASSERT(currentScope != NULL);
6539
6540 SgScopeStatement* tempScope = currentScope;
6541 while ((functionSymbol == NULL) && (tempScope != NULL))
6542 {
6543 functionSymbol = tempScope->lookup_function_symbol(functionName);
6544#if 0
6545 printf ("In lookupFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6546#endif
6547 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6548 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6549 else
6550 tempScope = NULL;
6551 }
6552 return functionSymbol;
6553 }
6554
6556SageInterface::lookupTemplateFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6557 {
6558 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6559 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6560
6561 // enable default search from top of StackScope, Liao, 1/24/2008
6562 SgFunctionSymbol* functionSymbol = NULL;
6563 if (currentScope == NULL)
6564 currentScope = SageBuilder::topScopeStack();
6565 ROSE_ASSERT(currentScope != NULL);
6566
6567 SgScopeStatement* tempScope = currentScope;
6568 while ((functionSymbol == NULL) && (tempScope != NULL))
6569 {
6570 functionSymbol = tempScope->lookup_template_function_symbol(functionName, ftype, tplparams);
6571#if 0
6572 printf ("In lookupTemplateFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6573#endif
6574 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6575 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6576 else
6577 tempScope = NULL;
6578 }
6579 return functionSymbol;
6580 }
6581
6583SageInterface::lookupTemplateMemberFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6584 {
6585 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6586 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6587
6588 // enable default search from top of StackScope, Liao, 1/24/2008
6589 SgFunctionSymbol* functionSymbol = NULL;
6590 if (currentScope == NULL)
6591 currentScope = SageBuilder::topScopeStack();
6592 ROSE_ASSERT(currentScope != NULL);
6593
6594 SgScopeStatement* tempScope = currentScope;
6595 while ((functionSymbol == NULL) && (tempScope != NULL))
6596 {
6597 functionSymbol = tempScope->lookup_template_member_function_symbol(functionName, ftype, tplparams);
6598#if 0
6599 printf ("In lookupTemplateMemberFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6600#endif
6601 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6602 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6603 else
6604 tempScope = NULL;
6605 }
6606 return functionSymbol;
6607 }
6608
6609void
6610SageInterface::addTextForUnparser ( SgNode* astNode, string s, AstUnparseAttribute::RelativePositionType inputlocation )
6611 {
6612 // printf ("addText(): using new attribute interface (s = %s) \n",s.c_str());
6613
6614 if (isSgType(astNode) != NULL)
6615 {
6616 printf ("Error: the mechanism to add text to be unparsed at IR nodes is not intended to operate on SgType IR nodes (since they are shared) \n");
6617 ROSE_ABORT();
6618 }
6619
6620 if (astNode->attributeExists(AstUnparseAttribute::markerName) == true)
6621 {
6622 AstUnparseAttribute* code = dynamic_cast<AstUnparseAttribute*>(astNode->getAttribute(AstUnparseAttribute::markerName));
6623 ROSE_ASSERT(code != NULL);
6624
6625 // DQ (2/23/2009): commented added.
6626 // Since there is at least one other string (there is an existing attribute) the relative order of the strings is significant.
6627 code->addString(s,inputlocation);
6628 }
6629 else
6630 {
6631 // DQ (2/25/2016): I think it is significant, because inputlocation refers to the order relative to
6632 // the statement, not relative to other AstUnparseAttribute objects. Fixed to use the inputlocation.
6633 // DQ (2/23/2009): commented added.
6634 // Note that this will be the only string in the attribute, so inputlocation is not significant (and e_before is the default used).
6635 // AstUnparseAttribute* code = new AstUnparseAttribute(s,AstUnparseAttribute::e_before);
6636 AstUnparseAttribute* code = new AstUnparseAttribute(s,inputlocation);
6637 ROSE_ASSERT(code != NULL);
6638
6639 astNode->addNewAttribute(AstUnparseAttribute::markerName,code);
6640 }
6641 }
6642
6643
6644#if 0
6645// DQ (7/20/2011): Resolving conflict, this was added in previous work in dq-cxx-rc branch.
6646// DQ (7/17/2011): Added function from cxx branch that I need here for the Java support.
6649 {
6650 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6651 SgClassSymbol* symbol = NULL;
6652 if (cscope == NULL)
6653 cscope = SageBuilder::topScopeStack();
6654 ROSE_ASSERT(cscope != NULL);
6655
6656 while ((cscope != NULL) && (symbol == NULL))
6657 {
6658 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6659 symbol = cscope->lookup_class_symbol(name,NULL);
6660
6661 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6662 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6663 else
6664 cscope = NULL;
6665 }
6666
6667 return symbol;
6668 }
6669#endif
6670
6671
6672
6673SgType* SageInterface::lookupNamedTypeInParentScopes(const std::string& type_name, SgScopeStatement* scope/*=NULL*/)
6674 {
6675 if (scope == NULL)
6677
6678 // DQ (8/16/2013): Added NULL pointers to at least handle the API change.
6679 SgSymbol* symbol = lookupSymbolInParentScopes (type_name,scope,NULL,NULL);
6680
6681 if (symbol == NULL)
6682 return NULL;
6683 else
6684 return symbol->get_type();
6685 }
6686
6688 const SgType* t,
6689 SgScopeStatement *currentScope)
6690 //SgScopeStatement *currentScope=NULL)
6691{
6692 SgFunctionSymbol* functionSymbol = NULL;
6693 if (currentScope == NULL)
6694 currentScope = SageBuilder::topScopeStack();
6695 ROSE_ASSERT(currentScope != NULL);
6696 SgScopeStatement* tempScope = currentScope;
6697 while (functionSymbol == NULL && tempScope != NULL)
6698 {
6699 functionSymbol = tempScope->lookup_function_symbol(functionName,t);
6700 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6701 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6702 else tempScope = NULL;
6703 }
6704 return functionSymbol;
6705}
6706
6707SgSymbol*
6708SageInterface::lookupSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6709 {
6710 SgSymbol* symbol = nullptr;
6711 if (cscope == nullptr) {
6712 cscope = SageBuilder::topScopeStack();
6713 }
6714 ASSERT_not_null(cscope);
6715
6716 while ((cscope != nullptr) && (symbol == nullptr))
6717 {
6718 symbol = cscope->lookup_symbol(name,templateParameterList,templateArgumentList);
6719 if (cscope->get_parent() != nullptr) // avoid calling get_scope when parent is not set
6720 cscope = isSgGlobal(cscope) ? nullptr : cscope->get_scope();
6721 else
6722 cscope = nullptr;
6723 }
6724
6725 return symbol;
6726 }
6727
6728
6729
6730SgSymbol*
6731SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols (const SgName & name, SgScopeStatement *currentScope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6732 {
6733// DQ (8/5/2020): the "using namespace" directive will not hide existing visability of symbols in resolving visability.
6734// So we need to test if a symbol is visible exclusing matching alises due to using direectives before we can decide to
6735// persue name space qualification. This is best demonstrated by Cxx_tests/test2020_18.C, test2020_19.C, test2020_20.C,
6736// and test2020_21.C.
6737
6738 SgSymbol* symbol = NULL;
6739 if (currentScope == NULL)
6740 {
6741 currentScope = SageBuilder::topScopeStack();
6742 }
6743
6744 ROSE_ASSERT(currentScope != NULL);
6745
6746#define DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS 0
6747
6748#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6749 printf ("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): currentScope = %p = %s (templateParameterList = %p templateArgumentList = %p) \n",
6750 currentScope,currentScope->class_name().c_str(),templateParameterList,templateArgumentList);
6751#endif
6752
6753 while ((currentScope != NULL) && (symbol == NULL))
6754 {
6755#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6756 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): name = %s currentScope = %p = %s \n",
6757 name.str(),currentScope,currentScope->class_name().c_str());
6758#endif
6759
6760 // DQ (8/16/2013): Changed API to support template parameters and template arguments.
6761 // symbol = cscope->lookup_symbol(name);
6762 symbol = currentScope->lookup_symbol(name,templateParameterList,templateArgumentList);
6763
6764 if (isSgAliasSymbol(symbol) != NULL)
6765 {
6766#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6767 printf ("Found a SgAliasSymbol: reset to NULL: symbol = %p = %s \n",symbol,symbol->class_name().c_str());
6768#endif
6769 symbol = NULL;
6770 }
6771
6772#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS && 1
6773 // debug
6774 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): symbol = %p \n",symbol);
6775 currentScope->print_symboltable("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): debug");
6776#endif
6777 if (currentScope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6778 currentScope = isSgGlobal(currentScope) ? NULL : currentScope->get_scope();
6779 else
6780 currentScope = NULL;
6781
6782#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6783 printf (" --- In SageInterface:: (base of loop) lookupSymbolInParentScopesIgnoringAliasSymbols(): cscope = %p symbol = %p \n\n",currentScope,symbol);
6784#endif
6785 }
6786
6787 if (symbol == NULL)
6788 {
6789#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6790 printf ("Warning: In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): could not locate the specified name %s in any outer symbol table (templateParameterList = %p templateArgumentList = %p) \n",
6791 name.str(),templateParameterList,templateArgumentList);
6792#endif
6793 // ROSE_ASSERT(false);
6794 }
6795
6796#if 0
6797 printf ("Support for lookupSymbolInParentScopesIgnoringAliasSymbols() is not yet implemented \n");
6798 ROSE_ABORT();
6799#endif
6800
6801 return symbol;
6802 }
6803
6804
6805
6806
6807
6808
6809
6810
6811#if 0
6812// DQ (7/13/2011): This was part of a merge conflict with the above modified function.
6813// It appeas they are the same so this one is commented out.
6815{
6816 SgSymbol* symbol = NULL;
6817 if (cscope == NULL)
6818 cscope = SageBuilder::topScopeStack();
6819 ROSE_ASSERT(cscope);
6820
6821 while ((cscope!=NULL)&&(symbol==NULL))
6822 {
6823 symbol = cscope->lookup_symbol(name);
6824 //debug
6825 // cscope->print_symboltable("debug sageInterface.C L3749...");
6826 if (cscope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6827 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6828 else
6829 cscope = NULL;
6830 }
6831
6832 if (symbol==NULL)
6833 {
6834 // printf ("Warning: could not locate the specified name %s in any outer symbol table \n"e,
6835 // name.str());
6836 // ROSE_ASSERT(false);
6837 }
6838 return symbol;
6839}
6840#endif
6841
6844 {
6845 // DQ (1/24/2011): This function is inconsistant with an implementation that would correctly handle SgAliasSymbols.
6846 // Also this function might get a SgClassSymbol instead of a SgVariableSymbol when both names are used.
6847 // This function needs to be fixed to handle the multi-map semantics of the symbol tables.
6848
6849#if 0
6850 // DQ (5/7/2011): I think this implementation is not correct (does not resolve past hidden types) and so should
6851 // be fixed to be consistant with the implementation of SageInterface::lookupClassSymbolInParentScopes().
6852 // Since I don't know where this function is used, I don't want to change it just yet.
6853 printf ("WARNING: SageInterface::lookupVariableSymbolInParentScopes() should be implemented similar to SageInterface::lookupClassSymbolInParentScopes() \n");
6854
6855 SgVariableSymbol* result = NULL;
6856 SgSymbol* symbol=lookupSymbolInParentScopes(name,cscope);
6857 if (symbol != NULL)
6858 {
6859 if (isSgAliasSymbol(symbol) != NULL)
6860 {
6861 printf ("Error: This SageInterface::lookupVariableSymbolInParentScopes() function does not handle SgAliasSymbols \n");
6862 ROSE_ABORT();
6863 }
6864 result = isSgVariableSymbol(symbol);
6865 }
6866 return result;
6867#else
6868 // I think this is the better implementation.
6869 SgVariableSymbol* symbol = NULL;
6870 if (cscope == NULL)
6871 cscope = SageBuilder::topScopeStack();
6872 ROSE_ASSERT(cscope != NULL);
6873
6874 while ((cscope != NULL) && (symbol == NULL))
6875 {
6876 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6877 symbol = cscope->lookup_variable_symbol(name);
6878
6879 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6880 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6881 else
6882 cscope = NULL;
6883 }
6884
6885 return symbol;
6886#endif
6887 }
6888
6889#define DEBUG_LOOKUP_TEMPLATE_VARIABLE 0
6890
6892SageInterface::lookupTemplateVariableSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList * tplparams, SgTemplateArgumentPtrList* tplargs, SgScopeStatement *cscope)
6893 {
6894#if DEBUG_LOOKUP_TEMPLATE_VARIABLE
6895 printf ("In SageInterface::lookupTemplateVariableSymbolInParentScopes():\n");
6896 printf (" -- name = %s\n", name.str());
6897 printf (" -- tplparams = %p [%zd]\n", tplparams, tplparams ? tplparams->size() : 0);
6898 printf (" -- tplargs = %p [%zd]\n", tplargs, tplargs ? tplargs->size() : 0);
6899 printf (" -- cscope = %p (%s)\n", cscope, cscope ? cscope->class_name().c_str() : "");
6900#endif
6901
6902 SgTemplateVariableSymbol* symbol = NULL;
6903 if (cscope == NULL)
6904 cscope = SageBuilder::topScopeStack();
6905 ROSE_ASSERT(cscope != NULL);
6906
6907 while ((cscope != NULL) && (symbol == NULL))
6908 {
6909 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6910 symbol = cscope->lookup_template_variable_symbol(name, tplparams, tplargs);
6911
6912 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6913 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6914 else
6915 cscope = NULL;
6916 }
6917
6918 return symbol;
6919 }
6920
6921// SgClassSymbol* SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
6923SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateArgumentPtrList* templateArgumentList)
6924 {
6925 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6926 SgClassSymbol* symbol = NULL;
6927 if (cscope == NULL)
6928 cscope = SageBuilder::topScopeStack();
6929 ROSE_ASSERT(cscope != NULL);
6930
6931 while ((cscope != NULL) && (symbol == NULL))
6932 {
6933 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6934 // symbol = cscope->lookup_class_symbol(name,NULL);
6935 symbol = cscope->lookup_class_symbol(name,templateArgumentList);
6936
6937 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6938 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6939 else
6940 cscope = NULL;
6941 }
6942
6943 return symbol;
6944 }
6945
6947SageInterface::lookupNonrealSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6948 {
6949 SgNonrealSymbol* symbol = NULL;
6950 if (cscope == NULL)
6951 cscope = SageBuilder::topScopeStack();
6952 ROSE_ASSERT(cscope != NULL);
6953
6954 while ((cscope != NULL) && (symbol == NULL))
6955 {
6956 symbol = cscope->lookup_nonreal_symbol(name,templateParameterList,templateArgumentList);
6957
6958 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6959 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6960 else
6961 cscope = NULL;
6962 }
6963
6964 return symbol;
6965 }
6966
6969 {
6970 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6971 SgTypedefSymbol* symbol = NULL;
6972 if (cscope == NULL)
6973 cscope = SageBuilder::topScopeStack();
6974 ROSE_ASSERT(cscope != NULL);
6975
6976#if 0
6977 printf ("In lookupTypedefSymbolInParentScopes(): name = %s starting with cscope = %p = %s \n",name.str(),cscope,cscope->class_name().c_str());
6978 printf ("--- parent scope = %p = %s \n",cscope->get_scope(),(cscope->get_scope() != NULL) ? cscope->get_scope()->class_name().c_str() : "null");
6979#endif
6980
6981 while ((cscope != NULL) && (symbol == NULL))
6982 {
6983 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6984 symbol = cscope->lookup_typedef_symbol(name);
6985
6986 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6987 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6988 else
6989 cscope = NULL;
6990
6991#if 0
6992 printf ("In lookupTypedefSymbolInParentScopes(): symbol = %p next cscope = %p = %s \n",symbol,cscope,(cscope != NULL) ? cscope->class_name().c_str() : "null");
6993#endif
6994 }
6995
6996#if 0
6997 printf ("Leaving lookupTypedefSymbolInParentScopes(): symbol = %p \n",symbol);
6998#endif
6999
7000 return symbol;
7001 }
7002
7003#if 0
7004// DQ (8/13/2013): This function does not make since any more, now that we have make the symbol
7005// table handling more precise and we have to provide template parameters for any template lookup.
7006// We also have to know if we want to lookup template classes, template functions, or template
7007// member functions (since each have specific requirements).
7009SageInterface::lookupTemplateSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
7010 {
7011 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7012 SgTemplateSymbol* symbol = NULL;
7013 if (cscope == NULL)
7014 cscope = SageBuilder::topScopeStack();
7015 ROSE_ASSERT(cscope != NULL);
7016
7017 while ((cscope != NULL) && (symbol == NULL))
7018 {
7019 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7020 // In this case these are unavailable from this point.
7021 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7022 // symbol = cscope->lookup_template_symbol(name);
7023 symbol = cscope->lookup_template_symbol(name,NULL,NULL);
7024#if 0
7025 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7026#endif
7027 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7028 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7029 else
7030 cscope = NULL;
7031 }
7032
7033 return symbol;
7034 }
7035#endif
7036
7037
7039SageInterface::lookupTemplateClassSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList, SgScopeStatement *cscope)
7040 {
7041 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7042 SgTemplateClassSymbol* symbol = NULL;
7043 if (cscope == NULL)
7044 cscope = SageBuilder::topScopeStack();
7045 ROSE_ASSERT(cscope != NULL);
7046
7047 while ((cscope != NULL) && (symbol == NULL))
7048 {
7049 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7050 // In this case these are unavailable from this point.
7051 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7052 // symbol = cscope->lookup_template_symbol(name);
7053 symbol = cscope->lookup_template_class_symbol(name,templateParameterList,templateArgumentList);
7054#if 0
7055 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7056#endif
7057 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7058 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7059 else
7060 cscope = NULL;
7061 }
7062
7063 return symbol;
7064 }
7065
7066
7069 {
7070 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7071 // A templated solution might make for a better implementation.
7072 SgEnumSymbol* symbol = NULL;
7073 if (cscope == NULL)
7074 cscope = SageBuilder::topScopeStack();
7075 ROSE_ASSERT(cscope != NULL);
7076
7077 while ((cscope != NULL) && (symbol == NULL))
7078 {
7079 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7080 symbol = cscope->lookup_enum_symbol(name);
7081
7082 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7083 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7084 else
7085 cscope = NULL;
7086 }
7087
7088 return symbol;
7089 }
7090
7093 {
7094 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7095 SgNamespaceSymbol* symbol = NULL;
7096 if (cscope == NULL)
7097 cscope = SageBuilder::topScopeStack();
7098 ROSE_ASSERT(cscope != NULL);
7099
7100 while ((cscope != NULL) && (symbol == NULL))
7101 {
7102 // I think this will resolve SgAliasSymbols to be a SgNamespaceSymbol where the alias is of a SgNamespaceSymbol.
7103 symbol = cscope->lookup_namespace_symbol(name);
7104
7105 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7106 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7107 else
7108 cscope = NULL;
7109 }
7110
7111 return symbol;
7112 }
7113
7114template<class T>
7115void
7116SageInterface::setSourcePositionToDefault( T* node )
7117 {
7118 // This is a templated function because SgPragma is not yet derived from SgLocatedNode.
7119
7120 // DQ (2/17/2013): This function is called a lot, so it might be a performance issue.
7121 // All IR nodes built by the Build Interface are assighed source position information
7122 // using this function and then reset afterward as we use information within EDG to
7123 // reset the source position information. Ideally, the EDG/ROSE connection would
7124 // use NULL pointers as the behavior for the front-end mode. We can move to that
7125 // later to maek the source position handling more efficient.
7126
7127 // DQ (1/24/2009): It might be that this function is only called from the Fortran support.
7128
7129 // This function sets the source position to be marked as not
7130 // available (since we often don't have token information)
7131 // These nodes WILL be unparsed in the conde generation phase.
7132
7133 // The SgLocatedNode has both a startOfConstruct and endOfConstruct source position.
7134 ROSE_ASSERT(node != NULL);
7135
7136 // We have to support this being called where the Sg_File_Info have previously been set.
7137 if (node->get_endOfConstruct() == NULL && node->get_startOfConstruct() == NULL)
7138 {
7139#if 0
7140 printf ("Both startOfConstruct and endOfConstruct are NOT yet initialized with pointers to Sg_File_Info objects (node = %p = %s) \n",node,node->class_name().c_str());
7141#endif
7142 // Check the endOfConstruct first since it is most likely NULL (helpful in debugging)
7143 ROSE_ASSERT(node->get_endOfConstruct() == NULL);
7144 ROSE_ASSERT(node->get_startOfConstruct() == NULL);
7145
7148
7149 // DQ (5/2/2012): I think we don't want to do this.
7150#if 0
7151 printf ("In SageInterface::setSourcePositionToDefault(): Calling setSourcePositionUnavailableInFrontend() \n");
7152#endif
7153 start_fileInfo->setSourcePositionUnavailableInFrontend();
7154 end_fileInfo->setSourcePositionUnavailableInFrontend();
7155
7156 // DQ (5/2/2012): I think we don't want to do this.
7157#if 0
7158 printf ("In SageInterface::setSourcePositionToDefault(): Calling setOutputInCodeGeneration() \n");
7159#endif
7160 // This is required for the unparser to output the code from the AST.
7161 start_fileInfo->setOutputInCodeGeneration();
7162 end_fileInfo->setOutputInCodeGeneration();
7163
7164 node->set_startOfConstruct(start_fileInfo);
7165 node->set_endOfConstruct (end_fileInfo);
7166
7167 node->get_startOfConstruct()->set_parent(node);
7168 node->get_endOfConstruct ()->set_parent(node);
7169 }
7170 else
7171 {
7172 // If both the starting and ending Sg_File_Info pointers are not NULL then both must be valid.
7173 // We don't want to support partially completed source code position information.
7174#if 0
7175 printf ("Both startOfConstruct and endOfConstruct are ALREADY initialized with pointers to Sg_File_Info objects (node = %p = %s) \n",node,node->class_name().c_str());
7176#endif
7177 if (node->get_startOfConstruct() == NULL)
7178 {
7179 printf ("ERROR: startOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7180 }
7181 if (node->get_endOfConstruct() == NULL)
7182 {
7183 printf ("ERROR: endOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7184 }
7185
7186 ROSE_ASSERT(node->get_startOfConstruct() != NULL);
7187 ROSE_ASSERT(node->get_endOfConstruct() != NULL);
7188 ROSE_ASSERT(node->get_endOfConstruct() != NULL && node->get_startOfConstruct() != NULL);
7189 }
7190
7191 // DQ (11/2/2012): This is an important fix to support the new EDG 4.x branch.
7192 // Note that because the unparser will use the function isFromAnotherFile() in the unparsing
7193 // of expressions, specifically: SgAggregateInitializer, SgCompoundInitializer, and anything
7194 // in their expression lists (which could be any expression). The isFromAnotherFile() will
7195 // use the get_file_info() function on the SgExpression IR nodes and the data from that
7196 // Sg_File_Info object to determine if that expression subtree should be unparsed. This
7197 // expression level granularity of unparsing capability is extremely useful in handling
7198 // now #includes and other CPP directives are woven back into the AST. But since the
7199 // get_file_info() function is used, and it returns the value of get_operatorPosition(),
7200 // it is critically important to have correct data in the SgExpression::p_operatorPosition
7201 // Sg_File_Info object (it counts more that the startOfConstruct and endOfConstruct
7202 // Sg_File_Info objects in controlling what expressions are unparsed. So we have to set these
7203 // up for all expressions (since any SgExpression could appear in the list contained in
7204 // a SgAggregateInitializer or SgCompoundInitializer.
7205
7206 // DQ (11/2/2012): Set the operator source position information to default values.
7207 // This will trigger it to be reset to valid source position information in the front-end.
7208 SgExpression* expression = isSgExpression(node);
7209 if (expression != NULL)
7210 {
7211#if 0
7212 SgBinaryOp* binaryOp = isSgBinaryOp(expression);
7213 if (binaryOp != NULL)
7214 {
7215 if (binaryOp->get_operatorPosition() == NULL)
7216 {
7218 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7219 operator_fileInfo->setOutputInCodeGeneration();
7220 binaryOp->set_operatorPosition(operator_fileInfo);
7221
7222 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7223 binaryOp->get_operatorPosition()->set_parent(binaryOp);
7224 }
7225 }
7226#else
7227 // Setup all of the SgExpression operatorPosition pointers to default objects.
7228 if (expression->get_operatorPosition() == NULL)
7229 {
7231 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7232 operator_fileInfo->setOutputInCodeGeneration();
7233 expression->set_operatorPosition(operator_fileInfo);
7234
7235 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7236 // expression->get_operatorPosition()->set_parent(expression);
7237 operator_fileInfo->set_parent(expression);
7238 ROSE_ASSERT(expression->get_operatorPosition()->get_parent() == expression);
7239 }
7240#endif
7241 }
7242 }
7243
7244
7245void
7247 {
7248 // DQ (5/1/2012): Older depricated function.
7249#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
7250 printf ("+++++ Depricated function (use setSourcePositionAsTransformation() instead) (no using internal source position mode) \n");
7251#endif
7252
7253 // setSourcePositionAsTransformation(node);
7254 setSourcePosition(node);
7255 }
7256
7257
7258void
7260 {
7261 // DQ (5/1/2012): Newer function to support specification of IR nodes being a part of a transformation.
7262
7263 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionAsTransformation(SgNode *node)"
7264 // The logic should be make more independent of if (locatedNode->get_startOfConstruct() == NULL)
7265 // Since that make understanding where the function is applied too complex.
7266 // If (locatedNode->get_startOfConstruct() != NULL), then we should just make that Sg_File_Info as
7267 // a transforamtion directly, this function misses that step.
7268
7269 ROSE_ASSERT(node != NULL);
7270
7271 // DQ (10/12/2012): Commented out since we are past AST regression tests passing and now trying to get this work checked in.
7272// printf ("In SageInterface::setSourcePositionAsTransformation() for node = %p = %s (make this an error while debugging AST construction) \n",node,node->class_name().c_str());
7273 // ROSE_ASSERT(false);
7274
7275 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7276 SgExpression* expression = isSgExpression(node);
7277 // SgInitializedName* initName = isSgInitializedName(node);
7278 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7279 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7280
7281#if 0
7282 SgVariableDefinition * v_d = isSgVariableDefinition(node);
7283 if (v_d )
7284 printf ("Debug, Found a variable definition: %p\n", v_d);
7285#endif
7286
7287 if (locatedNode != NULL)
7288 {
7290 locatedNode->get_startOfConstruct()->set_parent(locatedNode);
7291
7292 if (global==NULL)
7293 {
7295 locatedNode->get_endOfConstruct ()->set_parent(locatedNode);
7296 }
7297
7298 // Only SgExpression IR nodes have a 3rd source position data structure.
7299 if (expression!=NULL)
7300 {
7301 expression->set_operatorPosition(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7302 expression->get_operatorPosition()->set_parent(expression);
7303 }
7304 }
7305 else // special non-located node with file info
7306 {
7307 if ( (pragma != NULL) && (pragma->get_startOfConstruct() == NULL) )
7308 {
7309 pragma->set_startOfConstruct(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7310 pragma->get_startOfConstruct()->set_parent(pragma);
7311 }
7312 }
7313 }
7314
7315
7316void
7318 {
7319 // DQ (5/1/2012): Older depricated function (use setSourcePositionPointersToNull() instead).
7320#if 0
7321 printf ("+++++ Depricated name setOneSourcePositionNull() (use setSourcePositionPointersToNull() instead) (no using internal source position mode) \n");
7322#endif
7323
7324 setSourcePosition(node);
7325 }
7326
7327// DQ (5/1/2012): Newly renamed function (previous name preserved for backward compatability).
7328void
7330 {
7331 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionToNULL(SgNode *node)"
7332 // However, if this is doen then the logic should be that it asserts that: (locatedNode->get_startOfConstruct() == NULL)
7333 // so that we know when we are leaking memory. Similarly, we should assert that:
7334 // (locatedNode->get_endOfConstruct() == NULL).
7335 // But then this function just asserts that everything is already NULL and is less about setting them to NULL.
7336 // If (locatedNode->get_startOfConstruct() != NULL), should we delete the existing Sg_File_Info object?
7337 // This function misses that step.
7338
7339 ROSE_ASSERT(node != NULL);
7340
7341 SgLocatedNode * locatedNode = isSgLocatedNode(node);
7342 SgExpression* expression = isSgExpression(node);
7343 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7344 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7345
7346 // DQ (1/24/2009): If the point is to set the source position to NULL pointers,
7347 // why do we only handle the case when (get_startOfConstruct() == NULL)
7348 // (i.e. when the start source postion is already NULL).
7349
7350 if (locatedNode != NULL)
7351 {
7352 if (locatedNode->get_startOfConstruct() != NULL)
7353 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of startOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7354
7355 locatedNode->set_startOfConstruct(NULL);
7356
7357 // Note that SgGlobal should have NULL endOfConstruct()
7358 if (global == NULL)
7359 {
7360 if (locatedNode->get_endOfConstruct() != NULL)
7361 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of endOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7362
7363 locatedNode->set_endOfConstruct(NULL);
7364 }
7365
7366 // Only SgExpression IR nodes have a 3rd source position data structure.
7367 if (expression != NULL)
7368 {
7369 if (expression->get_operatorPosition() != NULL)
7370 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of operatorPosition Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7371
7372 expression->set_operatorPosition(NULL);
7373 }
7374 }
7375 else
7376 {
7377 if ( (pragma != NULL) && (pragma->get_startOfConstruct() != NULL) )
7378 {
7379 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7380
7381 pragma->set_startOfConstruct(NULL);
7382 }
7383 }
7384 }
7385
7386// DQ (1/24/2009): Could we change the name to be "setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)"
7387void
7389 {
7390#if 1
7391#if 0
7392 printf ("+++++ Depricated name setSourcePositionForTransformation() (use setSourcePositionAtRootAndAllChildrenAsTransformation() instead) \n");
7393#endif
7394
7395 // This is the semantically correct function to call.
7396 // setSourcePositionAtRootAndAllChildrenAsTransformation(root);
7397
7398 // DQ (5/2/2012): This is a test to replace the support we have to mark every thing as a transformation with the new mechanism using source position modes.
7399 // setSourcePosition(root);
7400 // Liao 11/21/2012. This function should only be called when the mode is transformation
7401 // Liao 8/2/2013. It can actually be called inside frontend by OmpSupport::lower_omp().
7402 //ROSE_ASSERT(SageBuilder::SourcePositionClassificationMode == SageBuilder::e_sourcePositionTransformation);
7404#else
7405 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7406 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7407 {
7409 }
7410#endif
7411 }
7412
7413
7414#if 0
7415// DQ (5/1/2012): New function with improved name (still preserving the previous interface).
7416void
7417SageInterface::setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)
7418 {
7419 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7420 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7421 {
7423 }
7424 }
7425#endif
7426
7427#if 0
7428void
7429SageInterface::setSourcePositionAtRootAndAllChildrenAsDefault(SgNode *root)
7430 {
7431 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7432 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7433 {
7434 setSourcePositionAsDefault(*i);
7435 }
7436 }
7437#endif
7438
7439void
7441 {
7442 // DQ (2/17/2013): This is a relatively expensive operation so we might look into this.
7443
7444 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7445
7446#if 0
7447 printf ("In setSourcePositionAtRootAndAllChildren(): nodeList.size() = %" PRIuPTR " \n",nodeList.size());
7448#endif
7449
7450 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
7451 {
7452#if 0
7453 printf ("In setSourcePositionAtRootAndAllChildren(): *i = %p = %s \n",*i,(*i)->class_name().c_str());
7454#endif
7456 }
7457 }
7458
7459// DQ (5/1/2012): This function queries the SageBuilder::SourcePositionClassification mode (stored in the SageBuilder
7460// interface) and used the specified mode to initialize the source position data (Sg_File_Info objects). This
7461// function is the only function that should be called directly (though in a namespace we can't define permissions).
7462void
7464 {
7465 // Check the mode and build the correct type of source code position.
7467
7468 // DQ (2/17/2013): Note that the SourcePositionClassification will be e_sourcePositionFrontendConstruction
7469 // during construction of the AST from the EDG frontend.
7470
7471#if 0
7472 printf ("In SageInterface::setSourcePosition(): SourcePositionClassification scp = %s \n",display(scp).c_str());
7473#endif
7474
7475 switch(scp)
7476 {
7477 case e_sourcePositionError: // Error value for enum.
7478 {
7479 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7480 ROSE_ABORT();
7481 }
7482
7483 case e_sourcePositionDefault: // Default source position.
7484 {
7485#if 0
7486 printf ("e_sourcePositionDefault in SageInterface::setSourcePosition() \n");
7487#endif
7488 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7489 if (locatedNode != NULL)
7490 {
7491 setSourcePositionToDefault(locatedNode);
7492 }
7493 else
7494 {
7495 // This is not supported (not clear if it need be).
7496 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionDefault with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7497 ROSE_ABORT();
7498 }
7499 break;
7500 }
7501
7502 case e_sourcePositionTransformation: // Classify as a transformation.
7503 {
7504#if 0
7505 printf ("e_sourcePositionTransformation in SageInterface::setSourcePosition() \n");
7506#endif
7507 // setSourcePositionAtRootAndAllChildrenAsTransformation(node);
7509 break;
7510 }
7511
7512 case e_sourcePositionCompilerGenerated: // Classify as compiler generated code (e.g. template instantiation).
7513 {
7514 printf ("e_sourcePositionCompilerGenerated in SageInterface::setSourcePosition() \n");
7515
7516 printf ("Sorry, not implemented \n");
7517 ROSE_ABORT();
7518 }
7519
7520 case e_sourcePositionNullPointers: // Set pointers to Sg_File_Info objects to NULL.
7521 {
7522 // DQ (2/17/2013): We want to move to this mode as the one used for EDG/ROSE connection so that we can
7523 // avoid building and rebuilding source position information.
7524#if 0
7525 printf ("e_sourcePositionNullPointers in SageInterface::setSourcePosition() \n");
7526#endif
7528 break;
7529 }
7530
7531 case e_sourcePositionFrontendConstruction: // Specify as source position to be filled in as part of AST construction in the front-end.
7532 {
7533 // DQ (2/17/2013): The setSourcePositionToDefault() function is called a lot, so it might be a performance issue.
7534 // All IR nodes built by the Build Interface are assighed source position information
7535 // using this function and then reset afterward as we use information within EDG to
7536 // reset the source position information. Ideally, the EDG/ROSE connection would
7537 // use NULL pointers as the behavior for the front-end mode. We can move to that
7538 // later to make the source position handling more efficient.
7539
7540 // This function builds an empty Sg_File_Info entry (valid object but filled with default values; must be reset in front-end processing).
7541#if 0
7542 printf ("e_sourcePositionFrontendConstruction in SageInterface::setSourcePosition() \n");
7543#endif
7544 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7545 if (locatedNode != NULL)
7546 {
7547 // setSourcePositionAtRootAndAllChildrenAsDefault(locatedNode);
7548 setSourcePositionToDefault(locatedNode);
7549 }
7550 else
7551 {
7552 // This is not supported (not clear if it need be).
7553 SgPragma* pragma = isSgPragma(node);
7554 if (pragma != NULL)
7555 {
7556 setSourcePositionToDefault(pragma);
7557 }
7558 else
7559 {
7560 // printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7561 // ROSE_ASSERT(false);
7562 SgType* type = isSgType(node);
7563 if (type != NULL)
7564 {
7565 // Ignore this case, OK.
7566 }
7567 else
7568 {
7569 SgFunctionParameterTypeList* functionParameterTypeList = isSgFunctionParameterTypeList(node);
7570 if (functionParameterTypeList != NULL)
7571 {
7572 // Ignore this case, OK.
7573 }
7574 else
7575 {
7576 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7577 ROSE_ABORT();
7578 }
7579 }
7580 }
7581 }
7582
7583 break;
7584 }
7585
7586
7588 {
7589 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7590 ROSE_ABORT();
7591 }
7592
7593 default:
7594 {
7595 printf ("Error: default reached in SageInterface::setSourcePosition() \n");
7596 break;
7597 }
7598 }
7599
7600#if 0
7601 if (node->get_file_info() != NULL)
7602 {
7603 node->get_file_info()->display("Leaving SageInterface::setSourcePosition()");
7604 }
7605#endif
7606 }
7607
7608#if 0
7609void
7610SageInterface::setSourcePositionForTransformation_memoryPool()
7611 {
7612 // DQ (1/24/2009): This seems like a very dangerous function to have, is it required!
7613
7614 // DQ (5/1/2012): Make it an error to call this function.
7615 printf ("ERROR: In setSourcePositionForTransformation_memoryPool(): This seems like a very dangerous function to have, is it required? \n");
7616 ROSE_ABORT();
7617
7618 VariantVector vv(V_SgNode);
7619 Rose_STL_Container<SgNode*> nodeList = NodeQuery::queryMemoryPool(vv);
7620 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++ )
7621 {
7623 }
7624 }
7625#endif
7626
7628 {
7629 // Liao, 1/9/2008, get the first global scope from current project
7630 // mostly used to prepare for AST construction under the global scope
7631 ROSE_ASSERT(project != NULL);
7632
7633 // DQ (1/24/2009): Added a check to make sure STL list is non-empty.
7634 ROSE_ASSERT(project->get_fileList().empty() == false);
7635
7636 // SgGlobal* global = project->get_file(0).get_root();
7637 SgSourceFile* file = isSgSourceFile(project->get_fileList()[0]);
7638 SgGlobal* global = file->get_globalScope();
7639
7640#if 0
7641 SgFilePtrListPtr fileList = project->get_fileList();
7642 SgFilePtrList::const_iterator i= fileList->begin();
7643
7644 SgGlobal* global = (*i)->get_globalScope();
7645#endif
7646 ROSE_ASSERT(global != NULL);
7647
7648 return global;
7649 }
7650
7651// Liao, 1/10/2008, get the last stmt from the scope
7652// two cases
7653// SgScopeStatement::getDeclarationList
7654// SgScopeStatement::getStatementList()
7656 {
7657 ROSE_ASSERT(scope);
7658 SgStatement* stmt = NULL;
7659
7660 if (scope->containsOnlyDeclarations())
7661 {
7662 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7663 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7664 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7665
7666 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7667 if (declList.empty() == false)
7668 {
7669 stmt = isSgStatement(declList.back());
7670 }
7671 }
7672 else
7673 {
7674 // DQ (2/17/2013): Fixed stmtList to be a reference instead of a copy.
7675 SgStatementPtrList & stmtList = scope->getStatementList();
7676
7677 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7678 if (stmtList.empty() == false)
7679 {
7680 stmt = stmtList.back();
7681 }
7682 }
7683
7684 return stmt;
7685 }
7686
7687
7688SgStatement* SageInterface::getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated/*=false*/)
7689 {
7690 // DQ (2/17/2013): This function appears to be a performance problem (so a pass was made to
7691 // use lower complexity operations that are equivalent in funcionality for this context).
7692
7693 ROSE_ASSERT(scope);
7694 SgStatement* stmt = NULL;
7695
7696 if (scope->containsOnlyDeclarations())
7697 {
7698 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7699 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7700 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7701 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7702 if (includingCompilerGenerated)
7703 {
7704 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7705 // DQ Note: (declList.empty() == false) is a much faster test O(1) than (declList.size() > 0), which is O(n).
7706 if (declList.empty() == false)
7707 {
7708 stmt = isSgStatement(declList.front());
7709 }
7710 }
7711 else
7712 {
7713 // skip compiler-generated declarations
7714 SgDeclarationStatementPtrList::iterator i=declList.begin();
7715 while (i != declList.end())
7716 {
7717 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7718 // some content from headers included are not marked as compiler-generated
7719 //
7720 // cout<<(*i)->unparseToString()<<endl;
7721 // ((*i)->get_file_info())->display("debug.......");
7722 Sg_File_Info * fileInfo = (*i)->get_file_info();
7723 // include transformation-generated statements, but not the hidden ones
7724 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7725 if ((fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation() && fileInfo->isOutputInCodeGeneration()))
7726 {
7727 stmt = *i;
7728 break;
7729 }
7730 else
7731 {
7732 i++;
7733 continue;
7734 }
7735 }
7736 }
7737 }
7738 else
7739 {
7740 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7741 SgStatementPtrList & stmtList = scope->getStatementList();
7742 if (includingCompilerGenerated)
7743 {
7744 // DQ (2/17/2013): Fixed evaluation of empty list use SgStatementPtrList::empty() member function for faster performance.
7745 // DQ Note: (stmtList.empty() == false) is a much faster test O(1) than (stmtList.size() > 0), which is O(n).
7746 if (stmtList.empty() == false)
7747 {
7748 stmt = stmtList.front();
7749 }
7750 }
7751 else
7752 {
7753 // skip compiler-generated declarations
7754 SgStatementPtrList::iterator i = stmtList.begin();
7755 while (i!=stmtList.end())
7756 {
7757 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7758 // some content from headers included are not marked as compiler-generated
7759 //
7760 // cout<<(*i)->unparseToString()<<endl;
7761 // ((*i)->get_file_info())->display("debug.......");
7762 Sg_File_Info * fileInfo = (*i)->get_file_info();
7763 // include transformation-generated statements, but not the hidden ones
7764 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7765 if ( (fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration()))
7766 {
7767 stmt=*i;
7768 break;
7769 }
7770 else
7771 {
7772 i++;
7773 continue;
7774 }
7775 }
7776 }
7777 }
7778
7779 return stmt;
7780 }
7781
7782
7784 {
7785 ROSE_ASSERT(scope);
7786 SgFunctionDeclaration* result = NULL;
7787 if (scope->containsOnlyDeclarations())
7788 {
7789 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7790 SgDeclarationStatementPtrList::iterator i=declList.begin();
7791 while (i!=declList.end())
7792 {
7793 Sg_File_Info * fileInfo = (*i)->get_file_info();
7794
7795 if ((fileInfo->isSameFile(scope->get_file_info()))||
7796 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7797 )
7798 {
7799 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7800 if (func)
7801 {
7802 if (func->get_definingDeclaration ()==func)
7803 {
7804 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7805 result=func;
7806 break;
7807 }
7808 }
7809 }
7810 i++;
7811 }//end while
7812 } else
7813 {
7814 SgStatementPtrList stmtList = scope->getStatementList();
7815 SgStatementPtrList::iterator i=stmtList.begin();
7816 while (i!=stmtList.end())
7817 {
7818 Sg_File_Info * fileInfo = (*i)->get_file_info();
7819 if ( (fileInfo->isSameFile(scope->get_file_info()))||
7820 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7821 )
7822 {
7823 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7824 if (func)
7825 {
7826 if (func->get_definingDeclaration ()==func)
7827 {
7828 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7829 result=func;
7830 break;
7831 }// if defining
7832 } // if func
7833 }// if fileInof
7834 i++;
7835 }//while
7836 } // end if
7837 return result;
7838 }
7839
7840
7842{
7843 bool result = false;
7844 // Liao 1/5/2010, handle Fortran main entry: SgProgramHeaderStatement
7846 if (isSgProgramHeaderStatement(n)) {
7847 result = true;
7848 }
7849 }
7850 else {
7851 if (isSgFunctionDeclaration(n) != nullptr) {
7852 bool either = false;
7854 either = true;
7855 }
7856 else {
7857 const SgStatement* stmnt = isSgStatement(n);
7858 ROSE_ASSERT(stmnt != nullptr);
7859 if (isSgGlobal(stmnt->get_scope())) {
7860 either = true;
7861 }
7862 }
7863 if (either) {
7864 const SgFunctionDeclaration* funcDefn = isSgFunctionDeclaration(n);
7865 ROSE_ASSERT(funcDefn != nullptr);
7866 if (funcDefn->get_name() == "main") {
7867 result = true;
7868 }
7869 }
7870 }
7871 }
7872 return result;
7873}
7874
7875// Originally from ompTranslator.C
7876// DQ (1/6/2007): The correct qualified name for "main" is "::main", at least in C++.
7877// however for C is should be "main". Our name qualification is not language specific,
7878// however, for C is makes no sense to as for the qualified name, so the name we
7879// want to search for could be language specific. The test code test2007_07.C
7880// demonstrates that the function "main" can exist in both classes (as member functions)
7881// and in namespaces (as more meaningfully qualified names). Because of this C++
7882// would have to qualify the global main function as "::main", I think.
7883
7884// Revised by Jeremiah,
7885// Added check to see if the scope is global: Liao
7887 if (!n) return 0;
7888 if (isMain(n))
7889 {
7890 return isSgFunctionDeclaration(n);
7891 }
7892 vector<SgNode*> children = n->get_traversalSuccessorContainer();
7893 for (vector<SgNode*>::const_iterator i = children.begin();
7894 i != children.end(); ++i) {
7895
7896 SgFunctionDeclaration* mainDecl = findMain(*i);
7897 if (mainDecl)
7898 if (mainDecl->get_definingDeclaration() == mainDecl) // skip non-defining main() declaration, Liao 8/27/2010
7899 return mainDecl;
7900 }
7901 return 0;
7902}
7903
7905// another declaration statement can be inserted.
7906// This is useful to find a safe place to insert a declaration statement with special requirements about where it can be inserted.
7907// e.g. a variable declaration statement should not be inserted before IMPLICIT none in Fortran
7908// If it returns NULL, a declaration statement should be able to be prepended to the scope
7910{
7911 SgStatement* rt = NULL;
7912 ROSE_ASSERT (scope != NULL);
7913
7914 SgStatementPtrList stmt_list = scope->generateStatementList ();
7915
7916 for (size_t i = 0; i<stmt_list.size(); i++)
7917 {
7918 SgStatement* cur_stmt = stmt_list[i];
7919 // We should exclude pragma decl. We don't want to insert things after pragmas.
7920 if (isSgDeclarationStatement(cur_stmt))
7921 {
7922 if (isSgPragmaDeclaration (cur_stmt))
7923 {
7924 if (includePragma)
7925 rt = cur_stmt;
7926 }
7927 else
7928 rt = cur_stmt;
7929 }
7930 //if (isSgImplicitStatement(cur_stmt)) || isSgFortranIncludeLine(cur_stmt) || isSgDeclarationStatement
7931 }
7932
7933 return rt;
7934}
7935
7937{
7938 SgNode* rt = NULL;
7939 SgTreeCopy g_treeCopy; // should use a copy object each time of usage!
7940 if (n!= NULL)
7941 {
7942 rt = n->copy (g_treeCopy);
7944 }
7945 // return n ? n->copy (g_treeCopy) : 0;
7946 return rt;
7947}
7948
7949// by Jeremiah
7950// Return bool for C++ code, and int for C code
7952 bool isC = TransformationSupport::getSourceFile(n)->get_outputLanguage() == SgFile::e_C_language;
7953 if (isC) {
7954 return SgTypeInt::createType();
7955 } else {
7956 return SgTypeBool::createType();
7957 }
7958}
7959
7960#if 1
7961// Change continue statements in a given block of code to gotos to a label
7963 {
7964#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
7965 std::vector<SgContinueStmt*> continues = SageInterface::findContinueStmts(stmt);
7966 for (std::vector<SgContinueStmt*>::iterator i = continues.begin(); i != continues.end(); ++i)
7967 {
7968 SgGotoStatement* gotoStatement = SageBuilder::buildGotoStatement(label);
7969 // printf ("Building gotoStatement #1 = %p \n",gotoStatement);
7970#ifndef _MSC_VER
7971 LowLevelRewrite::replace(*i, make_unit_list( gotoStatement ) );
7972#else
7973 ROSE_ABORT();
7974#endif
7975 }
7976#else
7977 printf ("Not supported in mode: ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT (LowLevelRewrite::replace() is unavailable)");
7978 ROSE_ABORT();
7979#endif
7980 }
7981
7982#define DEBUG_TEMPLATE_ARG_EQUIVALENCE 0
7983
7985 {
7986 if (arg1 == arg2)
7987 {
7988#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7989 printf ("In templateArgumentEquivalence(): same pointer to template argument: returning true \n");
7990#endif
7991 return true;
7992 }
7993
7994 if (arg1->get_argumentType() != arg2->get_argumentType())
7995 {
7996#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7997 printf ("In templateArgumentEquivalence(): different argumentType(): returning false \n");
7998#endif
7999 return false;
8000 }
8001
8002 switch (arg1->get_argumentType())
8003 {
8005 {
8006 ROSE_ASSERT(arg1->get_type() != NULL);
8007 ROSE_ASSERT(arg2->get_type() != NULL);
8008
8009#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8010 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: arg1->get_type() = %p = %s arg2->get_type() = %p = %s \n",
8011 arg1->get_type(),arg1->get_type()->class_name().c_str(),
8012 arg2->get_type(),arg2->get_type()->class_name().c_str());
8013#endif
8014 // DQ (5/19/2016): Rewrote to support debugging.
8015 // return arg1->get_type() == arg2->get_type();
8016 if (arg1->get_type() == arg2->get_type())
8017 {
8018#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8019 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: returning true \n");
8020#endif
8021 return true;
8022 }
8023 else
8024 {
8025 // ROSE_ASSERT(!"NIY: non-type template argument comparaison."); /// \todo
8026
8027 // DQ (5/19/2016): Use type equivalence mechanism to handle the case where
8028 // these are different pointers to what might still be the same type.
8029 // return false;
8030 bool typesAreEqual = isEquivalentType(arg1->get_type(),arg2->get_type());
8031
8032#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8033 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: pointers are different: returning typesAreEqual = %s \n",typesAreEqual ? "true" : "false");
8034#endif
8035 return typesAreEqual;
8036 }
8037 }
8038
8040 {
8041 SgExpression * expr1 = arg1->get_expression();
8042 SgExpression * expr2 = arg2->get_expression();
8043 if (expr1 == expr2) {
8044#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8045 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: checking for the same expression: returning true \n");
8046#endif
8047 return true;
8048 } else if (expr1->variantT() == expr2->variantT() ) {
8049#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8050 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: same variant of expression: %s\n", expr1->class_name().c_str());
8051#endif
8052 switch (expr1->variantT()) {
8053 case V_SgLongIntVal: {
8054 return ((SgLongIntVal *)expr1)->get_value() == ((SgLongIntVal *)expr2)->get_value();
8055 }
8056 // DQ (7/21/2024): Adding support for another type (from processing nlohmann/json.hpp with ROSE)
8057 case V_SgUnsignedLongVal:
8058 {
8059 return ((SgUnsignedLongVal*) expr1)->get_value() == ((SgUnsignedLongVal*) expr2)->get_value();
8060 }
8061 default: {
8062 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());
8063 ROSE_ABORT();
8064 }
8065 }
8066 } else {
8067#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8068 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: different variant of expression: returning false \n");
8069#endif
8070 return false;
8071 }
8072 }
8073
8075 {
8076 if (arg1->get_templateDeclaration() == arg2->get_templateDeclaration())
8077 {
8078#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8079 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::template_template_argument: checking for the same templateDeclaration: returning true \n");
8080#endif
8081 return true;
8082 }
8083 else
8084 {
8085 ROSE_ASSERT(!"NIY: template template argument comparaison.");
8086 }
8087 }
8088
8090 {
8091 ROSE_ASSERT(!"Try to compare template arguments of unknown type...");
8092 }
8093
8094 // DQ (7/19/2015): Added missing case:
8096 {
8097 // Liao 6/24/2016. Handle the simplest case: both arguments are parameter pack.
8099 return true;
8100 ROSE_ASSERT(!"Try to compare template arguments of unknown type start_of_pack_expansion_argument");
8101 }
8102
8103 // DQ (7/19/2015): Added missing default case: we always want to ahve a default case to catch errors and missing cases.
8104 default:
8105 {
8106 printf ("Error: default case not handled! \n");
8107 ROSE_ABORT();
8108 }
8109 }
8110
8111 ROSE_ABORT(); // unreachable code
8112 }
8113
8114#define DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE 0
8115
8116bool SageInterface::templateArgumentListEquivalence(const SgTemplateArgumentPtrList & list1, const SgTemplateArgumentPtrList & list2)
8117 {
8118 if (list1.size() != list2.size())
8119 {
8120#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8121 printf ("In templateArgumentListEquivalence(): different list sizes: returning false \n");
8122 printf (" --- list1.size() = %zu \n",list1.size());
8123 printf (" --- list2.size() = %zu \n",list2.size());
8124#endif
8125 return false;
8126 }
8127
8128 if (list1 == list2)
8129 {
8130#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8131 printf ("In templateArgumentListEquivalence(): same list using STL equality operator: returning true \n");
8132#endif
8133 return true;
8134 }
8135
8136 // for (unsigned i = 0; i < list1.size(); i++)
8137 for (size_t i = 0; i < list1.size(); i++)
8138 {
8139#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8140 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu \n",i);
8141#endif
8142 // if (!templateArgumentEquivalence(list1[i], list2[i]))
8143 if (templateArgumentEquivalence(list1[i], list2[i]) == false)
8144 {
8145#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8146 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu --- returned false: returning false \n",i);
8147#endif
8148 return false;
8149 }
8150 }
8151
8152#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8153 printf ("In templateArgumentListEquivalence(): reached base of function: returning true \n");
8154#endif
8155
8156 return true;
8157 }
8158
8159// Add a step statement to the end of a loop body
8160// Add a new label to the end of the loop, with the step statement after
8161// it; then change all continue statements in the old loop body into
8162// jumps to the label
8163//
8164// For example:
8165// while (a < 5) {if (a < -3) continue;} (adding "a++" to end) becomes
8166// while (a < 5) {if (a < -3) goto label; label: a++;}
8168 using namespace SageBuilder;
8170 SgStatement* old_body = SageInterface::getLoopBody(loopStmt);
8171 SgBasicBlock* new_body = buildBasicBlock();
8172// printf ("Building IR node #13: new SgBasicBlock = %p \n",new_body);
8173 SgName labelname = "rose_label__";
8174 labelname << ++gensym_counter;
8175 SgLabelStatement* labelstmt = buildLabelStatement(labelname,
8176buildBasicBlock(), proc);
8177 changeContinuesToGotos(old_body, labelstmt);
8178 appendStatement(old_body, new_body);
8179 appendStatement(labelstmt, new_body);
8180 appendStatement(step, new_body);
8181 SageInterface::setLoopBody(loopStmt, new_body);
8182}
8183
8184
8186 if (isSgNullExpression(f->get_increment())) return;
8187 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(f->get_increment());
8188 f->get_increment()->set_parent(incrStmt);
8191 f->set_increment(ne);
8192 ne->set_parent(f);
8193}
8194
8195static
8196bool hasEmptyCondition(SgForStatement* f)
8197{
8198 ROSE_ASSERT(f);
8199
8200 SgStatement* condstmt = f->get_test();
8201 ROSE_ASSERT(condstmt);
8202
8203 if (isSgNullStatement(condstmt)) return true;
8204
8205 SgExprStatement* exprStmt = isSgExprStatement(condstmt);
8206
8207 return isSgNullExpression(exprStmt->get_expression());
8208}
8209
8214 SgStatementPtrList& bbStmts = bb->get_statements();
8215 SgStatementPtrList& initStmts = inits->get_init_stmt();
8216 bbStmts = initStmts;
8217 for (size_t i = 0; i < bbStmts.size(); ++i) {
8218 bbStmts[i]->set_parent(bb);
8219 }
8220
8221 const bool testIsNull = hasEmptyCondition(f);
8223 : f->get_test();
8225
8226 appendStatement(ws, bb);
8227 isSgStatement(f->get_parent())->replace_statement(f, bb);
8228}
8229
8231 Rose_STL_Container<SgNode*> fors = NodeQuery::querySubTree(top,
8232V_SgForStatement);
8233 for (size_t i = 0; i < fors.size(); ++i) {
8234 convertForToWhile(isSgForStatement(fors[i]));
8235 }
8236}
8237
8238 vector<SgGotoStatement*> SageInterface::findGotoStmts(SgStatement* scope, SgLabelStatement* l) {
8239 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8240 // But we still need the copy since the return type is IR node specific.
8241 Rose_STL_Container<SgNode*> allGotos = NodeQuery::querySubTree(scope, V_SgGotoStatement);
8242
8243 vector<SgGotoStatement*> result;
8244 for (Rose_STL_Container<SgNode*>::const_iterator i = allGotos.begin(); i != allGotos.end(); ++i) {
8245 if (isSgGotoStatement(*i)->get_label() == l) {
8246 result.push_back(isSgGotoStatement(*i));
8247 }
8248 }
8249 return result;
8250 }
8251
8252#if 0 // Liao 5/21/2010. This is a bad function in terms of performance
8253 // vectors are created/destroyed multiple times
8254 vector<SgReturnStmt*> SageInterface::findReturnStmts(SgStatement* scope) {
8255 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8256 // But we still need the copy since the return type is IR node specific.
8257 Rose_STL_Container<SgNode*> returns = NodeQuery::querySubTree(scope, V_SgReturnStmt);
8258
8259 vector<SgReturnStmt*> result;
8260 for (Rose_STL_Container<SgNode*>::const_iterator i = returns.begin(); i != returns.end(); ++i) {
8261 result.push_back(isSgReturnStmt(*i));
8262 }
8263 return result;
8264 }
8265
8266#endif
8267static void getSwitchCasesHelper(SgStatement* top, vector<SgStatement*>& result) {
8268 ROSE_ASSERT (top);
8269 if (isSgSwitchStatement(top)) return; // Don't descend into nested switches
8270 if (isSgCaseOptionStmt(top) || isSgDefaultOptionStmt(top)) {
8271 result.push_back(top);
8272 }
8273 vector<SgNode*> children = top->get_traversalSuccessorContainer();
8274 for (unsigned int i = 0; i < children.size(); ++i) {
8275 if (isSgStatement(children[i])) {
8276 getSwitchCasesHelper(isSgStatement(children[i]), result);
8277 }
8278 }
8279 }
8280
8282 vector<SgStatement*> result;
8283 getSwitchCasesHelper(sw->get_body(), result);
8284 return result;
8285 }
8286
8287
8288#endif
8289
8296SgScopeStatement* SageInterface::getEnclosingScope(SgNode* n, const bool includingSelf/* =false*/)
8297{
8298 SgScopeStatement* result = getScope (n);
8299 if (result == n)
8300 {
8301 if (!includingSelf)
8302 result = getScope(n->get_parent());
8303 }
8304 return result;
8305}
8306
8307// from transformationSupport.C
8310 {
8311
8312 // Case 1: directly call get_scope() for some types of nodes
8313 if (const SgSymbol* symbol = isSgSymbol(astNode))
8314 return symbol->get_scope();
8315 else if (const SgInitializedName* initName = isSgInitializedName(astNode))
8316 return initName->get_scope();
8317 else if (const SgTemplateArgument* tempArg = isSgTemplateArgument(astNode))
8318 return tempArg->get_scope();
8319 else if (const SgQualifiedName* qualifiedName = isSgQualifiedName(astNode))
8320 return qualifiedName->get_scope();
8321
8322 // DQ (6/9/2007): This function traverses through the parents to the first scope (used for name qualification support of template arguments)
8323 const SgNode* parentNode = astNode;
8324 while (!isSgScopeStatement(parentNode))
8325 {
8326 //George Vulov (11/29/2010)
8327 //Function parameter lists are siblings of SgFunctionDefinition, so just going up to parents
8328 //produces SgGlobal.
8329 if (isSgFunctionParameterList(parentNode) || isSgCtorInitializerList(parentNode))
8330 {
8331 const SgFunctionDeclaration* funcDeclaration = isSgFunctionDeclaration(parentNode->get_parent());
8332 ROSE_ASSERT(funcDeclaration != NULL);
8333 funcDeclaration = isSgFunctionDeclaration(funcDeclaration->get_definingDeclaration());
8334 if (funcDeclaration != NULL)
8335 {
8336 return funcDeclaration->get_definition();
8337 }
8338 }
8339
8340 parentNode = parentNode->get_parent();
8341 if (parentNode == NULL)
8342 {
8343 break;
8344 }
8345 }
8346
8347 // Check to see if we made it back to the root (current root is SgProject).
8348 // It is also OK to stop at a node for which get_parent() returns NULL (SgType and SgSymbol nodes).
8349 if ( isSgScopeStatement(parentNode) == NULL &&
8350 dynamic_cast<const SgType*>(parentNode) == NULL &&
8351 dynamic_cast<const SgSymbol*>(parentNode) == NULL )
8352 {
8353 printf ("Error: In SageInterface::getScope(): could not trace back to SgScopeStatement node \n");
8354 ROSE_ABORT();
8355 }
8356 else
8357 {
8358 if ( dynamic_cast<const SgType*>(parentNode) != NULL || dynamic_cast<const SgSymbol*>(parentNode) != NULL )
8359 {
8360 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());
8361 return NULL;
8362 }
8363 }
8364
8365 // Make sure we have a SgStatement node
8366 const SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8367 //SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8368 ROSE_ASSERT (scopeStatement != NULL);
8369
8370 // ensure the search is inclusive
8371 if (isSgScopeStatement(astNode))
8372 if (isSgScopeStatement(parentNode))
8373 {
8374 ROSE_ASSERT (astNode == parentNode);
8375 }
8376
8377 // return scopeStatement;
8378 return const_cast<SgScopeStatement*>(scopeStatement);
8379 }
8380
8381
8382// from outliner, ASTtools
8383// ------------------------------------------------
8384
8392static
8393const SgVariableSymbol *
8394getVarSymFromName_const (const SgInitializedName* name)
8395 {
8396 SgVariableSymbol* v_sym = NULL;
8397
8398 if (name != NULL)
8399 {
8400#if 0
8401 printf ("In getVarSymFromName(): name->get_name() = %s \n",name->get_name().str());
8402#endif
8403 SgScopeStatement* scope = name->get_scope();
8404 ROSE_ASSERT (scope != NULL);
8405#if 0
8406 printf ("In getVarSymFromName(): name->get_name() = %s scope = %p = %s \n",name->get_name().str(),scope,scope->class_name().c_str());
8407#endif
8408 v_sym = scope->lookup_var_symbol (name->get_name());
8409
8410 if (!v_sym) // E.g., might be part of an 'extern' declaration.
8411 {
8412 // Try the declaration's scope.
8413 SgDeclarationStatement* decl = name->get_declaration ();
8414 ROSE_ASSERT (decl);
8415
8416 SgScopeStatement* decl_scope = decl->get_scope ();
8417 if (decl_scope != NULL)
8418 v_sym = decl_scope->lookup_var_symbol (name->get_name());
8419
8420 if (!v_sym)
8421 cerr << "\t\t*** WARNING: Can't seem to find a symbol for '"
8422 << name->get_name ().str ()
8423 << "' ***" << endl;
8424 }
8425 }
8426
8427 return v_sym;
8428 }
8429
8430#if 0
8438static
8440getVarSymFromName (SgInitializedName* name)
8441{
8442 const SgVariableSymbol* v_sym = getVarSymFromName_const (name);
8443 return const_cast<SgVariableSymbol *> (v_sym);
8444}
8445#endif
8450static
8451const SgVariableSymbol *
8452getVarSym_const (const SgNode* n)
8453{
8454 const SgVariableSymbol* v_sym = 0;
8455 switch (n->variantT ())
8456 {
8457 case V_SgVarRefExp:
8458 v_sym = isSgVarRefExp (n)->get_symbol ();
8459 break;
8460 case V_SgInitializedName:
8461 v_sym = getVarSymFromName_const (isSgInitializedName (n));
8462 break;
8463 default:
8464 break;
8465 }
8466 return v_sym;
8467}
8468
8469#if 0
8474static
8476getVarSym (SgNode* n)
8477{
8478 const SgVariableSymbol* v_sym = getVarSym_const (n);
8479 return const_cast<SgVariableSymbol *> (v_sym);
8480}
8481#endif
8482
8483static
8484const SgVariableSymbol *
8485getFirstVarSym_const (const SgVariableDeclaration* decl)
8486{
8487 if (!decl) return 0;
8488 const SgInitializedNamePtrList& names = decl->get_variables ();
8489 if (names.begin () != names.end ())
8490 {
8491 const SgInitializedName* name = *(names.begin ());
8492 return getVarSym_const (name);
8493 }
8494 else
8495 return 0;
8496}
8497
8500{
8501 const SgVariableSymbol* sym = getFirstVarSym_const (decl);
8502 return const_cast<SgVariableSymbol *> (sym);
8503}
8504
8505
8508{
8509 ROSE_ASSERT(decl);
8510 SgInitializedNamePtrList& names = decl->get_variables ();
8511 if (names.begin () != names.end ())
8512 return *(names.begin ());
8513 else
8514 return NULL;
8515}
8516
8517
8518static void findBreakStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgBreakStmt*>& breakStmts) {
8519 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code) || isSgSwitchStatement(code)) {
8520 if (fortranLabel == "") {
8521 // Outermost loop only
8522 return;
8523 } else {
8524 // Set this for query on children
8525 inOutermostBody = false;
8526 }
8527 }
8528 if (isSgBreakStmt(code)) {
8529 SgBreakStmt* bs = isSgBreakStmt(code);
8530 bool breakMatchesThisConstruct = false;
8531 if (bs->get_do_string_label() == "") {
8532 // Break matches closest construct
8533 breakMatchesThisConstruct = inOutermostBody;
8534 } else {
8535 breakMatchesThisConstruct = (fortranLabel == bs->get_do_string_label());
8536 }
8537 if (breakMatchesThisConstruct) {
8538 breakStmts.push_back(bs);
8539 }
8540 return;
8541 }
8542 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8543 for (unsigned int i = 0; i < children.size(); ++i) {
8544 if (isSgStatement(children[i])) {
8545 findBreakStmtsHelper(isSgStatement(children[i]), fortranLabel, inOutermostBody, breakStmts);
8546 }
8547 }
8548}
8549
8550vector<SgBreakStmt*> SageInterface::findBreakStmts(SgStatement* code, const std::string& fortranLabel) {
8551 // Run this on the body of a loop or switch, because it stops at any
8552 // construct which defines a new scope for break statements
8553 vector<SgBreakStmt*> result;
8554 findBreakStmtsHelper(code, fortranLabel, true, result);
8555 return result;
8556}
8557
8558
8559static void findContinueStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgContinueStmt*>& continueStmts) {
8560 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code)) {
8561 if (fortranLabel == "") {
8562 // Outermost loop only
8563 return;
8564 } else {
8565 // Set this for query on children
8566 inOutermostBody = false;
8567 }
8568 }
8569 if (isSgContinueStmt(code)) {
8570 SgContinueStmt* cs = isSgContinueStmt(code);
8571 bool continueMatchesThisConstruct = false;
8572 if (cs->get_do_string_label() == "") {
8573 // Continue matches closest construct
8574 continueMatchesThisConstruct = inOutermostBody;
8575 } else {
8576 continueMatchesThisConstruct = (fortranLabel == cs->get_do_string_label());
8577 }
8578 if (continueMatchesThisConstruct) {
8579 continueStmts.push_back(cs);
8580 }
8581 return;
8582 }
8583 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8584 for (unsigned int i = 0; i < children.size(); ++i) {
8585 SgStatement* stmnt = isSgStatement(children[i]);
8586 if (stmnt != NULL) {
8587 findContinueStmtsHelper(stmnt, fortranLabel, inOutermostBody, continueStmts);
8588 }
8589 }
8590}
8591
8592vector<SgContinueStmt*> SageInterface::findContinueStmts(SgStatement* code, const std::string& fortranLabel) {
8593 // Run this on the body of a loop, because it stops at any construct which
8594 // defines a new scope for continue statements
8595 vector<SgContinueStmt*> result;
8596 findContinueStmtsHelper(code, fortranLabel, true, result);
8597 return result;
8598}
8599
8600
8601// Get the initializer containing an expression if it is within an
8602// initializer.
8603// from replaceExpressionWithStatement.C
8605 assert(n);
8606#if 0
8607 std::cout << "Starting getInitializerOfExpression on 0x" << std::hex << (int)n << ", which has type " << n->sage_class_name() << std::endl;
8608#endif
8609 while (!isSgInitializer(n)) {
8610 n = isSgExpression(n->get_parent());
8611#if 0
8612 std::cout << "Continuing getInitializerOfExpression on 0x" << std::hex << (int)n;
8613 if (n) std::cout << ", which has type " << n->sage_class_name();
8614 std::cout << std::endl;
8615#endif
8616 assert(n);
8617 }
8618 return isSgInitializer(n);
8619}
8620
8621#ifndef USE_ROSE
8622// Get all symbols used in a given expression
8624 class GetSymbolsUsedInExpressionVisitor: public AstSimpleProcessing {
8625 public:
8626 std::vector<SgVariableSymbol*> symbols;
8627
8628 virtual void visit(SgNode* n) {
8629 if (isSgVarRefExp(n))
8630 symbols.push_back(isSgVarRefExp(n)->get_symbol());
8631 }
8632 };
8633
8634 GetSymbolsUsedInExpressionVisitor vis;
8635 vis.traverse(expr, preorder);
8636 return vis.symbols;
8637}
8638#endif
8639
8642 return getEnclosingNode<SgSourceFile>(n, includingSelf);
8643}
8644
8645
8647{
8648 return findDeclarationStatement<SgFunctionDeclaration> (root, name, scope, isDefining);
8649}
8650
8651
8653{
8654 return getEnclosingFunctionDefinition(n,includingSelf);
8655}
8656
8659 return getEnclosingNode<SgFunctionDefinition>(n, includingSelf);
8660}
8661
8662
8665 return getEnclosingNode<SgFunctionDeclaration>(astNode, includingSelf);
8666}
8667
8668// #endif
8669
8670// #ifndef USE_ROSE
8671
8672SgGlobal*
8674 // should including itself in this case
8675 return getEnclosingNode<SgGlobal>(astNode, true /*includingSelf*/);
8676}
8677
8679SageInterface::getEnclosingClassDefinition(SgNode* astNode, const bool includingSelf/* =false*/) {
8680 return getEnclosingNode<SgClassDefinition>(astNode, includingSelf);
8681}
8682
8683
8686 // DQ (1/24/2019): This might have to get the SgClassDefinition and then the SgClassDeclaration from that.
8687 // I'm having trouble making this work for a member function declared outside of the class definition.
8688 return getEnclosingNode<SgClassDeclaration>(astNode, true);
8689}
8690
8692SageInterface::getEnclosingExprListExp(SgNode* astNode, const bool includingSelf/* =false*/) {
8693 return getEnclosingNode<SgExprListExp>(astNode, includingSelf);
8694}
8695
8696bool
8698 {
8699 bool returnValue = false;
8700
8701 struct Visitor: public AstSimpleProcessing
8702 {
8703 SgExpression* expression_target;
8704 bool in_subtree;
8705 virtual void visit(SgNode* n)
8706 {
8707 if (n == expression_target)
8708 {
8709 in_subtree = true;
8710 }
8711 }
8712
8713 Visitor(SgExpression* expr) : expression_target(expr), in_subtree(false) {}
8714 };
8715
8716 Visitor traversal(exp);
8717
8718 traversal.traverse(subtree, preorder);
8719
8720 returnValue = traversal.in_subtree;
8721
8722 return returnValue;
8723 }
8724
8725
8728 {
8729 // DQ (2/7/2019): Added more general function to support extraction of the associated function declaration.
8730 // The lower level functions are more robust on the SgFunctionRefExp and SgMemberFunctionRefExp than
8731 // when called on the SgFunctionCallExp for example.
8732
8733 // SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
8734 ROSE_ASSERT (functionCallExp != NULL);
8735
8736 SgExpression* expression = functionCallExp->get_function();
8737 ROSE_ASSERT (expression != NULL);
8738
8739 SgFunctionDeclaration* returnDeclaration = NULL;
8740
8741 SgDotExp* dotExp = isSgDotExp(expression);
8742 if (dotExp != NULL)
8743 {
8744 ROSE_ASSERT (dotExp != NULL);
8745
8746 SgExpression* rhsOperand = dotExp->get_rhs_operand();
8747 ROSE_ASSERT (rhsOperand != NULL);
8748
8749 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8750
8751 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8752 if (memberFunctionRefExp != NULL)
8753 {
8754 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8755 }
8756 }
8757
8758 SgFunctionRefExp* functionReferenceExp = isSgFunctionRefExp(expression);
8759 if (functionReferenceExp != NULL)
8760 {
8761 returnDeclaration = functionReferenceExp->getAssociatedFunctionDeclaration();
8762 }
8763
8764 SgArrowExp* arrowExp = isSgArrowExp(expression);
8765 if ( arrowExp != NULL)
8766 {
8767 ROSE_ASSERT (arrowExp != NULL);
8768
8769 SgExpression* rhsOperand = arrowExp->get_rhs_operand();
8770 ROSE_ASSERT (rhsOperand != NULL);
8771
8772 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8773
8774 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8775 if (memberFunctionRefExp != NULL)
8776 {
8777 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8778 }
8779 }
8780
8781 return returnDeclaration;
8782 }
8783
8784
8785
8786std::list<SgClassType*>
8788 {
8789 // DQ (2/16/2019): This version support for data member name qualification return type chains.
8790
8791#define DEBUG_DATA_MEMBER_TYPE_CHAIN 0
8792
8793 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
8794 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
8795 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
8796
8797 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
8798
8799 std::list<SgClassType*> returnTypeChain;
8800
8801 // Internal list used to filter the class chain generated from chained SgCastExp objects to identify the subset containing an ambiguity.
8802 std::list<SgClassType*> classChain;
8803
8804 // Make sure this is at least a reference to a data or member function member.
8805 // The requirements for these functions are different, however, if they were
8806 // virtual functions it might be a more attractive design.
8807 if (varRefExp != NULL)
8808 {
8809 ROSE_ASSERT(isDataMemberReference(varRefExp) == true);
8810 }
8811 else
8812 {
8813 ROSE_ASSERT(memberFunctionRefExp != NULL);
8814 ROSE_ASSERT(isMemberFunctionMemberReference(memberFunctionRefExp) == true);
8815 }
8816
8817 SgNode* parent = refExp->get_parent();
8818 ROSE_ASSERT(parent != NULL);
8819
8820#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8821 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): parent = %p = %s \n",parent,parent->class_name().c_str());
8822#endif
8823
8824 SgArrowExp* arrowExp = isSgArrowExp(parent);
8825 SgDotExp* dotExp = isSgDotExp(parent);
8826
8827 SgBinaryOp* binaryOperator = NULL;
8828
8829 if (arrowExp != NULL)
8830 {
8831#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8832 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an arrow expression \n");
8833#endif
8834 binaryOperator = arrowExp;
8835 }
8836
8837 if (dotExp != NULL)
8838 {
8839#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8840 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an dot expression \n");
8841#endif
8842 binaryOperator = dotExp;
8843 }
8844
8845 // ROSE_ASSERT(binaryOperator != NULL);
8846 if (binaryOperator != NULL)
8847 {
8848 SgExpression* lhs = binaryOperator->get_lhs_operand();
8849 ROSE_ASSERT(lhs != NULL);
8850
8851#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8852 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs = %p = %s \n",lhs,lhs->class_name().c_str());
8853#endif
8854
8855 // Looking for a chain of SgCastExp expressions.
8856 SgExpression* temp_lhs = lhs;
8857 SgCastExp* cast = NULL;
8858 while (isSgCastExp(temp_lhs) != NULL)
8859 {
8860 cast = isSgCastExp(temp_lhs);
8861 ROSE_ASSERT(cast != NULL);
8862 temp_lhs = cast->get_operand();
8863
8864#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8865 printf ("Top of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8866#endif
8867 ROSE_ASSERT(cast->get_type() != NULL);
8868 SgClassType* classType = isSgClassType(cast->get_type());
8869 if (classType == NULL)
8870 {
8871#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8872 printf (" --- looking for base type: In SageInterface::getClassTypeChainForDataMemberReference(): classType == NULL: cast->get_type() = %p = %s \n",
8873 cast->get_type(),cast->get_type()->class_name().c_str());
8874#endif
8875 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);
8876 ROSE_ASSERT(baseType != NULL);
8877
8878#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8879 printf (" --- baseType = %p = %s name = %s \n",baseType,baseType->class_name().c_str(),get_name(baseType).c_str());
8880#endif
8881 classType = isSgClassType(baseType);
8882 }
8883 // ROSE_ASSERT(classType != NULL);
8884
8885 ROSE_ASSERT(temp_lhs != NULL);
8886
8887#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8888 printf (" --- temp_lhs = %p = %s name = %s \n",temp_lhs,temp_lhs->class_name().c_str(),get_name(temp_lhs).c_str());
8889#endif
8890
8891#if 1
8892 // DQ (1/20/2020): This (original) code works fine.
8893 // returnTypeChain.push_front(classType);
8894 if (classType != NULL)
8895 {
8896 classChain.push_front(classType);
8897 }
8898#else
8899 // DQ (1/20/2020): This (new) code works for Cxx11_tests/test2020_61.C.
8900 if (classType != NULL)
8901 {
8902 // DQ (1/20/2020): We might want to fully resolve the class types associated with this cast here directly
8903 // (see Cxx11_tests/test2020_61.C). The point is that we need a qualified name that will reflect all of
8904 // the class declarations from the temp_lhs to the declarations associated with the classType.
8905 // The steps are:
8906 // 1) Get the target class definition for the type represented by the temp_lhs.
8907 // 2) Get the source class definition for the classType.
8908 // 3) Iterate from the source class definition to the target class definition, and save the associated
8909 // types associated with the class declarations associated with the scopes visited.
8910 SgType* target_type = temp_lhs->get_type();
8911 ROSE_ASSERT(target_type != NULL);
8912 SgClassType* target_classType = isSgClassType(target_type);
8913 // ROSE_ASSERT(target_classType != NULL);
8914 if (target_classType != NULL)
8915 {
8916 SgDeclarationStatement* target_declaration = target_classType->get_declaration();
8917 ROSE_ASSERT(target_declaration != NULL);
8918 SgClassDeclaration* target_classDeclaration = isSgClassDeclaration(target_declaration);
8919 ROSE_ASSERT(target_classDeclaration != NULL);
8920 SgClassDeclaration* target_definingClassDeclaration = isSgClassDeclaration(target_classDeclaration->get_definingDeclaration());
8921 ROSE_ASSERT(target_definingClassDeclaration != NULL);
8922 SgScopeStatement* target_scope = target_definingClassDeclaration->get_definition();
8923 ROSE_ASSERT(target_scope != NULL);
8924
8925#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8926 printf ("target_classDeclaration = %p = %s name = %s target_scope = %p = %s \n",
8927 target_classDeclaration,target_classDeclaration->class_name().c_str(),target_classDeclaration->get_name().str(),target_scope,target_scope->class_name().c_str());
8928#endif
8929 SgClassType* source_classType = classType;
8930 ROSE_ASSERT(source_classType != NULL);
8931 SgDeclarationStatement* source_declaration = source_classType->get_declaration();
8932 ROSE_ASSERT(source_declaration != NULL);
8933 SgClassDeclaration* source_classDeclaration = isSgClassDeclaration(source_declaration);
8934 ROSE_ASSERT(source_classDeclaration != NULL);
8935 SgClassDeclaration* source_definingClassDeclaration = isSgClassDeclaration(source_classDeclaration->get_definingDeclaration());
8936 ROSE_ASSERT(source_definingClassDeclaration != NULL);
8937 SgScopeStatement* source_scope = source_definingClassDeclaration->get_definition();
8938 ROSE_ASSERT(source_scope != NULL);
8939
8940#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8941 printf ("source_classDeclaration = %p = %s name = %s source_scope = %p = %s \n",
8942 source_classDeclaration,source_classDeclaration->class_name().c_str(),source_classDeclaration->get_name().str(),source_scope,source_scope->class_name().c_str());
8943#endif
8944 SgScopeStatement* tmp_scope = source_scope;
8945 while (tmp_scope != NULL && tmp_scope != target_scope)
8946 {
8947#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8948 printf ("tmp_scope = %p = %s \n",tmp_scope,tmp_scope->class_name().c_str());
8949#endif
8950 SgClassDefinition* tmp_classDefinition = isSgClassDefinition(tmp_scope);
8951 ROSE_ASSERT(tmp_classDefinition != NULL);
8952 SgClassDeclaration* tmp_classDeclaration = tmp_classDefinition->get_declaration();
8953 ROSE_ASSERT(tmp_classDeclaration != NULL);
8954
8955#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8956 SgName scope_name = tmp_classDeclaration->get_name();
8957 printf ("scope_name = %s \n",scope_name.str());
8958#endif
8959 SgClassType* tmp_classType = tmp_classDeclaration->get_type();
8960 ROSE_ASSERT(tmp_classType != NULL);
8961
8962 // classChain.push_front(tmp_classDefinition);
8963 classChain.push_front(tmp_classType);
8964
8965 tmp_scope = tmp_scope->get_scope();
8966
8967 if (isSgGlobal(tmp_scope) != NULL)
8968 {
8969 tmp_scope = NULL;
8970 }
8971 }
8972 }
8973 else
8974 {
8975#if 1
8976 printf ("In loop processing cast: target_type = %p = %s \n",target_type,target_type->class_name().c_str());
8977#endif
8978 }
8979 }
8980#endif
8981
8982#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8983 printf ("Bottom of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8984#endif
8985 }
8986
8987 // 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.
8988
8989 ROSE_ASSERT(temp_lhs != NULL);
8990
8991#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8992 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
8993#endif
8994
8995 SgVarRefExp* derivedClassVarRefExp = isSgVarRefExp(temp_lhs);
8996 if (derivedClassVarRefExp != NULL)
8997 {
8998 SgVariableSymbol* derivedClassVariableSymbol = derivedClassVarRefExp->get_symbol();
8999 ROSE_ASSERT(derivedClassVariableSymbol != NULL);
9000
9001 SgName derivedClassVariableName = derivedClassVariableSymbol->get_name();
9002
9003#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9004 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): derivedClassVariableName = %s \n",derivedClassVariableName.str());
9005#endif
9006 // SgType* type = cast->get_type();
9007 SgType* type = temp_lhs->get_type();
9008 ROSE_ASSERT(type != NULL);
9009
9010#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9011 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s \n",type,type->class_name().c_str());
9012#endif
9013
9014 // SgType* stripped_type = type->stripType(SgType::STRIP_POINTER_TYPE|SgType::STRIP_ARRAY_TYPE|SgType::STRIP_REFERENCE_TYPE|SgType::STRIP_RVALUE_REFERENCE_TYPE|SgType::STRIP_MODIFIER_TYPE);
9015 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);
9016
9017#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9018 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type = %p = %s \n",stripped_type,stripped_type->class_name().c_str());
9019#endif
9020
9021 // SgClassType* classType = isSgClassType(type);
9022 SgClassType* classType = isSgClassType(stripped_type);
9023
9024 // ROSE_ASSERT(classType != NULL);
9025 if (classType != NULL)
9026 {
9027#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9028 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classType = %p = %s \n",classType,classType->class_name().c_str());
9029 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
9030 ROSE_ASSERT(classDeclaration != NULL);
9031 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classDeclaration = %p = %s name = %s \n",
9032 classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9033#endif
9034 // This is where we want the SgVarRefExp data member qualification to start.
9035 // returnType = classType;
9036 // returnTypeChain.push_front(classType);
9037 classChain.push_front(classType);
9038 }
9039 else
9040 {
9041#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9042 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type is not a SgClassType \n");
9043#endif
9044 }
9045 }
9046 else
9047 {
9048#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9049 printf ("Need to support alternative to SgVarRefExp: temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
9050#endif
9051 SgType* type = temp_lhs->get_type();
9052 ROSE_ASSERT(type != NULL);
9053
9054#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9055 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s name = %s \n",type,type->class_name().c_str(),get_name(type).c_str());
9056#endif
9057
9058 // DQ (1/3/2019): Need to strip the type to get to a possible SgClassType.
9059 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);
9060
9061#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9062 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());
9063#endif
9064 // SgClassType* classType = isSgClassType(type);
9065 SgClassType* classType = isSgClassType(stripped_type);
9066 // returnTypeChain.push_front(classType);
9067 if (classType != NULL)
9068 {
9069 classChain.push_front(classType);
9070 }
9071 }
9072
9073#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9074 printf ("classChain.size() = %zu \n",classChain.size());
9075 std::list<SgClassType*>::iterator iter = classChain.begin();
9076 while(iter != classChain.end())
9077 {
9078 printf (" --- *iter = %p = %s name = %s \n",*iter,(*iter)->class_name().c_str(),(*iter)->get_name().str());
9079
9080 iter++;
9081 }
9082#endif
9083
9084 // Test the first element in the list to see if there is an ambiguity in the associated classDefinition
9085 // for the input variable referenced SgVarRefExp).
9086
9087 // SgVariableSymbol* variableSymbol = varRefExp->get_symbol();
9088 // ROSE_ASSERT(variableSymbol != NULL);
9089 // SgName variableName = variableSymbol->get_name();
9090 SgSymbol* referenceSymbol = NULL;
9091 if (varRefExp != NULL)
9092 {
9093 ROSE_ASSERT(varRefExp != NULL);
9094 ROSE_ASSERT(memberFunctionRefExp == NULL);
9095
9096 referenceSymbol = varRefExp->get_symbol();
9097 }
9098 else
9099 {
9100 ROSE_ASSERT(varRefExp == NULL);
9101 ROSE_ASSERT(memberFunctionRefExp != NULL);
9102
9103 referenceSymbol = memberFunctionRefExp->get_symbol();
9104 }
9105 ROSE_ASSERT(referenceSymbol != NULL);
9106 SgName symbolName = referenceSymbol->get_name();
9107
9108#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9109 printf ("referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9110 printf ("symbolName = %s \n",symbolName.str());
9111#endif
9112
9113 // Generate the name without the template arguments.
9114 SgFunctionSymbol* functionSymbol = isSgFunctionSymbol(referenceSymbol);
9115 if (functionSymbol != NULL)
9116 {
9117 // 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.
9118 // SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(referenceSymbol->get_declaration());
9119 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(functionSymbol->get_declaration());
9120 if (templateInstantiationMemberFunctionDeclaration != NULL)
9121 {
9122#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9123 printf ("This is a template name, we want the name without template arguments \n");
9124 printf ("templateInstantiationMemberFunctionDeclaration = %p \n",templateInstantiationMemberFunctionDeclaration);
9125 printf ("templateInstantiationMemberFunctionDeclaration->get_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_name().str());
9126#endif
9127
9128 // DQ (2/24/2019): This is an error (calls base class function).
9129 // printf ("templateInstantiationMemberFunctionDeclaration->get_template_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_template_name().str());
9130
9131 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration =
9132 isSgTemplateMemberFunctionDeclaration(templateInstantiationMemberFunctionDeclaration->get_templateDeclaration());
9133 if (templateMemberFunctionDeclaration != NULL)
9134 {
9135#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9136 printf ("templateMemberFunctionDeclaration = %p \n",templateMemberFunctionDeclaration);
9137 printf ("templateMemberFunctionDeclaration->get_name() = %s \n",templateMemberFunctionDeclaration->get_name().str());
9138#endif
9139 // We need the template name without template arguments.
9140 symbolName = templateMemberFunctionDeclaration->get_name();
9141 }
9142 else
9143 {
9144#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9145 printf ("templateMemberFunctionDeclaration == NULL: template declaration not available from template instantiation (rare, I think) \n");
9146#endif
9147 }
9148#if 0
9149 printf ("Exiting as a test! \n");
9150 ROSE_ABORT();
9151#endif
9152 }
9153 else
9154 {
9155 // DQ (2/24/2019): This might indicate another case to handle: finding SgMemberFunctionDeclaration (but this is not a template).
9156 SgDeclarationStatement* declarationStatement = functionSymbol->get_declaration();
9157 ROSE_ASSERT(declarationStatement != NULL);
9158#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9159 printf ("functionSymbol != NULL: but declaration is not a member function: declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
9160#endif
9161 }
9162 }
9163 else
9164 {
9165 SgVariableSymbol* variableSymbol = isSgVariableSymbol(referenceSymbol);
9166 if (variableSymbol != NULL)
9167 {
9168 // Nothing to do in this case of a SgVariableSymbol.
9169 }
9170 else
9171 {
9172#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9173 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): NOTE: referenceSymbol is not a SgFunctionSymbol or SgVariableSymbol \n");
9174#endif
9175#if 1
9176 printf ("Exiting as a test! \n");
9177 ROSE_ABORT();
9178#endif
9179 }
9180
9181 }
9182
9183#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9184 printf ("symbolName = %s \n",symbolName.str());
9185#endif
9186
9187 // SgClassType* firstDetectedAmbiguity = NULL;
9188 // SgClassType* lastDetectedAmbiguity = NULL;
9189
9190 // bool nameQualificationRequired = false;
9191
9192 // std::list<SgClassType*> deleteList;
9193 std::list<SgClassType*> saveList;
9194
9195#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9196 printf ("classChain.size() = %zu \n",classChain.size());
9197#endif
9198
9199 std::list<SgClassType*>::iterator i = classChain.begin();
9200 std::list<SgClassType*>::iterator save_iter = i;
9201
9202 // 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.
9203 save_iter++;
9204
9205 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9206 bool ambiguityDetectedSoSaveWholeChain = false;
9207
9208 while(i != classChain.end())
9209 {
9210#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9211 printf ("******** TOP OF WHILE LOOP ******** \n");
9212 printf (" --- *i = %p = %s name = %s \n",*i,(*i)->class_name().c_str(),(*i)->get_name().str());
9213 printf (" --- --- referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9214#endif
9215 bool ambiguityDetected = false;
9216
9217 SgDeclarationStatement* declarationStatement = (*i)->get_declaration();
9218 ROSE_ASSERT(declarationStatement != NULL);
9219 SgDeclarationStatement* definingDeclarationStatement = declarationStatement->get_definingDeclaration();
9220 if (definingDeclarationStatement != NULL)
9221 {
9222 SgClassDeclaration* classDeclaration = isSgClassDeclaration(definingDeclarationStatement);
9223 ROSE_ASSERT(classDeclaration != NULL);
9224 SgClassDefinition* classDefinition = classDeclaration->get_definition();
9225
9226#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9227 printf (" --- classDeclaration = %p = %s name = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9228 printf (" --- classDefinition = %p = %s \n",classDefinition,classDefinition->class_name().c_str());
9229#endif
9230 // This works for any SgName and SgSymbol, so it need not be specific to variables.
9231 ambiguityDetected = classDefinition->hasAmbiguity(symbolName,referenceSymbol);
9232
9233#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9234 printf (" --- ambiguityDetected = %s \n",ambiguityDetected ? "true" : "false");
9235#endif
9236 }
9237
9238 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9239 if (ambiguityDetected == true || ambiguityDetectedSoSaveWholeChain == true)
9240 {
9241 ambiguityDetectedSoSaveWholeChain = true;
9242
9243 if (save_iter != classChain.end())
9244 {
9245#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9246 printf (" --- add to saveList: *save_iter = %p \n",*save_iter);
9247#endif
9248 saveList.push_back(*save_iter);
9249 }
9250 else
9251 {
9252#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9253 printf (" --- save_iter == classChain.end() \n");
9254#endif
9255 }
9256 }
9257
9258#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9259 printf ("******** BOTTOM OF WHILE LOOP ******** \n");
9260#endif
9261 i++;
9262
9263 // Also increment the save_iter.
9264 save_iter++;
9265 }
9266
9267 // Now build a list of class types to use in the name qualification from firstDetectedAmbiguity to lastDetectedAmbiguity (inclusive).
9268
9269#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9270 printf ("saveList.size() = %zu \n",saveList.size());
9271 std::list<SgClassType*>::iterator saveList_iterator = saveList.begin();
9272 while (saveList_iterator != saveList.end())
9273 {
9274 printf (" --- *saveList_iterator = %p = %s name = %s \n",*saveList_iterator,(*saveList_iterator)->class_name().c_str(),(*saveList_iterator)->get_name().str());
9275
9276 saveList_iterator++;
9277 }
9278#endif
9279
9280 returnTypeChain = saveList;
9281
9282 // End of branch for binaryOperator != NULL.
9283 }
9284
9285 return returnTypeChain;
9286 }
9287
9288
9289
9290bool
9292 {
9293 // DQ (2/17/2019): This may share a design in common with isDataMemberReference() below.
9294
9295#define DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE 0
9296
9297 ROSE_ASSERT(memberFunctionRefExp != NULL);
9298
9299 bool returnValue = false;
9300
9301 // 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;")
9302 SgNode* parent = memberFunctionRefExp->get_parent();
9303
9304 SgArrowExp* arrowExp = isSgArrowExp(parent);
9305 SgDotExp* dotExp = isSgDotExp(parent);
9306
9307 // I don't know that the SgAddressOfOp is as relevant for the case of SgMemberFunctionRefExp, but I think
9308 // it is because we would have to support membr pointeds to functions the same a member pointers to data.
9309 // I need some examples test codes to verify that name qualification is important in this case.
9310 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9311
9312 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9313 {
9314 // Use a SgFunctionSymbol instead of a SgMemberFunctionSymbol for generality (I hope this works).
9315 SgFunctionSymbol* symbol = memberFunctionRefExp->get_symbol();
9316 ROSE_ASSERT(symbol != NULL);
9317
9318 SgFunctionDeclaration* functionDeclaration = symbol->get_declaration();
9319 ROSE_ASSERT(functionDeclaration != NULL);
9320
9321 // Check if this is a statically declared variable.
9322 if (functionDeclaration != NULL)
9323 {
9324 bool isStatic = functionDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9325#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9326 printf ("isStatic = %s \n",isStatic ? "true" : "false");
9327#endif
9328 if (isStatic == false)
9329 {
9330 SgScopeStatement* scope = functionDeclaration->get_scope();
9331 ROSE_ASSERT(scope != NULL);
9332
9333 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9334 if (classDefinition != NULL)
9335 {
9336 returnValue = true;
9337 }
9338 }
9339 }
9340 else
9341 {
9342#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9343 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9344#endif
9345 }
9346 }
9347 else
9348 {
9349#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9350 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9351#endif
9352 }
9353
9354#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9355 printf ("Leaving SageInterface::isMemberFunctionMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9356#endif
9357
9358 return returnValue;
9359 }
9360
9361
9362
9363bool
9365 {
9366 // This function is used to support the name qualification of data member references seperate from name qualification
9367 // of variables that might be members (e.g. "X x; x.A::y;" instead of "A::y" (which is just simple name qualification)).
9368
9369 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9370
9371 // DQ (2/17/2019): I think we need to make sure this is not a static data member reference (since those are qualified
9372 // differently (not member data name qualification). Consider changing the name of this function to indicate non-static.
9373
9374#define DEBUG_IS_DATA_MEMBER_REFERENCE 0
9375
9376 ROSE_ASSERT(varRefExp != NULL);
9377
9378 bool returnValue = false;
9379
9380 // 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;")
9381 SgNode* parent = varRefExp->get_parent();
9382
9383 SgArrowExp* arrowExp = isSgArrowExp(parent);
9384 SgDotExp* dotExp = isSgDotExp(parent);
9385
9386 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9387
9388 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9389 {
9390 if (arrowExp != NULL)
9391 {
9392 // DQ (2/17/2019): Check if this is part of a sizeof operand for which is is_objectless_nonstatic_data_member_reference == true.
9393 SgNode* parentOfArrowExp = arrowExp->get_parent();
9394 ROSE_ASSERT(parentOfArrowExp != NULL);
9395 SgSizeOfOp* sizeOfOp = isSgSizeOfOp(parentOfArrowExp);
9396 if (sizeOfOp != NULL && sizeOfOp->get_is_objectless_nonstatic_data_member_reference() == true)
9397 {
9398 // This is not to be qualified using data member name qualification (it should use standard name qualification).
9399#if DEBUG_IS_DATA_MEMBER_REFERENCE
9400 printf ("In SageInterface::isDataMemberReference(): Found case of expression used in sizeof with objectless_nonstatic_data_member_reference \n");
9401#endif
9402 return false;
9403 }
9404 }
9405
9406 SgVariableSymbol* symbol = varRefExp->get_symbol();
9407 ROSE_ASSERT(symbol != NULL);
9408
9409 SgInitializedName* initializedName = symbol->get_declaration();
9410 ROSE_ASSERT(initializedName != NULL);
9411
9412 // Check if this is a statically declared variable.
9413 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(initializedName->get_parent());
9414 if (variableDeclaration != NULL)
9415 {
9416 bool isStatic = variableDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9417 if (isStatic == false)
9418 {
9419 SgScopeStatement* scope = initializedName->get_scope();
9420 ROSE_ASSERT(scope != NULL);
9421
9422 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9423 if (classDefinition != NULL)
9424 {
9425 returnValue = true;
9426 }
9427 }
9428 }
9429 else
9430 {
9431#if DEBUG_IS_DATA_MEMBER_REFERENCE
9432 printf ("In SageInterface::isDataMemberReference(): varRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9433#endif
9434 }
9435 }
9436 else
9437 {
9438#if DEBUG_IS_DATA_MEMBER_REFERENCE
9439 printf ("In SageInterface::isDataMemberReference(): varRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9440#endif
9441 }
9442
9443#if DEBUG_IS_DATA_MEMBER_REFERENCE
9444 printf ("Leaving SageInterface::isDataMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9445#endif
9446
9447 return returnValue;
9448 }
9449
9450
9451#if 0
9452bool
9454 {
9455 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9456 ROSE_ASSERT(varRefExp != NULL);
9457
9458 bool returnValue = false;
9459
9460 SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9461
9462 if (addressOfOp != NULL)
9463 {
9464 returnValue = true;
9465 }
9466
9467 return returnValue;
9468 }
9469#endif
9470
9471bool
9473 {
9474 // DQ (2/17/2019): Need to generalize this function to apply to member functions references as well.
9475
9476 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
9477 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
9478 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
9479
9480 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
9481
9482 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9483 // ROSE_ASSERT(varRefExp != NULL);
9484 ROSE_ASSERT(refExp != NULL);
9485
9486 bool returnValue = false;
9487
9488 // SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9489 SgAddressOfOp* addressOfOp = isSgAddressOfOp(refExp->get_parent());
9490
9491 if (addressOfOp != NULL)
9492 {
9493 returnValue = true;
9494 }
9495
9496 return returnValue;
9497 }
9498
9500 {
9501 // DQ (3/4/2014): This new version of this function supports both C/C++ and also Java.
9502 // If the SgJavaPackageDeclaration is noticed then the previous parent is a
9503 // SgClassDefinition and the previous previous parent is a SgClassDeclaration whose
9504 // name can be used to match the filename in the SgProject's list of files.
9505 // A better implementation usign an attribute (not in place until tomorrow) and
9506 // from the attribute the pointer to the associated file is directly available.
9507 // The later implementation is as fast as possible.
9508
9509 ROSE_ASSERT (astNode != NULL);
9510
9511 // Make sure this is not a project node (since the SgFile exists below
9512 // the project and could not be found by a traversal of the parent list)
9513 ROSE_ASSERT (isSgProject(astNode) == NULL);
9514
9515 SgNode* previous_parent = NULL;
9516 SgNode* previous_previous_parent = NULL;
9517
9518 SgNode* parent = astNode;
9519 // while ( (parent != NULL) && (isSgFile(parent) == NULL) )
9520 while ( (parent != NULL) && (isSgFile(parent) == NULL) && isSgJavaPackageDeclaration(parent) == NULL)
9521 {
9522#if 0
9523 printf ("In getEnclosingFileNode(): parent = %p = %s \n",parent,parent->class_name().c_str());
9524#endif
9525 previous_previous_parent = previous_parent;
9526 previous_parent = parent;
9527
9528 parent = parent->get_parent();
9529 }
9530
9531 if (previous_previous_parent != NULL && previous_parent != NULL && isSgJavaPackageDeclaration(parent) != NULL)
9532 {
9533 // This is for a Java program and is contained within a SgJavaPackageDeclaration
9534#if 0
9535 printf ("parent = %p = %s \n",parent,parent->class_name().c_str());
9536 printf ("previous_parent = %p = %s \n",previous_parent,previous_parent->class_name().c_str());
9537 printf ("previous_previous_parent = %p = %s \n",previous_previous_parent,previous_previous_parent->class_name().c_str());
9538#endif
9539 SgClassDeclaration* classDeclaration = isSgClassDeclaration(previous_previous_parent);
9540 if (classDeclaration != NULL)
9541 {
9542#if 0
9543 printf ("Class name = %p = %s = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9544#endif
9545 // Find the associated Java class file.
9546#if 0
9547 // DQ (3/4/2014): This is the code we want to use until we get Philippe's branch in place with the attribute.
9548 SgProject* project = TransformationSupport::getProject(parent);
9549 ROSE_ASSERT(project != NULL);
9550 SgFileList* fileList = project->get_fileList_ptr();
9551 ROSE_ASSERT(fileList != NULL);
9552 SgFilePtrList & vectorFile = fileList->get_listOfFiles();
9553#if 0
9554 printf ("Output list of files: \n");
9555#endif
9556 SgFilePtrList::iterator i = vectorFile.begin();
9557 while (i != vectorFile.end())
9558 {
9559 SgFile* file = *i;
9560 ROSE_ASSERT(file != NULL);
9561#if 0
9562 printf (" --- filename = %s \n",file->getFileName().c_str());
9563#endif
9564 string filename = file->getFileName();
9565 string filenameWithoutPath = file->get_sourceFileNameWithoutPath();
9566 string classname = classDeclaration->get_name();
9567 string matchingfilename = classname + ".java";
9568#if 0
9569 printf (" --- --- filename = %s \n",filename.c_str());
9570 printf (" --- --- filenameWithoutPath = %s \n",filenameWithoutPath.c_str());
9571 printf (" --- --- classname = %s \n",classname.c_str());
9572 printf (" --- --- matchingfilename = %s \n",matchingfilename.c_str());
9573#endif
9574 if (filenameWithoutPath == matchingfilename)
9575 {
9576#if 0
9577 printf (" return file = %p \n",file);
9578#endif
9579 return file;
9580 }
9581
9582 i++;
9583 }
9584#else
9585 // DQ (3/4/2014): This is the code we want to use when the attribute is in place (philippe's branch).
9586 AstSgNodeAttribute *attribute = (AstSgNodeAttribute *) classDeclaration->getAttribute("sourcefile");
9587
9588 // "This simpler and more efficent code requires the latest work in Java support (3/6/2014)"
9589
9590 if (attribute)
9591 {
9592 // true for all user-specified classes and false for all classes fom libraries
9593 SgSourceFile *sourcefile = isSgSourceFile(attribute->getNode());
9594 ROSE_ASSERT(sourcefile != NULL);
9595 return sourcefile;
9596 }
9597#endif
9598 }
9599 }
9600 else
9601 {
9602 // previous_parent was uninitialized to a non-null value or astNode is a SgJavaPackageDeclaration or SgFile.
9603 if (previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9604 {
9605 // The input was a SgJavaPackageDeclaration (so there is no associated SgFile).
9606 ROSE_ASSERT(isSgJavaPackageDeclaration(astNode) != NULL);
9607 return NULL;
9608 }
9609 else
9610 {
9611 if (previous_previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9612 {
9613 // The input was a SgClassDefinition (so there is no associated SgFile).
9614 ROSE_ASSERT(isSgClassDefinition(astNode) != NULL);
9615 return NULL;
9616 }
9617 else
9618 {
9619 // This could be a C/C++ file (handled below).
9620 }
9621 }
9622 }
9623
9624 // This is where we handle the C/C++ files.
9625 if (parent == nullptr)
9626 {
9627 return nullptr;
9628 }
9629 else
9630 {
9631 return isSgFile(parent);
9632 }
9633 }
9634
9636 struct FrontendSpecificTraversal : public ROSE_VisitTraversal {
9637 std::set<SgNode*> specific;
9638 std::set<SgNode*> non_specific;
9639
9640 static void recursive_collect( SgNode* node , std::set<SgNode *> & collection ) {
9641 // Stop on sinks and loops
9642 if (node == NULL || !collection.insert(node).second) return;
9643
9644 std::vector<std::pair<SgNode*, std::string> > data_members = node->returnDataMemberPointers();
9645 for (std::vector<std::pair<SgNode*, std::string> >::iterator i = data_members.begin(); i != data_members.end(); ++i) {
9646 recursive_collect(i->first, collection);
9647 }
9648 }
9649
9650 void visit (SgNode* n) {
9651 Sg_File_Info * fileInfo = n->get_file_info();
9652
9653 if (fileInfo != NULL) {
9654 if (fileInfo->isFrontendSpecific()) {
9655 specific.insert(n);
9656 recursive_collect(n, specific);
9657 } else {
9658 non_specific.insert(n);
9659 recursive_collect(n, non_specific);
9660 }
9661 } else {
9662 fileInfo = isSg_File_Info(n);
9663 if (fileInfo != NULL) {
9664 if (fileInfo->isFrontendSpecific()) {
9665 specific.insert(n);
9666 } else {
9667 non_specific.insert(n);
9668 }
9669 }
9670 }
9671 }
9672
9673 std::set<SgNode*> apply() {
9674 traverseMemoryPool();
9675
9676 std::set<SgNode*> result;
9677
9678 std::set_difference(
9679 specific.begin(), specific.end(),
9680 non_specific.begin(), non_specific.end(),
9681 std::insert_iterator<set<SgNode*> >(result, result.begin())
9682 );
9683
9684 return result;
9685 }
9686 };
9687
9688 FrontendSpecificTraversal fst;
9689 return fst.apply();
9690}
9691
9692void
9694 {
9695 // DQ (2/17/2019): Display the shared nodes in the AST for debugging.
9696
9697 class OutputSharedNodesTraversal : public SgSimpleProcessing
9698 {
9699 // This traversal collects the includes at the top of a file.
9700 public:
9701 void visit(SgNode *astNode)
9702 {
9703 ROSE_ASSERT(astNode != NULL);
9704 Sg_File_Info* file_info = astNode->get_file_info();
9705 if (file_info != NULL)
9706 {
9707 if (file_info->isShared() == true)
9708 {
9709 printf ("Found shared node: astNode = %p = %s \n",astNode,astNode->class_name().c_str());
9710 }
9711 }
9712 }
9713 };
9714
9715 OutputSharedNodesTraversal tt;
9716 tt.traverse(node,preorder);
9717 }
9718
9719
9720
9721
9722
9724 while (n && !isSgStatement(n)) n = n->get_parent();
9725 return isSgStatement(n);
9726}
9727
9728
9729
9730#if 1
9731// DQ (11/19/2020): We need to expand the use of this to cover deffered transformations of common SageInterface transformations (e.g. replaceStatement).
9732// So I need to move this out of being specific to the outliner and make it more generally data structure in the SageInterface.
9733
9734SageInterface::DeferredTransformation::DeferredTransformation()
9735 : deferredTransformationKind(e_default),
9736 statementToRemove(NULL),
9737 statementToAdd(NULL),
9738 class_definition(NULL),
9739 target_class_member(NULL),
9740 new_function_prototype(NULL),
9741 // DQ (2/28/2021): Added new data member to support deferred transformations.
9742 locationToOverwriteWithTransformation(NULL),
9743 transformationToOverwriteFirstStatementInInterval(NULL),
9744 blockOfStatementsToOutline(NULL)
9745 {
9746 // Default constructor (not particularly useful).
9747#if 0
9748 printf ("In SageInterface::DeferredTransformation default constructor called \n");
9749#endif
9750 }
9751
9752// DQ (2/28/2021): Added new data member to support deferred transformations.
9753// IntervalType statementInterval;
9754// SgStatement* locationToOverwriteWithTransformation;
9755
9756SageInterface::DeferredTransformation::DeferredTransformation(
9757 SgClassDefinition* input_class_definition,
9758 SgDeclarationStatement* input_target_class_member,
9759 SgDeclarationStatement* input_new_function_prototype)
9760 : deferredTransformationKind(e_outliner),
9761 statementToRemove(NULL),
9762 statementToAdd(NULL),
9763 class_definition(input_class_definition),
9764 target_class_member(input_target_class_member),
9765 new_function_prototype(input_new_function_prototype),
9766 // DQ (2/28/2021): Added new data member to support deferred transformations.
9767 locationToOverwriteWithTransformation(NULL),
9768 transformationToOverwriteFirstStatementInInterval(NULL),
9769 blockOfStatementsToOutline(NULL)
9770 {
9771 // This constructor is used by the outliner.
9772#if 0
9773 printf ("In SageInterface::DeferredTransformation constructor for outliner called \n");
9774#endif
9775 }
9776
9779 {
9780#if 0
9781 printf ("In SageInterface::DeferredTransformation constructor for replaceDefiningFunctionDeclarationWithFunctionPrototype called \n");
9782#endif
9783 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9784 // This constructor is used by tool_G and supports the use of the transformation represented
9785 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9787 X.deferredTransformationKind = e_replaceDefiningFunctionDeclarationWithFunctionPrototype;
9788 X.statementToRemove = functionDeclaration;
9789 X.statementToAdd = NULL;
9790 X.class_definition = NULL;
9791 X.target_class_member = NULL;
9792 X.new_function_prototype = NULL;
9793
9794 // DQ (2/28/2021): Added new data member to support deferred transformations.
9795 X.locationToOverwriteWithTransformation = NULL;
9796 X.transformationToOverwriteFirstStatementInInterval = NULL;
9797 X.blockOfStatementsToOutline = NULL;
9798
9799 return X;
9800 }
9801
9803SageInterface::DeferredTransformation::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool /*movePreprocessingInfo = false*/)
9804 {
9805#if 0
9806 printf ("In SageInterface::DeferredTransformation constructor for replaceStatement called \n");
9807#endif
9808 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9809 // This constructor is used by tool_G and supports the use of the transformation represented
9810 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9812 X.deferredTransformationKind = e_replaceStatement;
9813 X.statementToRemove = oldStmt;
9814 X.statementToAdd = newStmt;
9815 X.class_definition = NULL;
9816 X.target_class_member = NULL;
9817 X.new_function_prototype = NULL;
9818
9819 // DQ (2/28/2021): Added new data member to support deferred transformations.
9820 X.locationToOverwriteWithTransformation = NULL;
9821 X.transformationToOverwriteFirstStatementInInterval = NULL;
9822 X.blockOfStatementsToOutline = NULL;
9823
9824 return X;
9825 }
9826
9827SageInterface::DeferredTransformation::DeferredTransformation (const DeferredTransformation& X)
9828#if 0
9829 : deferredTransformationKind(X.deferredTransformationKind),
9830 statementToRemove(X.statementToRemove),
9831 statementToAdd(X.StatementToAdd),
9832 class_definition(X.class_definition),
9833 target_class_member(X.target_class_member),
9834 new_function_prototype(X.new_function_prototype),
9835 targetClasses(X.targetClasses),
9836 targetFriends(X.targetFriends)
9837 {
9838 }
9839#else
9840 {
9841#if 0
9842 printf ("In SageInterface::DeferredTransformation copy constructor called \n");
9843#endif
9844 // DQ (11/19/2020): Leverage the operator=() implementation to reduce complexity (one place to update).
9845 *this = X;
9846 }
9847#endif
9848
9850 {
9851#if 0
9852 printf ("Inside of SageInterface::DeferredTransformation::operator= (const DeferredTransformation& X) \n");
9853#endif
9854
9855#if 0
9856 // Original code.
9857 targetFriends = X.targetFriends;
9858 targetClasses = X.targetClasses;
9859#else
9860
9861 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9862 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9863 // definitions in the dynamic library file with function prototypes.
9864 transformationLabel = X.transformationLabel;
9865
9866 // New code added to support more general usage.
9867 deferredTransformationKind = X.deferredTransformationKind;
9868 statementToRemove = X.statementToRemove;
9869 statementToAdd = X.statementToAdd;
9870
9871 class_definition = X.class_definition;
9872 target_class_member = X.target_class_member;
9873 new_function_prototype = X.new_function_prototype;
9874 targetClasses = X.targetClasses;
9875 targetFriends = X.targetFriends;
9876
9877 // DQ (2/28/2021): Added new data member to support deferred transformations.
9878 statementInterval = X.statementInterval;
9879 locationToOverwriteWithTransformation = X.locationToOverwriteWithTransformation;
9880 transformationToOverwriteFirstStatementInInterval = X.transformationToOverwriteFirstStatementInInterval;
9881
9882 // DQ (3/1/2021): Added new data member to support deferred transformations.
9883 blockOfStatementsToOutline = X.blockOfStatementsToOutline;
9884#endif
9885
9886 return *this;
9887 }
9888
9893
9894std::string SageInterface::DeferredTransformation::outputDeferredTransformationKind(const TransformationKind & kind)
9895 {
9896 string returnValue = "uninitialized";
9897 switch (kind)
9898 {
9899 case e_error: returnValue = "e_error"; break;
9900 case e_default: returnValue = "e_default"; break;
9901 case e_outliner: returnValue = "e_outliner"; break;
9902 case e_replaceStatement: returnValue = "e_replaceStatement"; break;
9903 case e_removeStatement: returnValue = "e_removeStatement"; break;
9904 case e_replaceDefiningFunctionDeclarationWithFunctionPrototype: returnValue = "e_replaceDefiningFunctionDeclarationWithFunctionPrototype"; break;
9905 case e_last: returnValue = "e_last"; break;
9906 default:
9907 {
9908 printf ("Error: SageInterface::DeferredTransformation::get_deferredTransformationKind_string(): default reached \n");
9909 ROSE_ABORT();
9910 }
9911 }
9912
9913 return returnValue;
9914 }
9915
9916void SageInterface::DeferredTransformation::display ( std::string label ) const
9917 {
9918 printf ("SageInterface::DeferredTransformation::display(): label = %s \n",label.c_str());
9919
9920 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9921 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9922 // definitions in the dynamic library file with function prototypes.
9923 printf (" --- transformationLabel = %s \n",transformationLabel.c_str());
9924
9925 printf (" --- deferredTransformationKind = %s \n",outputDeferredTransformationKind(deferredTransformationKind).c_str());
9926 if (statementToRemove != NULL)
9927 {
9928 printf (" --- statementToRemove = %p = %s name = %s \n",statementToRemove,statementToRemove->class_name().c_str(),get_name(statementToRemove).c_str());
9929 }
9930 else
9931 {
9932 printf (" --- statementToRemove == NULL \n");
9933 }
9934
9935 if (statementToAdd != NULL)
9936 {
9937 printf (" --- statementToAdd = %p = %s name = %s \n",statementToAdd,statementToAdd->class_name().c_str(),get_name(statementToAdd).c_str());
9938 }
9939 else
9940 {
9941 printf (" --- statementToAdd == NULL \n");
9942 }
9943
9944 if (class_definition != NULL)
9945 {
9946 // printf (" --- class_definition = %p = %s name = %s \n",class_definition,class_definition->class_name().c_str(),get_name(class_definition).c_str());
9947 printf (" --- class_definition = %p \n",class_definition);
9948 }
9949
9950 if (target_class_member != NULL)
9951 {
9952 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());
9953 }
9954
9955 if (new_function_prototype != NULL)
9956 {
9957 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());
9958 }
9959
9960 // DQ (2/28/2021): Added new data member to support deferred transformations.
9961 if (locationToOverwriteWithTransformation != NULL)
9962 {
9963 // printf (" --- locationToOverwriteWithTransformation = %p = %s name = %s \n",locationToOverwriteWithTransformation,
9964 // locationToOverwriteWithTransformation->class_name().c_str(),get_name(locationToOverwriteWithTransformation).c_str());
9965 printf (" --- locationToOverwriteWithTransformation = %p \n",locationToOverwriteWithTransformation);
9966 }
9967
9968 // DQ (2/28/2021): Added new data member to support deferred transformations.
9969 if (transformationToOverwriteFirstStatementInInterval != NULL)
9970 {
9971 // printf (" --- transformationToOverwriteFirstStatementInInterval = %p = %s name = %s \n",transformationToOverwriteFirstStatementInInterval,
9972 // transformationToOverwriteFirstStatementInInterval->class_name().c_str(),get_name(transformationToOverwriteFirstStatementInInterval).c_str());
9973 printf (" --- transformationToOverwriteFirstStatementInInterval = %p \n",transformationToOverwriteFirstStatementInInterval);
9974 }
9975
9976 // DQ (3/1/2021): Added new data member to support deferred transformations.
9977 if (blockOfStatementsToOutline != NULL)
9978 {
9979 printf (" --- blockOfStatementsToOutline = %p \n",blockOfStatementsToOutline);
9980 }
9981
9982 printf ("targetClasses.size() = %zu \n",targetClasses.size());
9983 printf ("targetFriends.size() = %zu \n",targetFriends.size());
9984
9985 // DQ (2/28/2021): Added new data member to support deferred transformations.
9986 printf ("statementInterval.size() = %zu \n",statementInterval.size());
9987
9988 }
9989#endif
9990
9991
9992
9993
9994
9995// DQ (/20/2010): Control debugging output for SageInterface::removeStatement() function.
9996#define REMOVE_STATEMENT_DEBUG 0
9997
9999void SageInterface::removeStatement(SgStatement* targetStmt, bool autoRelocatePreprocessingInfo /*= true*/)
10000 {
10001#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
10002 // This function removes the input statement.
10003 // If there are comments and/or CPP directives then those comments and/or CPP directives will
10004 // be moved to a new SgStatement. The new SgStatement is selected using the findSurroundingStatementFromSameFile()
10005 // function and if there is not statement found then the SgGlobal IR node will be selected.
10006 // this work is tested by the tests/nonsmoke/functional/roseTests/astInterfaceTests/removeStatementCommentRelocation.C
10007 // translator and a number of input codes that represent a range of contexts which exercise different
10008 // cases in the code below.
10009
10010#ifndef _MSC_VER
10011 // This function only supports the removal of a whole statement (not an expression within a statement)
10012 ASSERT_not_null(targetStmt);
10013
10014 SgStatement * parentStatement = isSgStatement(targetStmt->get_parent());
10015
10016 // Can't assert this since SgFile is the parent of SgGlobal, and SgFile is not a statement.
10017 // Even so SgGlobal can't be removed from SgFile, but isRemovableStatement() takes a SgStatement.
10018 // ROSE_ASSERT (parentStatement != NULL);
10019
10020 bool isRemovable = (parentStatement != NULL) ? LowLevelRewrite::isRemovableStatement(targetStmt) : false;
10021
10022#if REMOVE_STATEMENT_DEBUG || 0
10023 printf ("In SageInterface::removeStatement(): parentStatement = %p = %s remove targetStatement = %p = %s (isRemovable = %s) \n",
10024 parentStatement,parentStatement->class_name().c_str(),targetStmt,targetStmt->class_name().c_str(),isRemovable ? "true" : "false");
10025#endif
10026
10027 if (isRemovable == true)
10028 {
10029 // DQ (9/19/2010): Disable this new (not completely working feature) so that I can checkin the latest UPC/UPC++ work.
10030#if 1
10031 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
10032 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
10033 // Liao 10/28/2010. Sometimes we want remove the statement with all its preprocessing information
10034 if (autoRelocatePreprocessingInfo == true)
10035 {
10036 // WE need to move up inner danglinge #endif or #if directives first.
10038 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
10039 // appear before the statment to be attached to the inserted statement (and marked
10040 // to appear before that statement).
10041 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
10042
10043
10044 if (comments != nullptr && isSgBasicBlock(targetStmt) == nullptr )
10045 {
10046 vector<int> captureList;
10047#if REMOVE_STATEMENT_DEBUG
10048 printf ("Found attached comments (removing %p = %s): comments->size() = %" PRIuPTR " \n",targetStmt,targetStmt->class_name().c_str(),comments->size());
10049#endif
10050
10051 // Liao 10/28/2010. relinking AST statements may be achieved by remove it and attach it to somewhere else.
10052 // In this case, preprocessing information sometimes should go with the statements and not be relocated to the original places.
10053 // Dan: Since this statement will be removed we have to relocate all the associated comments and CPP directives.
10054 int commentIndex = 0;
10055 AttachedPreprocessingInfoType::iterator i;
10056 for (i = comments->begin(); i != comments->end(); i++)
10057 {
10058 ROSE_ASSERT ( (*i) != NULL );
10059#if REMOVE_STATEMENT_DEBUG
10060 printf (" Attached Comment (relativePosition=%s): %s\n",
10061 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
10062 (*i)->getString().c_str());
10063 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
10064 (*i)->get_file_info()->display("comment/directive location debug");
10065#endif
10066 captureList.push_back(commentIndex);
10067 commentIndex++;
10068 }
10069
10070#if REMOVE_STATEMENT_DEBUG
10071 printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
10072#endif
10073
10074 if (captureList.empty() == false)
10075 {
10076 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
10077 // Find the surrounding statement by first looking up in the sequence of statements in this block, then down, we need another
10078 // statement from the same file. SgGlobal may be returned if nothing else is found.
10079 bool surroundingStatementPreceedsTargetStatement = false;
10080 SgStatement* surroundingStatement = findSurroundingStatementFromSameFile(targetStmt,surroundingStatementPreceedsTargetStatement);
10081
10082 if (surroundingStatement != nullptr)
10083 {
10084 // If we have identified a valid surrounding statemen, then move the comments and CPP directives to that statement.
10085#if REMOVE_STATEMENT_DEBUG
10086 printf ("In removeStatement(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10087 printf (" --- moving comments from targetStmt = %p = %s name = %s \n",targetStmt,targetStmt->class_name().c_str(),get_name(targetStmt).c_str());
10088 printf (" --- moving comments to surroundingStatement = %p = %s name = %s \n",surroundingStatement,surroundingStatement->class_name().c_str(),get_name(surroundingStatement).c_str());
10089#endif
10090 moveCommentsToNewStatement(targetStmt,captureList,surroundingStatement,surroundingStatementPreceedsTargetStatement);
10091 }
10092 }
10093 } // end if (comments)
10094 }// end if (autoRelocatePreprocessingInfo)
10095#endif // end #if 1
10096
10097 // DQ (12/1/2015): Adding support for fixup internal data struuctures that have references to statements (e.g. macro expansions).
10099
10100 parentStatement->remove_statement(targetStmt);
10101 }
10102#else
10103 printf ("Error: This is not supported within Microsoft Windows (I forget why). \n");
10104 ROSE_ABORT();
10105#endif
10106
10107#endif
10108 }
10109
10110
10111
10113void
10115 {
10116 // This function allows the modification of the input statement to trigger operations on internal
10117 // data structures that hold references to such statements. An example is the macroExpansion
10118 // data structures that have a reference to the statements that are associated with and macro expansion.
10119 // if a statement assocated with a macro expansion is removed, then the macroExpansion needs to be
10120 // updated to force all of the statements to be marked as transformed (so that the AST will be unparsed
10121 // instead of the tokens representing the macro or some partial representation of the transformed
10122 // statements and the macro call (worse).
10123
10124#if 0
10125 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10126#endif
10127
10128 SgSourceFile* sourceFile = getEnclosingSourceFile(sourceStatement);
10129
10130 // NOTE: if the statment has not yet been added to the AST then it will not return a valid pointer.
10131 // ROSE_ASSERT(sourceFile != NULL);
10132
10133#if 0
10134 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceFile = %p \n",sourceFile);
10135#endif
10136
10137 if (sourceFile != NULL)
10138 {
10139 std::map<SgStatement*,MacroExpansion*> & macroExpansionMap = sourceFile->get_macroExpansionMap();
10140
10141 if (macroExpansionMap.find(sourceStatement) != macroExpansionMap.end())
10142 {
10143 MacroExpansion* macroExpansion = macroExpansionMap[sourceStatement];
10144 ROSE_ASSERT(macroExpansion != NULL);
10145#if 0
10146 printf ("In resetInternalMapsForTargetStatement(): macroExpansion = %p = %s \n",macroExpansion,macroExpansion->macro_name.c_str());
10147#endif
10148 if (macroExpansion->isTransformed == false)
10149 {
10150 // Mark all of the statements in the macro expansion to be transformed.
10151 std::vector<SgStatement*> & associatedStatementVector = macroExpansion->associatedStatementVector;
10152
10153 for (size_t i = 0; i < associatedStatementVector.size(); i++)
10154 {
10155 // I am concerned that some of these statements might have been deleted.
10156 SgStatement* statement = associatedStatementVector[i];
10157#if 0
10158 printf ("Mark as transformation to be output: statement = %p = %s \n",statement,statement->class_name().c_str());
10159#endif
10160 // Note that any new statement might not yet have valid Sg_File_Info objects setup at this point.
10161 // Then again, now did it make it into the associatedStatementVector unless it was via memory
10162 // recycling through the mmory pool.
10163 if (statement->get_file_info() != NULL)
10164 {
10165 // Mark each of the statements as a transformation.
10166 statement->setTransformation();
10167
10168 // This is required, else the statement will not be output in the generated code.
10169 // To understand this, consider that statements in header files could be transformed,
10170 // but we would not want that to cause them to be unparse in the source file.
10171 statement->setOutputInCodeGeneration();
10172
10173 // Not clear if we should also remove the statement from the associatedStatementVector.
10174 // This would be important to do to avoid having the same location in the memory pool
10175 // be reused for another statement. Since we makr the macro expansion as transformed
10176 // we likely don't have to worry about this.
10177 }
10178 }
10179 }
10180
10181 // Mark this macro expansion as having been processed.
10182 macroExpansion->isTransformed = true;
10183 }
10184
10185 // Other data strucutes that may have to be updated include:
10186 // representativeWhitespaceStatementMap (should be required, but only effects whitespace details)
10187 // redundantlyMappedTokensToStatementMultimap (might not be required)
10188
10189 }
10190 }
10191
10192
10194void
10195SageInterface::moveCommentsToNewStatement(SgStatement* sourceStatement, const vector<int> & indexList, SgStatement* destinationStatement , bool destinationStatementProceedsSourceStatement)
10196 {
10197 AttachedPreprocessingInfoType* comments = sourceStatement->getAttachedPreprocessingInfo();
10198
10199#if REMOVE_STATEMENT_DEBUG || 0
10200 printf ("In moveCommentsToNewStatement(): destinationStatementProceedsSourceStatement = %s \n",destinationStatementProceedsSourceStatement ? "true" : "false");
10201 printf (" --- sourceStatement = %p = %s name = %s \n",sourceStatement,sourceStatement->class_name().c_str(),get_name(sourceStatement).c_str());
10202 printf (" --- destinationStatement = %p = %s name = %s \n",destinationStatement,destinationStatement->class_name().c_str(),get_name(destinationStatement).c_str());
10203#endif
10204 // Liao 2024/1/24
10205 // 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.
10206 // A solution : pcounter++ whenever a leading #if #ifdef #ifndef is encountered.
10207 // pcounter -- if #endif is countered
10208 // Normally the final pcounter ==0, if pcounter>=1, a #endif is missing somewhere. We should patch it up.
10209
10210#if REMOVE_STATEMENT_DEBUG
10211 printf ("Output the comments attached to sourceStatement: \n");
10212 printOutComments(sourceStatement);
10213 printf ("Output the comments attached to destinationStatement: \n");
10214 printOutComments(destinationStatement);
10215#endif
10216
10217 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
10218 vector<int>::const_iterator j = indexList.begin();
10219 PreprocessingInfo* prevTargetAnchorComment = NULL;
10220 while (j != indexList.end())
10221 {
10222 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
10223 ROSE_ASSERT(destinationStatement->get_file_info() != NULL);
10224#if REMOVE_STATEMENT_DEBUG || 0
10225 printf ("Attaching comments to destinationStatement = %p = %s on file = %s line %d \n",
10226 destinationStatement,destinationStatement->class_name().c_str(),
10227 destinationStatement->get_file_info()->get_filenameString().c_str(),
10228 destinationStatement->get_file_info()->get_line());
10229
10230 printf ("(*comments)[*j]->getRelativePosition() = %s \n",PreprocessingInfo::relativePositionName((*comments)[*j]->getRelativePosition()).c_str());
10231#endif
10232
10233 // Liao 2024/3/27: special handling when surrounding statement is SgGlobal
10234 // It should not be treated as either before or after the source statement we want to move comments from
10235 // SgGlobal should be treated as the enclosing scope of the source statement
10236 // The comments of the source statements should be attached to inside position of SgGlobal.
10237 // This is a variant of the before position (SgGlobal vs. source statement).
10238 // We do not treate SgGlobal as the same as if sgGlobal is preceeding source
10239 // because the comments of source statement would be attached to ::after of SgGlobal and
10240 // all comments will show up in the end of the file.
10241 // The ::inside location relies on the unparser to properly handle them later.
10242 if (destinationStatementProceedsSourceStatement == true || isSgGlobal(destinationStatement) != NULL )
10243 {
10244 // dest
10245 // src // comments to be moved up: all before positions become after position
10246 // // then append to dest's commments
10247 // adjust relative position one by one
10248 auto commentPosition = (*comments)[*j]->getRelativePosition();
10249 if (commentPosition == PreprocessingInfo::before)
10250 {
10251 // Mark comments that were before the preceeding statement to be after the preceeding statement
10252 (*comments)[*j]->setRelativePosition(PreprocessingInfo::after);
10253 }
10254 else if (commentPosition == PreprocessingInfo::after ||
10255 commentPosition == PreprocessingInfo::end_of)
10256 {
10257 // Leave position alone [Rasmussen 2023.01.09]
10258 }
10259 else
10260 {
10261 ROSE_ASSERT(false && "Comment relative position neither, before, after, nor end_of");
10262 }
10263
10264 // special handling of inside position
10265 // The surrounding statement will accept the comments. It also preceeds the source statement providing the comments.
10266 // If it is an enclosing scope statement, the comments should be attached to inside position, not before nor after.
10267 // if ( isSgGlobal(destinationStatement) || isSgBasicBlock(destinationStatement) )
10268 // Handle all SgScopeStatement variants.
10269 // We do this only for C/C++ language. Otherwise the code may break Jovial and other languages.
10271 {
10272 if (SageInterface::isAncestor(destinationStatement, sourceStatement))
10273 (*comments)[*j]->setRelativePosition(PreprocessingInfo::inside);
10274 }
10275 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10276
10277 }
10278 else // the target statement is after the source statment: we want to move comments from src to target
10279 {
10280 // src : comments : before or after (when moved to dest, it should become before)
10281 // all should be prepend to dest's first comment
10282 // dest: comments
10283 // adjust relative position one by one
10284 if ((*comments)[*j]->getRelativePosition() == PreprocessingInfo::before)
10285 {
10286 // Leave the comments marked as being before the removed statement
10287 // as before the following statement
10288 }
10289 else
10290 {
10291 // If is is not before, I hope it can only be after. Sometimes it is end_of, e.g. gitlab-issue-186.jov
10292 ASSERT_require((*comments)[*j]->getRelativePosition() == PreprocessingInfo::after||
10293 (*comments)[*j]->getRelativePosition() == PreprocessingInfo::end_of);
10294 (*comments)[*j]->setRelativePosition(PreprocessingInfo::before);
10295 }
10296 AttachedPreprocessingInfoType* targetInfoList = destinationStatement->getAttachedPreprocessingInfo();
10297 // source stmt has a list of comments c1, c2, c3
10298 // we want to keep their order and prepend to target stmt's existing comments
10299 // The solution is to define an anchor comment in target stmt
10300 // first time anchor is NULL, we prepend c1 to before the target stmt's first comment
10301 // after that, we insert after the anchor comment (previous anchor)
10302 // all anchor comments must come from source statement
10303 if (targetInfoList==NULL)
10304 {
10305 // we can just use append to the end. the same effect.
10306 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10307 }
10308 else
10309 {
10310 // target stmt has comments
10311 // first time to grab thing
10312 if( prevTargetAnchorComment==NULL)
10313 {
10314 PreprocessingInfo * origFirstTargetComment = *(targetInfoList->begin());
10315 // insert before this original first one
10316 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],origFirstTargetComment,false);
10317 }
10318 else
10319 {
10320 // now we have non null prev comment from target statement. insert after it!
10321 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],prevTargetAnchorComment ,true);
10322 }
10323 }
10324
10325 prevTargetAnchorComment = (*comments)[*j];
10326 }
10327
10328
10329 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
10330#if REMOVE_STATEMENT_DEBUG
10331 printf ("Marking entry from comments list as NULL on sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10332#endif
10333 (*comments)[*j] = nullptr;// Why do we need to make it NULL??
10334
10335 j++;
10336 }
10337
10338 // Now remove each NULL entries in the comments vector.
10339 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
10340 for (size_t n = 0; n < indexList.size(); n++)
10341 {
10342#if REMOVE_STATEMENT_DEBUG || 0
10343 printf ("Erase entry from comments list on comments->size() %" PRIuPTR " \n",comments->size());
10344#endif
10345 bool modifiedList = false;
10346 AttachedPreprocessingInfoType::iterator k = comments->begin();
10347 while (k != comments->end() && modifiedList == false)
10348 {
10349 // Only modify the list once per iteration over the captureList
10350 if (*k == nullptr)
10351 {
10352 k = comments->erase(k);
10353 modifiedList = true;
10354 continue;
10355 }
10356 else
10357 {
10358 k++;
10359 }
10360 }
10361 }
10362 }
10363
10364
10366// This function is a helper function for SageInterface::removeStatement() to handle preprocessing info.
10367// It should find a suitable destination statement to which we can move the current stmt's preprocessing info to.
10368// targetStmt of this function is the source statement to move preprocessing info first, before removing it.
10370SageInterface::findSurroundingStatementFromSameFile(SgStatement* targetStmt, bool & surroundingStatementPreceedsTargetStatement)
10371 {
10372 // Note that if the return value is SgGlobal (global scope), then surroundingStatementPreceedsTargetStatement is false, but meaningless.
10373 // This function can not return a NULL pointer.
10374
10375 ROSE_ASSERT(targetStmt != NULL);
10376
10377 SgStatement* surroundingStatement = targetStmt;
10378 int surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID; // No file id can have this value.
10379
10380#if REMOVE_STATEMENT_DEBUG || 0
10381 printf ("TOP of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10382#endif
10383
10384 std::set<SgStatement*> previousVisitedStatementSet;
10385
10386 // Only handle relocation for statements that exist in the file (at least for now while debugging).
10387 if (targetStmt->get_file_info()->get_file_id() >= 0)
10388 {
10389 surroundingStatementPreceedsTargetStatement = true;
10390
10391#if REMOVE_STATEMENT_DEBUG
10392 printf (" targetStmt->get_file_info()->get_file_id() = %d \n",targetStmt->get_file_info()->get_file_id());
10393#endif
10394#if REMOVE_STATEMENT_DEBUG
10395 printf ("Before loop: surroundingStatement = %p = %s name = %s surroundingStatement_fileId = %d \n",surroundingStatement,
10396 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str(),surroundingStatement_fileId);
10397#endif
10398 bool returningNullSurroundingStatement = false;
10399 // while (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id())
10400 while ((returningNullSurroundingStatement == false) && (surroundingStatement != NULL) && surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id() && surroundingStatement_fileId !=Sg_File_Info::TRANSFORMATION_FILE_ID)
10401 {
10402 // Start by going up in the source sequence.
10403 // This is a declaration from the wrong file so go to the next statement.
10404 // surroundingStatement = (insertBefore == true) ? getNextStatement(surroundingStatement) : getPreviousStatement(surroundingStatement);
10405 // surroundingStatement = (insertBefore == true) ? getPreviousStatement(surroundingStatement) : getNextStatement(surroundingStatement);
10406 // Liao, 12/26/2024. We should not climb out the current scope when finding the previous statement
10407 // Otherwise, preprocessingInfo may be moved from a child stmt to its parent stmt, causing errors in AST.
10408 surroundingStatement = getPreviousStatement(surroundingStatement, false);
10409
10410#if REMOVE_STATEMENT_DEBUG
10411 printf ("In loop: after getPreviousStatement(): surroundingStatement = %p = %s name = %s \n",surroundingStatement,
10412 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str());
10413#endif
10414
10415 if (surroundingStatement == NULL)
10416 {
10417 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10418#if REMOVE_STATEMENT_DEBUG
10419 printf (" surroundingStatement_fileId set to Sg_File_Info::BAD_FILE_ID \n");
10420#endif
10421 }
10422 else
10423 {
10424 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10425#if REMOVE_STATEMENT_DEBUG
10426 printf (" surroundingStatement = %p = %s surroundingStatement->get_file_info()->get_file_id() = %d \n",
10427 surroundingStatement,surroundingStatement->class_name().c_str(),surroundingStatement->get_file_info()->get_file_id());
10428#endif
10429 }
10430
10431#if REMOVE_STATEMENT_DEBUG
10432 if (surroundingStatement != NULL)
10433 {
10434 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",
10435 surroundingStatement,surroundingStatement->class_name().c_str(),
10436 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10437 surroundingStatement->get_file_info()->get_file_id(),
10438 surroundingStatement->get_file_info()->get_line());
10439 }
10440 else
10441 {
10442 printf ("surroundingStatement == NULL \n");
10443 }
10444#endif
10445
10446 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10447 if (previousVisitedStatementSet.find(surroundingStatement) != previousVisitedStatementSet.end())
10448 {
10449 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10450
10451 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10452
10453 surroundingStatement = NULL;
10454 // break;
10455 // return NULL;
10456 }
10457 else
10458 {
10459 previousVisitedStatementSet.insert(surroundingStatement);
10460 }
10461
10462 // As a last resort restart and go down in the statement sequence.
10463 if (surroundingStatement == NULL || isSgGlobal(surroundingStatement) != NULL)
10464 {
10465 // This is triggered by rose_inputloopUnrolling.C
10466#if REMOVE_STATEMENT_DEBUG
10467 printf ("We just ran off the start (top) of the file... targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
10468#endif
10469#if 0
10470 ROSE_ABORT();
10471#endif
10472 // A statement in the same file could not be identified, so this is false.
10473 surroundingStatementPreceedsTargetStatement = false;
10474
10475 // Restart by going the other direction (down in the source sequence)
10476 surroundingStatement = targetStmt;
10477 SgStatement* previousStatement = surroundingStatement;
10478 // surroundingStatement = getNextStatement(surroundingStatement);
10479 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10480
10481 std::set<SgStatement*> forwardVisitedStatementSet;
10482
10483 // while ( (surroundingStatement != NULL) && (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id()) )
10484 while ( (surroundingStatement != NULL) && (surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id()) )
10485 {
10486 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10487 if (forwardVisitedStatementSet.find(surroundingStatement) != forwardVisitedStatementSet.end())
10488 {
10489 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10490
10491 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10492
10493 surroundingStatement = NULL;
10494 break;
10495 // return NULL;
10496 }
10497 else
10498 {
10499 forwardVisitedStatementSet.insert(surroundingStatement);
10500 }
10501
10502 previousStatement = surroundingStatement;
10503 surroundingStatement = getNextStatement(surroundingStatement);
10504
10505 if (surroundingStatement == NULL)
10506 {
10507 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10508#if REMOVE_STATEMENT_DEBUG
10509 printf ("We just ran off the end (bottom) of the file... \n");
10510#endif
10511#if 0
10512 ROSE_ABORT();
10513#endif
10514 returningNullSurroundingStatement = true;
10515 }
10516 else
10517 {
10518 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10519#if REMOVE_STATEMENT_DEBUG
10520 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",
10521 surroundingStatement,surroundingStatement->class_name().c_str(),
10522 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10523 surroundingStatement->get_file_info()->get_file_id(),
10524 surroundingStatement->get_file_info()->get_line());
10525#endif
10526 }
10527 }
10528
10529 if (surroundingStatement == NULL)
10530 {
10531#if REMOVE_STATEMENT_DEBUG
10532 printf ("Resetting the surroundingStatement to the previousStatement = %p = %s \n",previousStatement,previousStatement->class_name().c_str());
10533#endif
10534 surroundingStatement = previousStatement;
10535
10536 // Check if this is the input statement we are removing (since the we have to attach comments to the global scope IR node.
10537 if (surroundingStatement == targetStmt)
10538 {
10539 // This can happen if there was only a single statement in a file and it was removed.
10540 // All associated comments would have to be relocated to the SgGlobal IR node.
10541#if REMOVE_STATEMENT_DEBUG
10542 printf ("Setting the surroundingStatement to be global scope \n");
10543#endif
10544 surroundingStatement = TransformationSupport::getGlobalScope(targetStmt);
10545 }
10546 }
10547 }
10548 }
10549
10550 ROSE_ASSERT(surroundingStatement != NULL);
10551 }
10552 else
10553 {
10554 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());
10555 surroundingStatement = NULL;
10556 }
10557
10558#if REMOVE_STATEMENT_DEBUG
10559 printf ("BOTTOM of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s surroundingStatement = %p \n",surroundingStatementPreceedsTargetStatement ? "true" : "false",surroundingStatement);
10560 if (surroundingStatement != NULL)
10561 {
10562 printf ("surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10563 }
10564#endif
10565
10566 // ROSE_ASSERT(surroundingStatement != NULL);
10567
10568 return surroundingStatement;
10569 }
10570
10571
10572#ifndef USE_ROSE
10575{
10576#if 0
10577 struct Visitor: public AstSimpleProcessing {
10578 virtual void visit(SgNode* n) {
10579 delete (n);
10580 }
10581 };
10582 Visitor().traverse(root, postorder);
10583#else
10584 deleteAST(root);
10585#endif
10586}
10587#endif
10588
10590void SageInterface::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool movePreprocessingInfoValue/* = false*/)
10591 {
10592 ROSE_ASSERT(oldStmt);
10593 ROSE_ASSERT(newStmt);
10594
10595 if (oldStmt == newStmt) return;
10596
10597 SgStatement * p = isSgStatement(oldStmt->get_parent());
10598 ROSE_ASSERT(p);
10599
10600#if 0
10601 // TODO handle replace the body of a C/Fortran function definition with a single statement?
10602 // Liao 2/1/2010, in some case, we want to replace the entire body (SgBasicBlock) for some parent nodes.
10603 // the built-in replace_statement() (insert_child() underneath) may not defined for them.
10604 if (SgFortranDo * f_do = isSgFortranDo (p))
10605 {
10606 ROSE_ASSERT (f_do->get_body() == oldStmt);
10607 if (!isSgBasicBlock(newStmt))
10608 newStmt = buildBasicBlock (newStmt);
10609 f_do->set_body(isSgBasicBlock(newStmt));
10610 newStmt->set_parent(f_do);
10611 }
10612 else
10613 {
10614 p->replace_statement(oldStmt,newStmt);
10615 }
10616#endif
10617 p->replace_statement(oldStmt,newStmt);
10618
10619#if 1
10620 // DQ (7/20/2021): Need to make the physical_file_ids match and the parents.
10621 // Acutally this may be too late in the case of a deferred transformation since
10622 // we run the AST consistancy tests as an intermediate step.
10623 int physical_file_id = oldStmt->get_startOfConstruct()->get_physical_file_id();
10624
10625#if 0
10626 printf ("In SageInterface::replaceStatement(): physical_file_id = %d \n",physical_file_id);
10627#endif
10628
10629 newStmt->get_startOfConstruct()->set_physical_file_id(physical_file_id);
10630 newStmt->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
10631
10632 // DQ (7/20/2021): Do we need this when we set the physical_file_id?
10633 newStmt->set_parent(oldStmt->get_parent());
10634#endif
10635
10636 // Some translators have their own handling for this (e.g. the outliner)
10637 if (movePreprocessingInfoValue)
10638 {
10639 // move inner dangling #endif, #if etc to newStmt's after position, otherwise they got lost
10640//A-B test here
10641 // I think we should move up old statement's inner dangling directives
10642 // later , we move directives from old statement to new statement
10644#if 0
10645 printf ("In SageInterface::replaceStatement(): calling moveUpPreprocessingInfo() changed to movePreprocessingInfo() \n");
10646#endif
10647
10648 // DQ (12/28/2020): I think this should be movePreprocessingInfo instead of moveUpPreprocessingInfo
10649 // (which has a collection of defaults that are not appropriate).
10650 // moveUpPreprocessingInfo(newStmt, oldStmt);
10651#if 1
10652 // 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).
10653 moveUpPreprocessingInfo(newStmt, oldStmt);
10654#else
10655 // void SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
10656 // PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
10657 bool usePrepend = true;
10658 // movePreprocessingInfo ( newStmt, oldStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10659 movePreprocessingInfo ( oldStmt, newStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10660#endif
10661 }
10662 }
10663
10664void
10666 {
10667 // Relocate the declaration to be explicitly represented in its associated namespace (required for some backend compilers to process template instantiations).
10668
10669 // DQ (7/19/2015): This is required to support general unparsing of template instantations for the GNU g++
10670 // compiler which does not permit name qualification to be used to support the expression of the namespace
10671 // where a template instantiatoon would be places. Such name qualification would also sometimes require
10672 // global qualification which is also not allowed by the GNU g++ compiler. These issues appear to be
10673 // specific to the GNU compiler versions, at least versions 4.4 through 4.8.
10674
10675 // Find the previous statement in this scope so that we can close off the namepsace and start a new one.
10676 SgStatement* previousDeclarationStatement = getPreviousStatement(declarationStatement);
10677 SgStatement* nextDeclarationStatement = getNextStatement(declarationStatement);
10678
10679#if 0
10680 printf ("In SageInterface::moveDeclarationToAssociatedNamespace(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
10681 printf (" --- previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement != NULL ? previousDeclarationStatement->class_name().c_str() : "null");
10682 printf (" --- nextDeclarationStatement = %p \n",nextDeclarationStatement);
10683 printf (" --- nextDeclarationStatement = %p = %s \n",nextDeclarationStatement, nextDeclarationStatement != NULL ? nextDeclarationStatement->class_name().c_str() : "null");
10684#endif
10685
10686 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10687 if (previousDeclarationStatement != NULL)
10688 {
10689 // printf ("previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement->class_name().c_str());
10690 }
10691 else
10692 {
10693 printf ("There is no previous statement so there is no namespace to close off! \n");
10694
10695 // Handle this corner case after we have the most general case working!
10696 printf ("Exiting as a test! \n");
10697 ROSE_ABORT();
10698 }
10699
10700 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10701 if (nextDeclarationStatement != NULL)
10702 {
10703 // printf ("nextDeclarationStatement = %p = %s \n",nextDeclarationStatement,nextDeclarationStatement->class_name().c_str());
10704 }
10705 else
10706 {
10707#if 0
10708 printf ("There is no next statement so there is no namespace to reopen! \n");
10709#endif
10710#if 0
10711 // Handle this corner case after we have the most general case working!
10712 printf ("Exiting as a test! \n");
10713 ROSE_ABORT();
10714#endif
10715 }
10716
10717 if (previousDeclarationStatement != NULL && nextDeclarationStatement != NULL)
10718 {
10719 // DQ (7/19/2015): This is the most common case!
10720#if 0
10721 printf ("Identified the most common case... \n");
10722#endif
10723 // Identify the associated namespace
10724 //SgScopeStatement* declarationScope = declarationStatement->get_scope();
10725#if 0
10726 printf ("declarationScope = %p = %s \n",declarationScope,declarationScope->class_name().c_str());
10727#endif
10728#if 0
10729 // Handle this corner case after we have the most general case working!
10730 printf ("Exiting as a test! \n");
10731 ROSE_ABORT();
10732#endif
10733 }
10734 else
10735 {
10736 if (previousDeclarationStatement != NULL && nextDeclarationStatement == NULL)
10737 {
10738 // This is the case for the last template instantiaton in global scope (so it too is a common case)!
10739#if 0
10740 printf ("Found 2nd most common case: previousDeclarationStatement != NULL && nextDeclarationStatement == NULL \n");
10741#endif
10742#if 0
10743 // Handle this corner case after we have the most general case working!
10744 printf ("Exiting as a test! \n");
10745 ROSE_ABORT();
10746#endif
10747 }
10748 else
10749 {
10750 if (previousDeclarationStatement == NULL && nextDeclarationStatement == NULL)
10751 {
10752 printf ("This case should require no special handling, unless we are still in the wrong namespace \n");
10753
10754 // Handle this corner case after we have the most general case working!
10755 printf ("Exiting as a test! \n");
10756 ROSE_ABORT();
10757 }
10758 else
10759 {
10760 printf ("This case should have been caught above! \n");
10761
10762 // Handle this corner case after we have the most general case working!
10763 printf ("Exiting as a test! \n");
10764 ROSE_ABORT();
10765 }
10766 }
10767 }
10768
10769 SgScopeStatement* declarationParent = isSgScopeStatement(declarationStatement->get_parent());
10770 if (declarationParent == NULL)
10771 {
10772#if 0
10773 printf ("declarationStatement->get_parent() = %p = %s \n",declarationStatement->get_parent(), (declarationStatement->get_parent() != NULL) ? declarationStatement->get_parent()->class_name().c_str() : "null");
10774#endif
10775 }
10776 // This can be a SgTemplateInstantiationDirectiveStatement (bug we want to skip over this case for now).
10777 // ROSE_ASSERT(declarationParent != NULL);
10778
10779 if (declarationParent != NULL)
10780 {
10781 SgScopeStatement* declarationScope = declarationStatement->get_scope();
10782 ROSE_ASSERT(declarationScope != NULL);
10783
10784 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(declarationScope);
10785 if (namespaceDefinition != NULL)
10786 {
10787 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
10788 ROSE_ASSERT(namespaceDeclaration != NULL);
10789#if 0
10790 printf ("The declaration has been identified to be associuated with a valid namespace = %p = %s \n",namespaceDeclaration,namespaceDeclaration->get_name().str());
10791 printf (" --- declarationParent = %p = %s \n",declarationParent,declarationParent->class_name().c_str());
10792 printf (" --- Move declaration from scope = %p = %s to namespace = %p = %s \n",declarationParent,declarationParent->class_name().c_str(),namespaceDeclaration,namespaceDeclaration->get_name().str());
10793#endif
10794#if 0
10795 printf ("Exiting as a test! \n");
10796 ROSE_ABORT();
10797#endif
10798 }
10799 else
10800 {
10801#if 0
10802 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());
10803#endif
10804 }
10805 }
10806 else
10807 {
10808#if 0
10809 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");
10810#endif
10811 // ROSE_ASSERT(declarationParent != NULL);
10812 }
10813
10814 }
10815
10816
10817bool
10819 {
10820 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10821 if (isSgTemplateInstantiationDefn(node) != NULL)
10822 {
10823#if 0
10824 printf ("Note: In SageInterface::isTemplateInstantiationNode(): skipping SgTemplateInstantiationDefn \n");
10825#endif
10826 }
10827
10828 return isSgTemplateInstantiationDecl(node)
10829 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10830// || isSgTemplateInstantiationDefn(node)
10831 || isSgTemplateInstantiationDefn(node)
10832 || isSgTemplateInstantiationFunctionDecl(node)
10833 || isSgTemplateInstantiationMemberFunctionDecl(node)
10834 || isSgTemplateInstantiationTypedefDeclaration(node)
10835 || isSgTemplateInstantiationDirectiveStatement(node)
10836 ;
10837 }
10838
10839#if 0
10840// DQ (5/23/2021): Added (uncommented, and added to the header file) function to support test for template declaration.
10841// Commented back out, since this is not required for what I am debugging currently.
10842// DQ (6/27/2018): This will be the template declaration test version of the template instantiation test function above.
10843bool
10844SageInterface::isTemplateDeclarationNode(SgNode* node)
10845 {
10846 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10847 if (isSgTemplateDefinition(node) != NULL)
10848 {
10849#if 0
10850 printf ("Note: In SageInterface::isTemplateDeclarationNode(): skipping SgTemplateDefinition \n");
10851#endif
10852 }
10853
10854 return isSgTemplateInstantiationDecl(node)
10855 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10856 // || isSgTemplateInstantiationDefn(node)
10857 || isSgTemplateInstantiationDefn(node)
10858 || isSgTemplateInstantiationFunctionDecl(node)
10859 || isSgTemplateInstantiationMemberFunctionDecl(node)
10860 || isSgTemplateInstantiationTypedefDeclaration(node)
10861 || isSgTemplateInstantiationDirectiveStatement(node)
10862 ;
10863 }
10864#endif
10865
10866void
10868 {
10869 // DQ (8/18/2015): This function is called from the tests/nonsmoke/functional/testTemplates translator.
10870
10871 // DQ (7/19/2015): This function can't use an iterator since it will be
10872 // doing transformations on the AST and will cause iterator invalidation errors.
10873
10874 std::vector<SgDeclarationStatement*> templateInstantiationVector;
10875
10876 // DQ (9/24/2015): This feature is not available yet in CMake (Markus is adding the library support for this feature).
10877#ifndef USE_CMAKEx
10878 RoseAst ast(root);
10879
10880 for (RoseAst::iterator i= ast.begin(); i!= ast.end(); ++i)
10881 {
10883 {
10884 // markNodeToBeUnparsed(*i);
10885 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
10886 if (declaration != NULL)
10887 {
10888 templateInstantiationVector.push_back(declaration);
10889 }
10890 else
10891 {
10892 // I think it is OK that not all are a SgDeclarationStatement.
10893 }
10894 }
10895 }
10896#else
10897 std::cerr << "This feature for now is available with autotools only!" << std::endl;
10898 ROSE_ABORT();
10899#endif
10900
10901 std::vector<SgDeclarationStatement*>::iterator j = templateInstantiationVector.begin();
10902 while (j != templateInstantiationVector.end())
10903 {
10905 j++;
10906 }
10907 }
10908
10909
10910
10912// All SgVariantExpression in the pattern will be replaced with copies of the anchor node.
10914{
10915 SgExpression * anchor_exp = isSgExpression(anchor);
10916 SgExpression * pattern_exp = isSgExpression(new_pattern);
10917 ROSE_ASSERT (anchor_exp != NULL);
10918 ROSE_ASSERT (pattern_exp != NULL);
10919
10920 // we replace all SgExpression within the pattern with copies of anchor
10921 Rose_STL_Container<SgNode*> opaque_exp_list = NodeQuery::querySubTree(pattern_exp,V_SgExpression);
10922 for (size_t i = 0; i<opaque_exp_list.size(); i++)
10923 {
10924 SgExpression* opaque_exp = isSgExpression(opaque_exp_list[i]);
10925 ROSE_ASSERT (opaque_exp != NULL);
10926 if (opaque_exp->variantT() == V_SgVariantExpression)
10927 {
10928 SgExpression * anchor_exp_copy = deepCopy(anchor_exp);
10929 replaceExpression(opaque_exp, anchor_exp_copy);
10930 }
10931 }
10932
10933 // finally we replace anchor_exp with the pattern_exp
10934 replaceExpression(anchor_exp, pattern_exp, false);
10935 return new_pattern;
10936}
10940{
10941 //This implementation tends to generate numbers that are unnecessarily high.
10942 static int counter = 0;
10943
10944 string name;
10945 bool collision = false;
10946 do
10947 {
10948 name = "__" + baseName + boost::lexical_cast<string > (counter++) + "__";
10949
10950 // DQ (8/16/2013): Modified to reflect new API.
10951 // Look up the name in the parent scopes
10952 // SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope);
10953 SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope,NULL,NULL);
10954 collision = (nameSymbol != NULL);
10955
10956 //Look up the name in the children scopes
10957 Rose_STL_Container<SgNode*> childScopes = NodeQuery::querySubTree(scope, V_SgScopeStatement);
10958
10959 BOOST_FOREACH(SgNode* childScope, childScopes)
10960 {
10961 SgScopeStatement* childScopeStatement = isSgScopeStatement(childScope);
10962
10963 // DQ (8/16/2013): Modified to reflect new API.
10964 // nameSymbol = childScopeStatement->lookup_symbol(SgName(name));
10965 nameSymbol = childScopeStatement->lookup_symbol(SgName(name),NULL,NULL);
10966
10967 collision = collision || (nameSymbol != NULL);
10968 }
10969 } while (collision);
10970
10971 return name;
10972}
10973
10974
10975std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableForExpression
10976(SgExpression* expression, SgScopeStatement* scope, bool initializeInDeclaration, SgAssignOp** reEvaluate)
10977{
10978 SgType* expressionType = expression->get_type();
10979 SgType* variableType = expressionType;
10980
10981 //If the expression has a reference type, we need to use a pointer type for the temporary variable.
10982 //Else, re-assigning the variable is not possible
10983 bool isReferenceType = SageInterface::isReferenceType(expressionType);
10984 if (isReferenceType)
10985 {
10986 SgType* expressionBaseType = expressionType->stripType(SgType::STRIP_TYPEDEF_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE);
10987 variableType = SageBuilder::buildPointerType(expressionBaseType);
10988 }
10989
10990 //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.
10991 if (SgArrayType* arrayType=isSgArrayType(expressionType)) {
10992 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
10993 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
10994 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
10995 }
10996 }
10997
10998 // If the expression is a dereferenced pointer, use a reference to hold it.
10999 if (isSgPointerDerefExp(expression))
11000 variableType = SageBuilder::buildReferenceType(variableType);
11001
11002 //Generate a unique variable name
11003 string name = generateUniqueVariableName(scope);
11004
11005 //Initialize the temporary variable to an evaluation of the expression
11006 SgExpression* tempVarInitExpression = SageInterface::copyExpression(expression);
11007 ROSE_ASSERT(tempVarInitExpression != NULL);
11008 if (isReferenceType)
11009 {
11010 //FIXME: the next line is hiding a bug in ROSE. Remove this line and talk to Dan about the resulting assert
11011 tempVarInitExpression->set_lvalue(false);
11012
11013 tempVarInitExpression = SageBuilder::buildAddressOfOp(tempVarInitExpression);
11014 }
11015
11016 //Optionally initialize the variable in its declaration
11017 SgAssignInitializer* initializer = NULL;
11018 if (initializeInDeclaration)
11019 {
11020 SgExpression* initExpressionCopy = SageInterface::copyExpression(tempVarInitExpression);
11021 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11022 }
11023
11024 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11025 ROSE_ASSERT(tempVarDeclaration != NULL);
11026
11027 //Now create the assignment op for reevaluating the expression
11028 if (reEvaluate != NULL)
11029 {
11030 SgVarRefExp* tempVarReference = SageBuilder::buildVarRefExp(tempVarDeclaration);
11031 *reEvaluate = SageBuilder::buildAssignOp(tempVarReference, tempVarInitExpression);
11032 }
11033
11034 //Build the variable reference expression that can be used in place of the original expression
11035 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11036 if (isReferenceType)
11037 {
11038 //The temp variable is a pointer type, so dereference it before using it
11039 varRefExpression = SageBuilder::buildPointerDerefExp(varRefExpression);
11040 }
11041
11042 return std::make_pair(tempVarDeclaration, varRefExpression);
11043}
11044
11045// This function creates a temporary variable for a given expression in the given scope
11046// This is different from SageInterface::createTempVariableForExpression in that it does not
11047// try to be smart to create pointers to reference types and so on. The tempt is initialized to expression.
11048// The caller is responsible for setting the parent of SgVariableDeclaration since buildVariableDeclaration
11049// may not set_parent() when the scope stack is empty. See programTransformation/extractFunctionArgumentsNormalization/ExtractFunctionArguments.C for sample usage.
11050
11051std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableAndReferenceForExpression
11052(SgExpression* expression, SgScopeStatement* scope)
11053{
11054 SgType* expressionType = expression->get_type();
11055 SgType* variableType = expressionType;
11056
11057 //MS 10/24/2018: If the expression has array type, we need to use a pointer type for the temporary variable.
11058 if (SgArrayType* arrayType=isSgArrayType(expressionType))
11059 {
11060 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
11061 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
11062 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
11063 }
11064 }
11065
11066 //Generate a unique variable name
11067 string name = generateUniqueVariableName(scope);
11068
11069 //initialize the variable in its declaration
11070 SgAssignInitializer* initializer = NULL;
11071 SgExpression* initExpressionCopy = SageInterface::copyExpression(expression);
11072 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11073
11074 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11075 ROSE_ASSERT(tempVarDeclaration != NULL);
11076
11077 //Build the variable reference expression that can be used in place of the original expression
11078 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11079 return std::make_pair(tempVarDeclaration, varRefExpression);
11080}
11081
11082
11083namespace
11084{
11085 void
11086 replaceExpressionInSgExpressionPtrList(SgExpression* oldExp, SgExpression* newExp, SgExpressionPtrList& lst, bool replAll = false)
11087 {
11088 SgExpressionPtrList::iterator lim = lst.end();
11089 SgExpressionPtrList::iterator pos = lst.begin();
11090 bool chg = false;
11091
11092 do
11093 {
11094 pos = std::find(pos, lim, oldExp);
11095
11096 if (pos != lim) { *pos = newExp; ++pos; chg = true; }
11097 } while (replAll && (pos != lim));
11098
11099 ROSE_ASSERT(chg);
11100 }
11101}
11102
11103// This code is based on OpenMP translator's ASTtools::replaceVarRefExp() and astInling's replaceExpressionWithExpression()
11104// Motivation: It involves the parent node to replace a VarRefExp with a new node
11105// Used to replace shared variables with the dereference expression of their addresses
11106// e.g. to replace shared1 with (*__pp_shared1)
11107
11108void SageInterface::replaceExpression(SgExpression* oldExp, SgExpression* newExp, bool keepOldExp/*=false*/) {
11109 SgExpression* parentExp;
11110
11111 ROSE_ASSERT(oldExp);
11112 ROSE_ASSERT(newExp);
11113 if (oldExp==newExp) return;
11114
11115 if (isSgVarRefExp(newExp))
11116 newExp->set_need_paren(true); // enclosing new expression with () to be safe
11117
11118 SgNode* parent = oldExp->get_parent();
11119 ROSE_ASSERT(parent!=NULL);
11120 newExp->set_parent(parent);
11121
11122 // set lvalue when necessary
11123 if (oldExp->get_lvalue() == true) newExp->set_lvalue(true);
11124
11125 if (isSgExprStatement(parent)) {
11126 isSgExprStatement(parent)->set_expression(newExp);
11127 } else if (isSgForStatement(parent)) {
11128 ROSE_ASSERT (isSgForStatement(parent)->get_increment() == oldExp);
11129 isSgForStatement(parent)->set_increment(newExp);
11130 // TODO: any other cases here??
11131 } else if(SgMatlabForStatement *matlabFor = isSgMatlabForStatement(parent)) {
11132 if(matlabFor->get_index() == oldExp)
11133 matlabFor->set_index(newExp);
11134 else if(matlabFor->get_range() == oldExp)
11135 matlabFor->set_range(newExp);
11136 else
11137 ROSE_ASSERT(!"sub-expression not found");
11138 } else if(SgJovialForThenStatement *jovFor = isSgJovialForThenStatement(parent)) {
11139 if(jovFor->get_initialization() == oldExp)
11140 jovFor->set_initialization(newExp);
11141 else if(jovFor->get_while_expression() == oldExp)
11142 jovFor->set_while_expression(newExp);
11143 else if(jovFor->get_by_or_then_expression() == oldExp)
11144 jovFor->set_by_or_then_expression(newExp);
11145 else
11146 ROSE_ASSERT(!"sub-expression not found");
11147 } else if (SgRangeExp* rngexp = isSgRangeExp(parent)) {
11148 if (rngexp->get_start() == oldExp)
11149 rngexp->set_start(newExp);
11150 else if (rngexp->get_end() == oldExp)
11151 rngexp->set_end(newExp);
11152 else if (rngexp->get_stride() == oldExp)
11153 rngexp->set_stride(newExp);
11154 else
11155 ROSE_ASSERT(!"sub-expression not found");
11156 } else if (isSgReturnStmt(parent)) {
11157 isSgReturnStmt(parent)->set_expression(newExp);
11158 } else if (isSgBinaryOp(parent)!=NULL) {
11159 if (oldExp==isSgBinaryOp(parent)->get_lhs_operand()) {
11160 isSgBinaryOp(parent)->set_lhs_operand(newExp);
11161 } else if (oldExp==isSgBinaryOp(parent)->get_rhs_operand()) {
11162 isSgBinaryOp(parent)->set_rhs_operand(newExp);
11163 } else {
11164 ROSE_ABORT();
11165 }
11166 } else if (isSgUnaryOp(parent)!=NULL){
11167 if (oldExp==isSgUnaryOp(parent)->get_operand_i())
11168 isSgUnaryOp(parent)->set_operand_i(newExp);
11169 else
11170 ROSE_ABORT();
11171 } else if (isSgConditionalExp(parent) != NULL) {
11172 SgConditionalExp* expparent = isSgConditionalExp(parent); //get explicity type parent
11173 if (oldExp==expparent->get_conditional_exp())
11174 expparent->set_conditional_exp(newExp);
11175 else if (oldExp==expparent->get_true_exp())
11176 expparent->set_true_exp(newExp);
11177 else if (oldExp==expparent->get_false_exp())
11178 expparent->set_false_exp(newExp);
11179 else
11180 ROSE_ABORT();
11181 } else if (isSgExprListExp(parent) != NULL) {
11182 SgExpressionPtrList& explist = isSgExprListExp(parent)->get_expressions();
11183 for (Rose_STL_Container<SgExpression*>::iterator i=explist.begin();i!=explist.end();i++) {
11184 if (isSgExpression(*i)==oldExp) {
11185 SgExprListExp* parentExpListExp = isSgExprListExp(parent);
11186 parentExpListExp->replace_expression(oldExp,newExp);
11187 // break; //replace the first occurrence only??
11188 }
11189 }
11190 } else if (isSgValueExp(parent)) {
11191 // For compiler generated code, this could happen.
11192 // We can just ignore this function call since it will not appear in the final AST.
11193 return;
11194 } else if (SgActualArgumentExpression* actexp = isSgActualArgumentExpression(parent)) {
11195 ROSE_ASSERT(oldExp == actexp->get_expression());
11196 actexp->set_expression(newExp);
11197 } else if (SgAdaAttributeExp* attrexp = isSgAdaAttributeExp(parent)) {
11198 if (oldExp == attrexp->get_object()) {
11199 attrexp->set_object(newExp);
11200 } else if (oldExp == attrexp->get_args()) {
11201 SgExprListExp* newLst = isSgExprListExp(newExp);
11202 ASSERT_not_null(newLst);
11203
11204 attrexp->set_args(newLst);
11205 } else {
11206 ROSE_ABORT();
11207 }
11208 /**** ALL expressions must be handled before the next line *****/
11209 } else if ((parentExp=isSgExpression(parent)) != NULL) {
11210 int worked = parentExp->replace_expression(oldExp, newExp);
11211 // ROSE_DEPRECATED_FUNCTION
11212 ROSE_ASSERT (worked);
11213 } else if (isSgInitializedName(parent)) {
11214 SgInitializedName* initializedNameParent = isSgInitializedName(parent);
11215 if (oldExp == initializedNameParent->get_initializer()) {
11216 //We can only replace an initializer expression with another initializer expression
11217 ROSE_ASSERT(isSgInitializer(newExp));
11218 initializedNameParent->set_initializer(isSgInitializer(newExp));
11219 } else {
11220 //What other expressions can be children of an SgInitializedname?
11221 ROSE_ABORT();
11222 }
11223 } else if (isSgCaseOptionStmt(parent)) {
11224 SgCaseOptionStmt * case_stmt = isSgCaseOptionStmt(parent);
11225 if (oldExp == case_stmt->get_key()) {
11226 case_stmt->set_key(newExp);
11227 } else if(oldExp == case_stmt->get_key_range_end()) {
11228 case_stmt->set_key_range_end(newExp);
11229 } else {
11230 ROSE_ABORT();
11231 }
11232 } else if (isSgProcessControlStatement(parent)) {
11234 if (oldExp == ctrl_stmt->get_quiet()) {
11235 ctrl_stmt->set_quiet(newExp);
11236 } else if (oldExp == ctrl_stmt->get_code()) {
11237 ctrl_stmt->set_code(newExp);
11238 } else {
11239 ROSE_ABORT();
11240 }
11241 } else if (isSgFortranDo(parent)) {
11242 SgFortranDo* fortranDo = isSgFortranDo(parent);
11243 if (oldExp == fortranDo->get_initialization()) {
11244 fortranDo->set_initialization(newExp);
11245 } else if(oldExp == fortranDo->get_bound()) {
11246 fortranDo->set_bound(newExp);
11247 } else if (oldExp == fortranDo->get_increment()) {
11248 fortranDo->set_increment(newExp);
11249 } else {
11250 ROSE_ABORT();
11251 }
11252 }
11253 else if (SgAdaExitStmt* stm = isSgAdaExitStmt(parent)) {
11254 ROSE_ASSERT(oldExp == stm->get_condition());
11255 stm->set_condition(newExp);
11256 }
11257 else if (SgAdaModularType* ptype = isSgAdaModularType(parent)) {
11258 ROSE_ASSERT(oldExp == ptype->get_modexpr());
11259 ptype->set_modexpr(newExp);
11260 }
11261 else if (SgAdaDelayStmt* stm = isSgAdaDelayStmt(parent)) {
11262 ROSE_ASSERT(oldExp == stm->get_time());
11263 stm->set_time(newExp);
11264 } else if (SgAdaAttributeClause* clause = isSgAdaAttributeClause(parent)) {
11265 ROSE_ASSERT(oldExp == clause->get_size());
11266 clause->set_size(newExp);
11267 } else if (SgAdaRenamingDecl* dcl = isSgAdaRenamingDecl(parent)) {
11268 ROSE_ASSERT(oldExp == dcl->get_renamed());
11269 dcl->set_renamed(newExp);
11270 } else if (SgAdaEntryDecl* dcl = isSgAdaEntryDecl(parent)) {
11271 ROSE_ASSERT(oldExp == dcl->get_entryBarrier());
11272 dcl->set_entryBarrier(newExp);
11273 } else if (SgAdaSelectAlternativeStmt* stm = isSgAdaSelectAlternativeStmt(parent)) {
11274 ROSE_ASSERT(oldExp == stm->get_guard());
11275 stm->set_guard(newExp);
11276 } else if (SgAdaDeltaConstraint* delc = isSgAdaDeltaConstraint(parent)) {
11277 ROSE_ASSERT(oldExp == delc->get_delta());
11278 delc->set_delta(newExp);
11279 } else if (SgAdaDigitsConstraint* digc = isSgAdaDigitsConstraint(parent)) {
11280 ROSE_ASSERT(oldExp == digc->get_digits());
11281 digc->set_digits(newExp);
11282 } else if (SgAdaDiscriminantConstraint* disc = isSgAdaDiscriminantConstraint(parent)) {
11283 replaceExpressionInSgExpressionPtrList(oldExp, newExp, disc->get_discriminants());
11284 } else if (SgAdaRangeConstraint* rngc = isSgAdaRangeConstraint(parent)) {
11285 ROSE_ASSERT(oldExp == rngc->get_range());
11286 rngc->set_range(newExp);
11287 } else if (SgAdaIndexConstraint* idxc = isSgAdaIndexConstraint(parent)) {
11288 replaceExpressionInSgExpressionPtrList(oldExp, newExp, idxc->get_indexRanges());
11289 } else if (SgAdaVariantDecl* vtdcl = isSgAdaVariantDecl(parent)) {
11290 ROSE_ASSERT(oldExp == vtdcl->get_discriminant());
11291 vtdcl->set_discriminant(newExp);
11292 } else if (SgAdaRepresentationClause* clause = isSgAdaRepresentationClause(parent)) {
11293 ROSE_ASSERT(oldExp == clause->get_alignment());
11294 clause->set_alignment(newExp);
11295 } else if (SgAdaVariantWhenStmt* vtwhen = isSgAdaVariantWhenStmt(parent)) {
11296 SgExprListExp* newLst = isSgExprListExp(newExp);
11297 if (newLst && (oldExp == vtwhen->get_choices()))
11298 vtwhen->set_choices(newLst);
11299 else
11300 ROSE_ABORT();
11301 } else if (SgAdaComponentClause* clause = isSgAdaComponentClause(parent)) {
11302 if (oldExp == clause->get_offset())
11303 clause->set_offset(newExp);
11304 else if (oldExp == clause->get_range() && isSgRangeExp(newExp))
11305 clause->set_range(isSgRangeExp(newExp));
11306 else if (oldExp == clause->get_component() && isSgVarRefExp(newExp))
11307 clause->set_component(isSgVarRefExp(newExp));
11308 else
11309 ROSE_ABORT();
11310 } else if (SgAdaFunctionRenamingDecl* rendcl = isSgAdaFunctionRenamingDecl(oldExp->get_parent())) {
11311 if (oldExp == rendcl->get_renamed_function())
11312 rendcl->set_renamed_function(newExp);
11313 else
11314 ROSE_ABORT();
11315 } else {
11316 cerr<<"SageInterface::replaceExpression(). Unhandled parent expression type of SageIII enum value: " <<parent->class_name()<<endl;
11317 ROSE_ABORT();
11318 }
11319
11320 if (!keepOldExp) {
11321 deepDelete(oldExp); // avoid dangling node in memory pool
11322 } else {
11323 oldExp->set_parent(NULL);
11324 }
11325
11326} //replaceExpression()
11327
11329 {
11330 // reuse the implementation in ROSE namespace from src/roseSupport/utility_functions.C
11331 return Rose::getNextStatement(currentStmt);
11332 }
11333
11334SgStatement* SageInterface::getPreviousStatement(SgStatement * currentStmt, bool climbOutScope /*= true*/)
11335 {
11336 return Rose::getPreviousStatement(currentStmt, climbOutScope);
11337 }
11338
11340 return isSgIntVal(e) && isSgIntVal(e)->get_value() == value;
11341 }
11342
11344 {
11345 ROSE_ASSERT(func1&& func2);
11346 bool result = false;
11347 if (func1 == func2)
11348 result = true;
11349 else
11350 {
11352 {
11353 if (func1->get_name() == func2->get_name())
11354 result = true;
11355 }
11356 else if (is_Cxx_language() || is_Java_language())
11357 {
11358 if (func1->get_qualified_name().getString() +
11359 func1->get_mangled_name().getString() ==
11360 func2->get_qualified_name().getString() +
11361 func2->get_mangled_name().getString()
11362 )
11363 result = true;
11364 }
11365 else if (is_Fortran_language())
11366 {
11367 if (func1->get_name() == func2->get_name())
11368 result = true;
11369 }
11370 else
11371 {
11372 cout<<"Error: SageInterface::isSameFunction(): unhandled language"<<endl;
11373 ROSE_ABORT();
11374 }
11375
11376 } // not identical
11377 return result;
11378 } // isSameFunction()
11379
11382{
11383 bool result =false;
11384 ROSE_ASSERT(stmt != NULL);
11385 SgScopeStatement* p_scope = stmt->get_scope();
11386 ROSE_ASSERT(p_scope != NULL);
11387#if 0
11388 if (p_scope->containsOnlyDeclarations())
11389 {
11390 SgDeclarationStatementPtrList stmtlist= p_scope->getDeclarationList ()
11391 if (stmtlist[stmtlist.size()-1] == stmt)
11392 result = true;
11393 }
11394 else
11395 {
11396 SgStatementPtrList stmtlist= p_scope->getStatementList ();
11397 if (stmtlist[stmtlist.size()-1] == stmt)
11398 result = true;
11399 }
11400#endif
11401 SgStatementPtrList stmtlist= p_scope->generateStatementList ();
11402 if (stmtlist[stmtlist.size()-1] == stmt)
11403 result = true;
11404
11405 return result;
11406}
11407
11408#ifndef USE_ROSE
11409//-----------------------------------------------
11410// Remove original expression trees from expressions, so you can change
11411// the value and have it unparsed correctly.
11413 struct Visitor: public AstSimpleProcessing {
11414 virtual void visit(SgNode* n) {
11415 SgValueExp* valueExp = isSgValueExp(n);
11416 if (valueExp != NULL) {
11417 valueExp->set_originalExpressionTree(NULL);
11418 }
11419 else {
11420 SgCastExp* cast_exp = isSgCastExp(n);
11421 if (cast_exp != NULL) {
11422 cast_exp->set_originalExpressionTree(NULL);
11423 }
11424 }
11425 }
11426 };
11427 Visitor().traverse(top, preorder);
11428}
11429#endif
11430
11432 while (s && !isSgSwitchStatement(s)) {
11433 s = isSgStatement(s->get_parent());
11434 }
11435 ROSE_ASSERT (s);
11436 return isSgSwitchStatement(s);
11437}
11438
11441 while (s && !isSgOmpClauseBodyStatement(s)) {
11442 s = isSgStatement(s->get_parent());
11443 }
11444 // ROSE_ASSERT (s); // s is allowed to be NULL.
11445 if (s==NULL)
11446 return NULL;
11447 return isSgOmpClauseBodyStatement(s);
11448}
11449
11450
11451SgScopeStatement* SageInterface::findEnclosingLoop(SgStatement* s, const std::string& label, bool stopOnSwitches) {
11452 /* label can represent a fortran label or a java label provided as a label in a continue/break statement */
11453 for (; s; s = isSgStatement(s->get_parent())) {
11454 SgScopeStatement* sc = isSgScopeStatement(s);
11455 // Need to check for empty label as for java we must detect the
11456 // innermost labeled statement and skip everything in between
11457 switch (s->variantT()) {
11458 case V_SgDoWhileStmt: {
11459 if (label.empty()) {
11460 return sc;
11461 }
11462 break;
11463 }
11464 case V_SgForStatement: {
11465 if (label.empty()) {
11466 return sc;
11467 }
11468 break;
11469 }
11470 case V_SgFortranDo:
11471 case V_SgFortranNonblockedDo: {
11472 if (label.empty() ||
11473 label == isSgFortranDo(sc)->get_string_label()) {
11474 return sc;
11475 }
11476 break;
11477 }
11478 case V_SgWhileStmt: {
11479 if (label.empty() ||
11480 label == isSgWhileStmt(sc)->get_string_label()) {
11481 return sc;
11482 }
11483 break;
11484 }
11485 case V_SgSwitchStatement: {
11486 if (stopOnSwitches) return sc;
11487 break;
11488 }
11489 case V_SgJavaForEachStatement: {
11490 if (label.empty()) {
11491 return sc;
11492 }
11493 break;
11494 }
11495 case V_SgJavaLabelStatement: {
11496 if (label.empty() ||
11497 label == isSgJavaLabelStatement(sc)->get_label().getString()) {
11498 return sc;
11499 }
11500 break;
11501 }
11502 default: continue;
11503 }
11504 }
11505 return NULL;
11506}
11507
11508#ifndef USE_ROSE
11510{
11511 class RemoveJumpsToNextStatementVisitor: public AstSimpleProcessing {
11512 public:
11513 virtual void visit(SgNode* n) {
11514 if (isSgBasicBlock(n)) {
11515 SgBasicBlock* bb = isSgBasicBlock(n);
11516 bool changes = true;
11517 while (changes) {
11518 changes = false;
11519 for (SgStatementPtrList::iterator i = bb->get_statements().begin();
11520 i != bb->get_statements().end(); ++i) {
11521 if (isSgGotoStatement(*i)) {
11522 SgGotoStatement* gs = isSgGotoStatement(*i);
11523 SgStatementPtrList::iterator inext = i;
11524 ++inext;
11525 if (inext == bb->get_statements().end())
11526 continue;
11527 if (!isSgLabelStatement(*inext))
11528 continue;
11529 SgLabelStatement* ls = isSgLabelStatement(*inext);
11530 if (gs->get_label() == ls) {
11531 changes = true;
11532 bb->get_statements().erase(i);
11533 break;
11534 }
11535 }
11536 }
11537 }
11538 }
11539 }
11540 };
11541
11542 RemoveJumpsToNextStatementVisitor().traverse(top, postorder);
11543
11544}
11545#endif
11546
11547// special purpose remove for AST transformation/optimization from astInliner, don't use it otherwise.
11549 // assert (LowLevelRewrite::isRemovableStatement(*i));
11550 SgStatement* parent = isSgStatement(stmt->get_parent());
11551 ROSE_ASSERT (parent);
11552 SgBasicBlock* bb = isSgBasicBlock(parent);
11553 SgForInitStatement* fis = isSgForInitStatement(parent);
11554 if (bb || fis) {
11555 ROSE_ASSERT (bb || fis);
11556 SgStatementPtrList& siblings =
11557 (bb ? bb->get_statements() : fis->get_init_stmt());
11558 SgStatementPtrList::iterator j =
11559 std::find(siblings.begin(), siblings.end(), stmt);
11560 ROSE_ASSERT (j != siblings.end());
11561 siblings.erase(j);
11562 // LowLevelRewrite::remove(*i);
11563 } else {
11564 parent->replace_statement(stmt, new SgNullStatement(TRANS_FILE));
11565 }
11566}
11567
11568
11569#ifndef USE_ROSE
11570std::set<SgLabelStatement*> SageInterface::findUnusedLabels (SgNode* top)
11571{
11572 class FindUsedAndAllLabelsVisitor: public AstSimpleProcessing {
11573 SgLabelStatementPtrSet& used;
11574 SgLabelStatementPtrSet& all;
11575
11576 public:
11577 FindUsedAndAllLabelsVisitor(SgLabelStatementPtrSet& used,
11578 SgLabelStatementPtrSet& all):
11579 used(used), all(all) {}
11580
11581 virtual void visit(SgNode* n) {
11582 if (isSgGotoStatement(n)) {
11583 used.insert(isSgGotoStatement(n)->get_label());
11584 }
11585 if (isSgLabelStatement(n)) {
11586 all.insert(isSgLabelStatement(n));
11587 }
11588 }
11589 };
11590
11591 SgLabelStatementPtrSet used;
11592 SgLabelStatementPtrSet unused;
11593 FindUsedAndAllLabelsVisitor(used, unused).traverse(top, preorder);
11594
11595 for (SgLabelStatementPtrSet::iterator i = used.begin();
11596 i != used.end(); ++i) {
11597 assert (unused.find(*i) != unused.end());
11598 // std::cout << "Keeping used label " << (*i)->get_label().str() << std::endl;
11599 unused.erase(*i);
11600 }
11601
11602 return unused;
11603}
11604
11605// Remove all unused labels in a section of code.
11606void SageInterface::removeUnusedLabels(SgNode* top, bool keepChild/* =false */) {
11607
11608 SgLabelStatementPtrSet unused = findUnusedLabels(top);
11609
11610 for (SgLabelStatementPtrSet::iterator i = unused.begin();
11611 i != unused.end(); ++i) {
11612
11613 SgLabelStatement* l_stmt = *i;
11614 // std::cout << "Removing unused label " << (*i)->get_label().str() << std::endl;
11615 if (keepChild)
11616 {
11617 SgStatement* child= l_stmt->get_statement();
11618// l_stmt->set_parent(NULL);
11619 l_stmt->set_statement(NULL);
11620 replaceStatement (l_stmt, child);
11621 }
11622 else
11624 }
11625}
11626#endif
11627
11629 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_body();
11630 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_loop_body();
11631 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_body();
11632
11633 ROSE_ASSERT (!"Bad loop kind");
11634 return NULL;
11635 }
11636
11638 if (isSgWhileStmt(loopStmt)) {
11639 isSgWhileStmt(loopStmt)->set_body(body);
11640 } else if (isSgForStatement(loopStmt)) {
11641 isSgForStatement(loopStmt)->set_loop_body(body);
11642 } else if (isSgDoWhileStmt(loopStmt)) {
11643 isSgDoWhileStmt(loopStmt)->set_body(body);
11644 } else {
11645 ROSE_ASSERT (!"Bad loop kind");
11646 }
11647 body->set_parent(loopStmt);
11648 }
11649
11651 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_condition();
11652 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_test();
11653 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_condition();
11654
11655 ROSE_ASSERT (!"Bad loop kind");
11656 return NULL;
11657 }
11658
11660 if (isSgWhileStmt(loopStmt)) {
11661 isSgWhileStmt(loopStmt)->set_condition(cond);
11662 } else if (isSgForStatement(loopStmt)) {
11663 isSgForStatement(loopStmt)->set_test(cond);
11664 } else if (isSgDoWhileStmt(loopStmt)) {
11665 isSgDoWhileStmt(loopStmt)->set_condition(cond);
11666 } else {
11667 ROSE_ASSERT (!"Bad loop kind");
11668 }
11669 cond->set_parent(loopStmt);
11670 }
11671
11673// usually useful when compare two expressions to see if they actually refer to the same variable
11674static SgExpression* SkipCasting (SgExpression* exp)
11675{
11676 SgCastExp* cast_exp = isSgCastExp(exp);
11677 if (cast_exp != NULL)
11678 {
11679 SgExpression* operand = cast_exp->get_operand();
11680 assert(operand != 0);
11681 return SkipCasting(operand);
11682 }
11683 else
11684 return exp;
11685}
11686
11689{
11690 ROSE_ASSERT(loop!=NULL);
11691
11692 SgStatementPtrList &init = loop ->get_init_stmt();
11693 if (init.size() !=1) // We only handle one statement case
11694 return false;
11695
11696 SgStatement* init1 = init.front();
11697 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
11698 if (decl == NULL) // we only handle for (int i=0; ...)
11699 return true; // the return value is ambiguous: if not int i=0; it is already normalized
11700
11701 SgVariableSymbol* osymbol = getFirstVarSym(decl);
11702 SgInitializedName* ivarname = decl->get_variables().front();
11703 SgExpression* lbast = NULL; // the lower bound, initial state
11704 ROSE_ASSERT(ivarname != NULL);
11705 SgInitializer * initor = ivarname->get_initializer();
11706 if (isSgAssignInitializer(initor))
11707 {
11708 lbast = isSgAssignInitializer(initor)->get_operand();
11709 }
11710 else
11711 { //SgConstructorInitializer etc.
11712 // other complex declaration statements, such as Decomposition::Iterator ditr(&decomp) should be skipped
11713 // they cause a loop to be non-canonical.
11714 return false;
11715 }
11716
11717 // add a new statement like int i; and insert it to the enclosing function
11718 // There are multiple choices about where to insert this statement:
11719 // global scope: max name pollution,
11720 // right before the loop: mess up perfectly nested loops
11721 // So we prepend the statement to the enclosing function's body
11723 ROSE_ASSERT(funcDef!=NULL);
11724 SgBasicBlock* funcBody = funcDef->get_body();
11725 ROSE_ASSERT(funcBody!=NULL);
11726 //TODO a better name
11727 std::ostringstream os;
11728 os<<ivarname->get_name().getString();
11729
11730 // keep the original variable name if possible
11731 SgSymbol * visibleSym = NULL;
11732 visibleSym = lookupVariableSymbolInParentScopes(ivarname->get_name(), funcBody);
11733 if (visibleSym != NULL) // if there is a name collision, add suffix to the variable name
11734 {
11735 os<<"_nom_";
11736 os<<++gensym_counter;
11737 }
11738
11739 SgVariableDeclaration* ndecl = buildVariableDeclaration(os.str(),ivarname->get_type(), NULL, funcBody);
11740 prependStatement(ndecl, funcBody);
11741 SgVariableSymbol* nsymbol = getFirstVarSym(ndecl);
11742
11743 // replace variable ref to the new symbol
11744 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11745 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11746 {
11747 SgVarRefExp *vRef = isSgVarRefExp((*i));
11748 if (vRef->get_symbol()==osymbol)
11749 vRef->set_symbol(nsymbol);
11750 }
11751 // replace for (int i=0;) with for (i=0;)
11753 removeStatement(decl); //any side effect to the symbol? put after symbol replacement anyway
11754 init.push_back(ninit);
11755 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11756 // ninit->set_parent(loop);
11757 ninit->set_parent(loop->get_for_init_stmt ());
11758
11759 // keep record of this normalization
11760 // We may undo it later on.
11761 trans_records.forLoopInitNormalizationTable[loop] = true;
11762 trans_records.forLoopInitNormalizationRecord[loop] = make_pair (decl, ndecl) ;
11763
11764 return true;
11765}
11766
11767/*
11768 int i_norm_1;
11769 for (i_norm_1=0; i_norm_1<upper; i_norm_1 ++ );
11770Becomes:
11771 for (int i=0; i< upper; i++) ;
11772 * */
11774{
11775 ROSE_ASSERT (loop != NULL);
11776 //If not previously normalized, nothing to do and return false.
11777 if (!trans_records.forLoopInitNormalizationTable[loop])
11778 return false;
11779 // retrieve original and new declaration of the previous normalization
11780 SgVariableDeclaration* decl = trans_records.forLoopInitNormalizationRecord[loop].first;
11781 SgVariableDeclaration* ndecl = trans_records.forLoopInitNormalizationRecord[loop].second;
11782 ROSE_ASSERT (decl!= NULL);
11783 ROSE_ASSERT (ndecl!= NULL);
11784
11785
11786 // Sanity check
11787 SgStatementPtrList &init = loop ->get_init_stmt();
11788 ROSE_ASSERT(init.size() ==1); // We only handle one statement case
11789
11790 // remove the current init_stmt
11791 SgStatement* init1 = init.front();
11792 SgExprStatement* exp_stmt = isSgExprStatement(init1);
11793 ROSE_ASSERT (exp_stmt != NULL);
11794 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
11795 ROSE_ASSERT (assign_op != NULL);
11796
11797 // remove the new declaration and the current i_norm=1;
11798 removeStatement(ndecl);
11799 removeStatement (exp_stmt);
11800
11801 // restore the original declaration
11802 init.push_back(decl);
11803 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11804 // ninit->set_parent(loop);
11805 decl->set_parent(loop->get_for_init_stmt ());
11806
11807 // replace variable references
11808 // current symbol in the AST
11809 SgVariableSymbol* osymbol = getFirstVarSym(ndecl);
11810 // new symbol we want to have: the original decl
11811 SgVariableSymbol* nsymbol = getFirstVarSym(decl);
11812 // replace variable ref to the new symbol
11813 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11814 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11815 {
11816 SgVarRefExp *vRef = isSgVarRefExp((*i));
11817 if (vRef->get_symbol()==osymbol)
11818 vRef->set_symbol(nsymbol);
11819 }
11820
11821 // clear record: now the loop is not normalized any more
11822 trans_records.forLoopInitNormalizationTable[loop] = false;
11823 return true;
11824}
11825
11827{
11828 ROSE_ASSERT(loop != NULL);
11829
11830 // Normalized the test expressions
11831 // -------------------------------------
11832#if 0 // this is undecided
11833 // skip for (;;) case
11834 SgStatement* test_stmt = loop->get_test();
11835 if (test_stmt!=NULL)
11836 {
11837 if (isSgNullStatement(test_stmt))
11838 return false;
11839 }
11840#endif
11841 SgExpression* test = loop->get_test_expr();
11842 SgExpression* testlhs=NULL, * testrhs=NULL;
11843 if (isSgBinaryOp(test))
11844 {
11845 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11846 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11847 ROSE_ASSERT(testlhs && testrhs);
11848 }
11849 else
11850 return false;
11851 // keep the variable since test will be removed later on
11852 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11853 if (testlhs_var == NULL )
11854 return false;
11855 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11856 if (var_symbol==NULL)
11857 return false;
11858
11859 switch (test->variantT()) {
11860 case V_SgLessThanOp: // i<x is normalized to i<= (x-1)
11862 buildSubtractOp(deepCopy(testrhs), buildIntVal(1))));
11863 // deepDelete(test);// replaceExpression() does this already by default.
11864 break;
11865 case V_SgGreaterThanOp: // i>x is normalized to i>= (x+1)
11867 buildAddOp(deepCopy(testrhs), buildIntVal(1))));
11868 break;
11869 case V_SgLessOrEqualOp:
11870 case V_SgGreaterOrEqualOp:
11871 case V_SgNotEqualOp: //TODO Do we want to allow this?
11872 break;
11873 default:
11874 return false;
11875 }
11876 return true;
11877}
11879{
11880 ROSE_ASSERT(loop != NULL);
11881
11882 SgExpression* test = loop->get_test_expr();
11883 SgExpression* testlhs=NULL, * testrhs=NULL;
11884 if (isSgBinaryOp(test))
11885 {
11886 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11887 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11888 ROSE_ASSERT(testlhs && testrhs);
11889 }
11890 else
11891 return false;
11892 // keep the variable since test will be removed later on
11893 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11894 if (testlhs_var == NULL )
11895 return false;
11896 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11897 if (var_symbol==NULL)
11898 return false;
11899
11900
11901 // -------------------------------------
11902 SgExpression* incr = loop->get_increment();
11903 ROSE_ASSERT(incr != NULL);
11904 switch (incr->variantT()) {
11905 case V_SgPlusPlusOp: //i++ is normalized to i+=1
11906 {
11907 // check if the variables match
11908 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgPlusPlusOp(incr)->get_operand()));
11909 if (incr_var == NULL) return false;
11910 if ( incr_var->get_symbol() != var_symbol)
11911 return false;
11912 replaceExpression(incr,
11913 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)),buildIntVal(1)));
11914 break;
11915 }
11916 case V_SgMinusMinusOp: //i-- is normalized to i+=-1
11917 {
11918 // check if the variables match
11919 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusMinusOp(incr)->get_operand()));
11920 if (incr_var == NULL) return false;
11921 if ( incr_var->get_symbol() != var_symbol)
11922 return false;
11923 replaceExpression(incr,
11924 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildIntVal(-1)));
11925 break;
11926 }
11927 case V_SgMinusAssignOp: // i-= s is normalized to i+= -s
11928 {
11929 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusAssignOp(incr)->get_lhs_operand()));
11930 SgExpression* rhs = isSgMinusAssignOp(incr)->get_rhs_operand();
11931 ROSE_ASSERT (rhs != NULL);
11932 if (incr_var == NULL) return false;
11933 if ( incr_var->get_symbol() != var_symbol)
11934 return false;
11935 replaceExpression(incr,
11936 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildMultiplyOp(buildIntVal(-1), copyExpression(rhs))));
11937 break;
11938 }
11939 case V_SgAssignOp:
11940 case V_SgPlusAssignOp:
11941 break;
11942 default:
11943 return false;
11944 }
11945
11946 return true;
11947}
11949// Her loop translation does not pass AST consistency tests so we rewrite some of them here
11950// NormalizeCPP.C NormalizeLoopTraverse::ProcessLoop()
11951bool SageInterface::forLoopNormalization(SgForStatement* loop, bool foldConstant /*= true*/)
11952{
11953 ROSE_ASSERT(loop != NULL);
11954 // Normalize initialization statement of the for loop
11955 // -------------------------------------
11956 // for (int i=0;... ) becomes int i; for (i=0;..)
11957 // Only roughly check here, isCanonicalForLoop() should be called to have a stricter check
11959 return false;
11960
11961 // Normalized the test expressions
11962 if (!normalizeForLoopTest(loop))
11963 return false;
11964
11965 // Normalize the increment expression
11966 if (!normalizeForLoopIncrement(loop))
11967 return false;
11968
11969 // Normalize the loop body: ensure there is a basic block
11971 ROSE_ASSERT(body!=NULL);
11972 // Liao, 9/22/2009
11973 // folding entire loop may cause decreased accuracy for floating point operations
11974 // we only want to fold the loop controlling expressions
11975 if (foldConstant)
11976 {
11977 //constantFolding(loop->get_parent());
11978 constantFolding(loop->get_test());
11979 constantFolding(loop->get_increment());
11980 }
11981
11982 return true;
11983}
11984
11987{
11988 // TODO, normalize continue to enddo ?
11989 ROSE_ASSERT (loop != NULL);
11990 SgExpression* e_3 = loop->get_increment();
11991 if (isSgNullExpression(e_3))
11992 {
11993 SgIntVal* iv = buildIntVal(1);
11994 loop->set_increment(iv);
11995 iv->set_parent(loop);
11996 delete (e_3);
11997 }
11998 return true;
11999}
12000
12001#if 0
12002bool SageInterface::loopUnrolling(SgForStatement* loop, size_t unrolling_factor)
12003{
12004 // normalize the loop first
12005 if (!forLoopNormalization(loop))
12006 return false; // input loop cannot be normalized to a canonical form
12007 // prepare Loop transformation environment
12009 ROSE_ASSERT(func!=NULL);
12010 AstInterfaceImpl faImpl(func->get_definition()->get_body());
12011 AstInterface fa(&faImpl);
12012 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
12013 ArrayInterface array_interface (*annot);
12014 array_interface.initialize(fa, AstNodePtrImpl(func->get_definition()));
12015 array_interface.observe(fa);
12016 LoopTransformInterface :: set_astInterface(fa);
12017 LoopTransformInterface :: set_arrayInterface(&array_interface);
12018
12019 // invoke the unrolling defined in Qing's code
12020 // the traversal will skip the input node ptr, so we pass loop's parent ptr instead
12021 AstNodePtr result = AstNodePtrImpl(loop->get_parent()) ;
12022
12023 LoopUnrolling lu(unrolling_factor);
12024 //LoopUnrolling lu(unrolling_factor,LoopUnrolling::COND_LEFTOVER);//works but not a good choice
12025 //if (lu.cmdline_configure()) // this will cause unrolling to be skipped if no -unroll is used in command line
12026 result = lu(lpTrans, result);
12027 return true;
12028}
12029#else
12030
12031// a brand new serious implementation for loop unrolling, Liao, 6/25/2009
12032/* Handle left-over iterations if iteration_count%unrolling_factor != 0
12033 * Handle stride (step) >1
12034 * Assuming loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
12035 *
12036 * iteration_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1
12037 * fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step;
12038 * fringe ==0 if no leftover iterations
12039 * otherwise adjust ub so the leftover iterations will put into the last fringe loop
12040 * unrolled loop's header: for (i=lb;i<=ub - fringe; i+= step*unroll_factor)
12041 * loop body: copy body n times from 0 to factor -1
12042 * stmt(i+ 0*step); ...; stmt (i+ (factor-1)*step);
12043 * fringe loop: the same as the original loop, except for no init statement
12044 *
12045 * e.g:
12046 * // unrolling 3 times for the following loop with stride !=1
12047 * for (i=0; i<=9; i+=3)
12048 * {
12049 * a[i]=i;
12050 * }
12051 * // it becomes
12052 * // iteration count = 10%3=1 -> 10/3+1 = 4
12053 * // fringe = 4%3 =1 --> 3*3
12054 * // ub-fringe = 9-3*3
12055 * for (i=0; i<=9-3*3; i+=3*3)
12056 * {
12057 * a[i+3*0]=i;
12058 * a[i+3*1]=i;
12059 * a[i+3*2]=i;
12060 * }
12061 * // i=9 is the leftover iteration
12062 * for (; i<=9; i+=3)
12063 * {
12064 * a[i]=i;
12065 * }
12066 *
12067 */
12068bool SageInterface::loopUnrolling(SgForStatement* target_loop, size_t unrolling_factor)
12069{
12070#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
12071 //Handle 0 and 1, which means no unrolling at all
12072 if (unrolling_factor <= 1)
12073 return true;
12074
12075 // normalize the target loop first
12076
12077 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12078 if (!forLoopNormalization(target_loop))
12079 {
12080 // the return value is not reliable
12081 // cerr<<"Error in SageInterface::loopUnrolling(): target loop cannot be normalized."<<endl;
12082 // dumpInfo(target_loop);
12083 // return false;
12084 }
12085 // grab the target loop's essential header information
12086 SgInitializedName* ivar = NULL;
12087 SgExpression* lb = NULL;
12088 SgExpression* ub = NULL;
12089 SgExpression* step = NULL;
12090 SgStatement* orig_body = NULL;
12091 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, &orig_body))
12092 {
12093 cerr<<"Error in SageInterface::loopUnrolling(): target loop is not canonical."<<endl;
12094 dumpInfo(target_loop);
12095 return false;
12096 }
12097 ROSE_ASSERT(ivar&& lb && ub && step);
12098 ROSE_ASSERT(isSgBasicBlock(orig_body));
12099
12100 // generate the fringe loop
12101 bool needFringe = true;
12102 SgForStatement* fringe_loop = deepCopy<SgForStatement>(target_loop);
12103 insertStatementAfter(target_loop,fringe_loop);
12104 removeStatement(fringe_loop->get_for_init_stmt());
12105 fringe_loop->set_for_init_stmt(NULL);
12106
12107 // _lu_iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;
12109 copyExpression(lb));
12110 raw_range_exp->set_need_paren(true);
12111 SgExpression* range_d_step_exp = buildDivideOp(raw_range_exp,copyExpression(step));//(ub-lb+1)/step
12112 SgExpression* condition_1 = buildEqualityOp(buildModOp(copyExpression(raw_range_exp),copyExpression(step)),buildIntVal(0)); //(ub-lb+1)%step ==0
12113
12114 SgExpression* iter_count_exp = buildConditionalExp(condition_1,range_d_step_exp, buildAddOp(copyExpression(range_d_step_exp),buildIntVal(1)));
12115 // fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step
12116 SgExpression* condition_2 = buildEqualityOp(buildModOp(iter_count_exp, buildIntVal(unrolling_factor)), buildIntVal(0));
12117 SgExpression* initor = buildConditionalExp(condition_2, buildIntVal(0), buildMultiplyOp(buildIntVal(unrolling_factor),copyExpression(step)));
12118
12119 SgScopeStatement* scope = target_loop->get_scope();
12120 ROSE_ASSERT(scope != NULL);
12121 string fringe_name = "_lu_fringe_"+ StringUtility::numberToString(++gensym_counter);
12122 SgVariableDeclaration* fringe_decl = buildVariableDeclaration(fringe_name, buildIntType(),buildAssignInitializer(initor), scope);
12123 insertStatementBefore(target_loop, fringe_decl);
12124 attachComment(fringe_decl, "iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;");
12125 attachComment(fringe_decl, "fringe = iter_count%unroll_factor==0 ? 0:unroll_factor*step");
12126
12127 // compile-time evaluate to see if index is a constant of value 0
12128 // if so, the iteration count can be divided even by the unrolling factor
12129 // and no fringe loop is needed
12130 // WE have to fold on its parent node to get a possible constant since
12131 // constant folding only folds children nodes, not the current node to a constant
12132 ConstantFolding::constantFoldingOptimization(fringe_decl,false);
12133 SgInitializedName * ivarname = fringe_decl->get_variables().front();
12134 ROSE_ASSERT(ivarname != NULL);
12135 // points to a new address if constant folding happens
12136 SgAssignInitializer * init1 = isSgAssignInitializer(ivarname->get_initializer());
12137 if (init1)
12138 if (isSgIntVal(init1->get_operand_i()))
12139 if (isSgIntVal(init1->get_operand_i())->get_value() == 0)
12140 needFringe = false;
12141
12142 // rewrite loop header ub --> ub -fringe; step --> step *unrolling_factor
12143 SgBinaryOp* ub_bin_op = isSgBinaryOp(ub->get_parent());
12144 ROSE_ASSERT(ub_bin_op);
12145 if (needFringe)
12146 ub_bin_op->set_rhs_operand(buildSubtractOp(copyExpression(ub),buildVarRefExp(fringe_name,scope)));
12147 else
12148 {
12149 ub_bin_op->set_rhs_operand(copyExpression(ub));
12150 removeStatement(fringe_decl);
12151 }
12152
12153 SgBinaryOp* step_bin_op = isSgBinaryOp(step->get_parent());
12154 ROSE_ASSERT(step_bin_op != NULL);
12155 step_bin_op->set_rhs_operand(buildMultiplyOp(copyExpression(step),buildIntVal(unrolling_factor)));
12156
12157 bool isPlus = false;
12158 if (isSgPlusAssignOp(step_bin_op))
12159 isPlus = true;
12160 else if (isSgMinusAssignOp(step_bin_op))
12161 isPlus = false;
12162 else
12163 {
12164 cerr<<"Error in SageInterface::loopUnrolling(): illegal incremental exp of a canonical loop"<<endl;
12165 dumpInfo(step_bin_op);
12166 ROSE_ABORT();
12167 }
12168
12169 // copy loop body factor -1 times, and replace reference to ivar with ivar +/- step*[1 to factor-1]
12170 for (size_t i =1; i<unrolling_factor; i++)
12171 {
12172 SgBasicBlock* body = isSgBasicBlock(deepCopy(fringe_loop->get_loop_body())); // normalized loop has a BB body
12173 ROSE_ASSERT(body);
12174 std::vector<SgVarRefExp*> refs = querySubTree<SgVarRefExp> (body, V_SgVarRefExp);
12175 for (std::vector<SgVarRefExp*>::iterator iter = refs.begin(); iter !=refs.end(); iter++)
12176 {
12177 SgVarRefExp* refexp = *iter;
12178 if (refexp->get_symbol()==ivar->get_symbol_from_symbol_table())
12179 {
12180 // replace reference to ivar with ivar +/- step*i
12181 SgExpression* new_exp = NULL;
12182 //build replacement expression for every appearance
12183 if (isPlus) //ivar +/- step * i
12184 new_exp = buildAddOp(buildVarRefExp(ivar,scope),buildMultiplyOp(copyExpression(step),buildIntVal(i)));
12185 else
12187
12188 // replace it with the right one
12189 replaceExpression(refexp, new_exp);
12190 }
12191 }
12192 // copy body to loop body, this should be a better choice
12193 // to avoid redefinition of variables after unrolling (new scope is introduced to avoid this)
12194 appendStatement(body,isSgBasicBlock(orig_body));
12195 // moveStatementsBetweenBlocks(body,isSgBasicBlock(orig_body));
12196 }
12197
12198 // remove the fringe loop if not needed finally
12199 // it is used to buffering the original loop body before in either cases
12200 if (!needFringe)
12201 removeStatement(fringe_loop);
12202
12203 // constant folding for the transformed AST
12204 ConstantFolding::constantFoldingOptimization(scope,false);
12205 //ConstantFolding::constantFoldingOptimization(getProject(),false);
12206
12207#endif
12208
12209 return true;
12210}
12211#endif
12212
12213// Liao, 6/15/2009
12216static size_t myfactorial (size_t n)
12217{
12218 size_t result=1;
12219 for (size_t i=2; i<=n; i++)
12220 result*=i;
12221 return result;
12222}
12223
12224#endif
12225
12226#ifndef USE_ROSE
12227
12230std::vector<size_t> getPermutationOrder( size_t n, size_t lexicoOrder)
12231{
12232 size_t k = lexicoOrder;
12233 std::vector<size_t> s(n);
12234 // initialize the permutation vector
12235 for (size_t i=0; i<n; i++)
12236 s[i]=i;
12237
12238 //compute (n- 1)!
12239 size_t factorial = myfactorial(n-1);
12240 //check if the number is not in the range of [0, n! - 1]
12241 if (k/n>=factorial)
12242 {
12243 printf("Error: in getPermutationOrder(), lexicoOrder is larger than n!-1\n");
12244 ROSE_ABORT();
12245 }
12246 // Algorithm:
12247 //check each element of the array, excluding the right most one.
12248 //the goal is to find the right element for each s[j] from 0 to n-2
12249 // method: each position is associated a factorial number
12250 // s[0] -> (n-1)!
12251 // s[1] -> (n-2)! ...
12252 // the input number k is divided by the factorial at each position (6, 3, 2, 1 for size =4)
12253 // so only big enough k can have non-zero value after division
12254 // 0 value means no change to the position for the current iteration
12255 // The non-zero value is further modular by the number of the right hand elements of the current element.
12256 // (mode on 4, 3, 2 to get offset 1-2-3, 1-2, 1 from the current position 0, 1, 2)
12257 // choose one of them to be moved to the current position,
12258 // shift elements between the current and the moved element to the right direction for one position
12259 for (size_t j=0; j<n-1; j++)
12260 {
12261 //calculates the next cell from the cells left
12262 //(the cells in the range [j, s.length - 1])
12263 int tempj = (k/factorial) % (n - j);
12264 //Temporarily saves the value of the cell needed
12265 // to add to the permutation this time
12266 int temps = s[j+tempj];
12267 //shift all elements to "cover" the "missing" cell
12268 //shift them to the right
12269 for (size_t i=j+tempj; i>j; i--)
12270 {
12271 s[i] = s[i-1]; //shift the chain right
12272 }
12273 // put the chosen cell in the correct spot
12274 s[j]= temps;
12275 // updates the factorial
12276 factorial = factorial /(n-(j+1));
12277 }
12278#if 0
12279 for (size_t i = 0; i<n; i++)
12280 cout<<" "<<s[i];
12281 cout<<endl;
12282#endif
12283 return s;
12284}
12285
12287/* Translation
12288 Before:
12289 for (i = 0; i < 100; i++)
12290 for (j = 0; j < 100; j++)
12291 for (k = 0; k < 100; k++)
12292 c[i][j]= c[i][j]+a[i][k]*b[k][j];
12293
12294 After tiling i loop nest's level 3 (k-loop) with size 5, it becomes
12295
12296// added a new controlling loop at the outer most level
12297 int _lt_var_k;
12298 for (_lt_var_k = 0; _lt_var_k <= 99; _lt_var_k += 1 * 5) {
12299 for (i = 0; i < 100; i++)
12300 for (j = 0; j < 100; j++)
12301 // rewritten loop header , normalized also
12302 for (k = _lt_var_k; k <= (99 < (_lt_var_k + 5 - 1))?99 : (_lt_var_k + 5 - 1); k += 1) {
12303 c[i][j] = c[i][j] + a[i][k] * b[k][j];
12304 }
12305 }
12306// finally run constant folding
12307
12308 */
12309bool SageInterface::loopTiling(SgForStatement* loopNest, size_t targetLevel, size_t tileSize)
12310{
12311 ROSE_ASSERT(loopNest != NULL);
12312 ROSE_ASSERT(targetLevel >0);
12313 // ROSE_ASSERT(tileSize>0);// 1 is allowed
12314 // skip tiling if tiling size is 0 (no tiling), we allow 0 to get a reference value for the original code being tuned
12315 // 1 (no need to tile)
12316 if (tileSize<=1)
12317 return true;
12318 // Locate the target loop at level n
12319 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(loopNest,V_SgForStatement);
12320 ROSE_ASSERT(loops.size()>=targetLevel);
12321 SgForStatement* target_loop = loops[targetLevel -1]; // adjust to numbering starting from 0
12322
12323 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12324 // normalize the target loop first
12325 if (!forLoopNormalization(target_loop))
12326 {// the return value is not reliable
12327// cerr<<"Error in SageInterface::loopTiling(): target loop cannot be normalized."<<endl;
12328// dumpInfo(target_loop);
12329// return false;
12330 }
12331 // grab the target loop's essential header information
12332 SgInitializedName* ivar = NULL;
12333 SgExpression* lb = NULL;
12334 SgExpression* ub = NULL;
12335 SgExpression* step = NULL;
12336 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, NULL))
12337 {
12338 cerr<<"Error in SageInterface::loopTiling(): target loop is not canonical."<<endl;
12339 dumpInfo(target_loop);
12340 return false;
12341 }
12342 ROSE_ASSERT(ivar&& lb && ub && step);
12343
12344 // Add a controlling loop around the top loop nest
12345 // Ensure the parent can hold more than one children
12346 SgLocatedNode* parent = NULL; //SageInterface::ensureBasicBlockAsParent(loopNest)
12347 if (isBodyStatement(loopNest)) // if it is a single body statement (Already a for statement, not a basic block)
12348 parent = makeSingleStatementBodyToBlock (loopNest);
12349 else
12350 parent = isSgLocatedNode(loopNest ->get_parent());
12351
12352 ROSE_ASSERT(parent!= NULL);
12353 // Now we can prepend a controlling loop index variable: __lt_var_originalIndex
12354 string ivar2_name = "_lt_var_"+ivar->get_name().getString();
12355 SgScopeStatement* scope = loopNest->get_scope();
12357 (ivar2_name, buildIntType(),NULL, scope);
12358 insertStatementBefore(loopNest, loop_index_decl);
12359 // init statement of the loop header, copy the lower bound
12360 SgStatement* init_stmt = buildAssignStatement(buildVarRefExp(ivar2_name,scope), copyExpression(lb));
12361 //two cases <= or >= for a normalized loop
12362 SgExprStatement* cond_stmt = NULL;
12363 SgExpression* orig_test = target_loop->get_test_expr();
12364 if (isSgBinaryOp(orig_test))
12365 {
12366 if (isSgLessOrEqualOp(orig_test))
12367 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12368 else if (isSgGreaterOrEqualOp(orig_test))
12369 {
12370 cond_stmt = buildExprStatement(buildGreaterOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12371 }
12372 else
12373 {
12374 cerr<<"Error: illegal condition operator for a canonical loop"<<endl;
12375 dumpInfo(orig_test);
12376 ROSE_ABORT();
12377 }
12378 }
12379 else
12380 {
12381 cerr<<"Error: illegal condition expression for a canonical loop"<<endl;
12382 dumpInfo(orig_test);
12383 ROSE_ABORT();
12384 }
12385 ROSE_ASSERT(cond_stmt != NULL);
12386
12387 // build loop incremental I
12388 // expression var+=up*tilesize or var-=upper * tilesize
12389 SgExpression* incr_exp = NULL;
12390 SgExpression* orig_incr_exp = target_loop->get_increment();
12391 if( isSgPlusAssignOp(orig_incr_exp))
12392 {
12393 incr_exp = buildPlusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12394 }
12395 else if (isSgMinusAssignOp(orig_incr_exp))
12396 {
12397 incr_exp = buildMinusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12398 }
12399 else
12400 {
12401 cerr<<"Error: illegal increment expression for a canonical loop"<<endl;
12402 dumpInfo(orig_incr_exp);
12403 ROSE_ABORT();
12404 }
12405 SgForStatement* control_loop = buildForStatement(init_stmt, cond_stmt,incr_exp, buildBasicBlock());
12406 insertStatementBefore(loopNest, control_loop);
12407 // move loopNest into the control loop
12408 removeStatement(loopNest);
12409 appendStatement(loopNest,isSgBasicBlock(control_loop->get_loop_body()));
12410
12411 // rewrite the lower (i=lb), upper bounds (i<=/>= ub) of the target loop
12412 SgAssignOp* assign_op = isSgAssignOp(lb->get_parent());
12413 ROSE_ASSERT(assign_op);
12414 assign_op->set_rhs_operand(buildVarRefExp(ivar2_name,scope));
12415 // ub< var_i+tileSize-1? ub:var_i+tileSize-1
12416 SgBinaryOp* bin_op = isSgBinaryOp(ub->get_parent());
12417 ROSE_ASSERT(bin_op);
12418 SgExpression* ub2 = buildSubtractOp(buildAddOp(buildVarRefExp(ivar2_name,scope), buildIntVal(tileSize)), buildIntVal(1));
12419 SgExpression* test_exp = buildLessThanOp(copyExpression(ub),ub2);
12420 test_exp->set_need_paren(true);
12421 ub->set_need_paren(true);
12422 ub2->set_need_paren(true);
12423 SgConditionalExp * triple_exp = buildConditionalExp(test_exp,copyExpression(ub), copyExpression(ub2));
12424 bin_op->set_rhs_operand(triple_exp);
12425 // constant folding
12426 // folding entire loop may decrease the accuracy of floating point calculation
12427 // we fold loop control expressions only
12428 //constantFolding(control_loop->get_scope());
12429 constantFolding(control_loop->get_test());
12430 constantFolding(control_loop->get_increment());
12431 return true;
12432}
12433
12435bool SageInterface::loopInterchange(SgForStatement* loop, size_t depth, size_t lexicoOrder)
12436{
12437 if (lexicoOrder == 0) // allow 0 to mean no interchange at all
12438 return true;
12439 // parameter verification
12440 ROSE_ASSERT(loop != NULL);
12441 //must have at least two levels
12442 ROSE_ASSERT (depth >1);
12443 ROSE_ASSERT(lexicoOrder<myfactorial(depth));
12444 //TODO need to verify the input loop has n perfectly-nested children loops inside
12445 // save the loop nest's headers: init, test, and increment
12446 std::vector<SgForStatement* > loopNest = SageInterface::querySubTree<SgForStatement>(loop,V_SgForStatement);
12447 ROSE_ASSERT(loopNest.size()>=depth);
12448 std::vector<std::vector<SgNode*> > loopHeads;
12449 for (std::vector<SgForStatement* > ::iterator i = loopNest.begin(); i!= loopNest.end(); i++)
12450 {
12451 SgForStatement* cur_loop = *i;
12452 std::vector<SgNode*> head;
12453 head.push_back(cur_loop->get_for_init_stmt());
12454 head.push_back(cur_loop->get_test());
12455 head.push_back(cur_loop->get_increment());
12456 loopHeads.push_back(head);
12457 }
12458
12459 // convert the lexicographical number to a permutation order array permutation[depth]
12460 std::vector<size_t> changedOrder = getPermutationOrder (depth, lexicoOrder);
12461 // rewrite the loop nest to reflect the permutation
12462 // set the header to the new header based on the permutation array
12463 for (size_t i=0; i<depth; i++)
12464 {
12465 // only rewrite if necessary
12466 if (i != changedOrder[i])
12467 {
12468 SgForStatement* cur_loop = loopNest[i];
12469 std::vector<SgNode*> newhead = loopHeads[changedOrder[i]];
12470
12471 SgForInitStatement* init = isSgForInitStatement(newhead[0]);
12472 //ROSE_ASSERT(init != NULL) // could be NULL?
12473 ROSE_ASSERT(init != cur_loop->get_for_init_stmt());
12474 cur_loop->set_for_init_stmt(init);
12475 if (init)
12476 {
12477 init->set_parent(cur_loop);
12479 }
12480
12481 SgStatement* test = isSgStatement(newhead[1]);
12482 cur_loop->set_test(test);
12483 if (test)
12484 {
12485 test->set_parent(cur_loop);
12487 }
12488
12489 SgExpression* incr = isSgExpression(newhead[2]);
12490 cur_loop->set_increment(incr);
12491 if (incr)
12492 {
12493 incr->set_parent(cur_loop);
12495 }
12496 }
12497 }
12498 return true;
12499}
12500
12503{
12504 ROSE_ASSERT(loop != NULL);
12505 SgInitializedName* ivarname=NULL;
12506
12507 // Fortran case ------------------
12508 if (SgFortranDo * do_loop = isSgFortranDo(loop))
12509 {
12510 SgAssignOp* assign_op = isSgAssignOp (do_loop->get_initialization());
12511 ROSE_ASSERT (assign_op != NULL);
12512 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12513 ROSE_ASSERT (var != NULL);
12514 ivarname = var->get_symbol()->get_declaration();
12515 ROSE_ASSERT (ivarname != NULL);
12516 return ivarname;
12517 }
12518 // C/C++ case ------------------------------
12519 SgForStatement* fs = isSgForStatement(loop);
12520 if (fs == NULL)
12521 {
12522 return NULL;
12523 }
12524 // we only handle C/C++ for loops and Fortran Do loops.
12525 // Any other kinds of loops (while, do-while,etc.) are skipped and return NULL;
12526 // ROSE_ASSERT (fs != NULL);
12527
12528 //Check initialization statement is something like i=xx;
12529 SgStatementPtrList & init = fs->get_init_stmt();
12530 if (init.size() !=1)
12531 {
12532 cerr<<"SageInterface::getLoopIndexVariable(), no or more than one initialization statements are encountered. Not supported yet "<<endl;
12533 //ROSE_ASSERT(false);
12534 return NULL;
12535 }
12536 SgStatement* init1 = init.front();
12537 SgExpression* ivarast=NULL;
12538
12539 // DQ (3/20/2016): Note that GNU compiler reports these variables are set but not used.
12540 //bool isCase1=false, isCase2=false;
12541
12542 //consider C99 style: for (int i=0;...)
12543 if (isSgVariableDeclaration(init1))
12544 {
12545 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12546 ivarname = decl->get_variables().front();
12547 ROSE_ASSERT(ivarname != NULL);
12548 //SgInitializer * initor = ivarname->get_initializer();
12549 // if (isSgAssignInitializer(initor))
12550 // isCase1 = true;
12551 }// other regular case: for (i=0;..)
12552 else if (isAssignmentStatement(init1, &ivarast))
12553 {
12554 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12555 if (var)
12556 {
12557 ivarname = var->get_symbol()->get_declaration();
12558 //isCase2 = true;
12559 }
12560 }
12561 else if (SgExprStatement* exp_stmt = isSgExprStatement(init1))
12562 { //case like: for (i = 1, len1 = 0, len2=0; i <= n; i++)
12563 // AST is: SgCommaOpExp -> SgAssignOp -> SgVarRefExp
12564 if (SgCommaOpExp* comma_exp = isSgCommaOpExp(exp_stmt->get_expression()))
12565 {
12566 SgCommaOpExp* leaf_exp = comma_exp;
12567 while (isSgCommaOpExp(leaf_exp->get_lhs_operand()))
12568 leaf_exp = isSgCommaOpExp(leaf_exp->get_lhs_operand());
12569 if (SgAssignOp* assign_op = isSgAssignOp(leaf_exp->get_lhs_operand()))
12570 {
12571 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12572 if (var)
12573 {
12574 ivarname = var->get_symbol()->get_declaration();
12575 }
12576 }
12577 }
12578 }
12579 else
12580 {
12581
12582 mlog[Sawyer::Message::Common::WARN] <<"Warning: SageInterface::getLoopIndexVariable(). Unhandled init_stmt type of SgForStatement"<<endl;
12583 mlog[Sawyer::Message::Common::WARN] <<"Init statement is :"<<init1->class_name() <<" " <<init1->unparseToString()<<endl;
12584 init1->get_file_info()->display("Debug");
12585
12586 return NULL;
12587 //ROSE_ASSERT (false);
12588 }
12589 // Cannot be both true
12590 // ROSE_ASSERT(!(isCase1&&isCase2));
12591
12592 //Check loop index's type
12593 //ROSE_ASSERT(isStrictIntegerType(ivarname->get_type()));
12594 return ivarname;
12595}
12596
12600{
12601 ROSE_ASSERT (ivar != NULL);
12602 ROSE_ASSERT (subtree_root != NULL);
12603 bool result = false;
12604 SgScopeStatement * cur_loop = findEnclosingLoop (getEnclosingStatement(subtree_root));
12605 while (cur_loop)
12606 {
12607 SgInitializedName * i_index = getLoopIndexVariable (cur_loop);
12608 if (i_index == ivar)
12609 {
12610 result = true;
12611 break;
12612 }
12613 else
12614 { // findEnclosingLoop() is inclusive.
12615 cur_loop = findEnclosingLoop (getEnclosingStatement(cur_loop->get_parent()));
12616 }
12617 }
12618 return result;
12619}
12620
12622
12627{
12628 ROSE_ASSERT (loop !=NULL);
12629 SgStatementPtrList& stmt_list = loop->get_init_stmt();
12630 if (stmt_list.size() >1) return true; // two var decl statements
12631 if (stmt_list.size() == 0) return false;
12632
12633// generateDOTforMultipleFile(*getProject());
12634 //single variable declaration statement, like int i;
12635 SgVariableDeclaration* decl_stmt = isSgVariableDeclaration(stmt_list[0]);
12636 if (decl_stmt != NULL)
12637 return false;
12638
12639 // single statement, but with comma expression (i=0, j=0)
12640 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
12641 ROSE_ASSERT (exp_stmt != NULL);
12642 if (isSgCommaOpExp (exp_stmt->get_expression()) )
12643 {
12644 return true;
12645 }
12646
12647 return false;
12648}
12650bool 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*/)
12651{
12652 ROSE_ASSERT(loop != NULL);
12653 SgFortranDo* fs = isSgFortranDo(loop);
12654 if (fs == NULL)
12655 return false;
12656 // 1. Check initialization statement is something like i=xx;
12657 SgExpression * init = fs->get_initialization();
12658 if (init == NULL)
12659 return false;
12660 SgAssignOp* init_assign = isSgAssignOp (init);
12661 SgExpression *lbast=NULL, *ubast=NULL;
12662 // SgExpression* ivarast=NULL, *stepast=NULL;
12663 SgInitializedName* ivarname=NULL;
12664
12665 bool isCase1=false;
12666 if (init_assign)
12667 {
12668 SgVarRefExp* var = isSgVarRefExp(init_assign->get_lhs_operand());
12669 if (var)
12670 ivarname = var->get_symbol()->get_declaration();
12671 lbast = init_assign->get_rhs_operand();
12672 if (ivarname && lbast )
12673 isCase1 = true;
12674 }
12675 // if not i=1
12676 if (!isCase1)
12677 return false;
12678
12679 //Check loop index's type
12680 if (!SageInterface::isStrictIntegerType(ivarname->get_type()))
12681 return false;
12682#if 0
12683 //2. Check test expression i [<=, >=, <, > ,!=] bound
12684 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12685 if (test == NULL)
12686 return false;
12687 switch (test->variantT()) {
12688 case V_SgLessOrEqualOp:
12689 if (isInclusiveUpperBound != NULL)
12690 *isInclusiveUpperBound = true;
12691 if (hasIncrementalIterationSpace != NULL)
12692 *hasIncrementalIterationSpace = true;
12693 break;
12694 case V_SgLessThanOp:
12695 if (isInclusiveUpperBound != NULL)
12696 *isInclusiveUpperBound = false;
12697 if (hasIncrementalIterationSpace != NULL)
12698 *hasIncrementalIterationSpace = true;
12699 break;
12700 case V_SgGreaterOrEqualOp:
12701 if (isInclusiveUpperBound != NULL)
12702 *isInclusiveUpperBound = true;
12703 if (hasIncrementalIterationSpace != NULL)
12704 *hasIncrementalIterationSpace = false;
12705 break;
12706 case V_SgGreaterThanOp:
12707 if (isInclusiveUpperBound != NULL)
12708 *isInclusiveUpperBound = false;
12709 if (hasIncrementalIterationSpace != NULL)
12710 *hasIncrementalIterationSpace = false;
12711 break;
12712// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12713 break;
12714 default:
12715 return false;
12716 }
12717 // check the tested variable is the same as the loop index
12718 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12719 if (testvar == NULL)
12720 return false;
12721 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12722 return false;
12723#endif
12724 //grab the upper bound
12725 ubast = loop->get_bound();
12726 // Fortran Do loops always have inclusive upper bound
12727 if (isInclusiveUpperBound != NULL)
12728 *isInclusiveUpperBound = true;
12729 //3. Check the increment expression
12730 SgExpression* incr = fs->get_increment();
12731 ROSE_ASSERT (incr != NULL);
12732 if (isSgNullExpression(incr))
12733 {
12734 cerr<<"Error:isCanonicalDoLoop() found NULL increment expression. Please call doLoopNormalization() first!"<<endl;
12735 ROSE_ASSERT (false);
12736 }
12737 if (hasIncrementalIterationSpace != NULL)
12738 {
12739 *hasIncrementalIterationSpace = true;
12740 // We can only tell a few cases
12741 if (SgIntVal* i_v = isSgIntVal(incr))
12742 {
12743 if (i_v->get_value()<0)
12744 *hasIncrementalIterationSpace = false;
12745 }
12746 }
12747#if 0
12748 SgVarRefExp* incr_var = NULL;
12749 switch (incr->variantT()) {
12750 case V_SgPlusAssignOp: //+=
12751 case V_SgMinusAssignOp://-=
12752 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12753 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12754 break;
12755 case V_SgPlusPlusOp: //++
12756 case V_SgMinusMinusOp: //--
12757 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12758 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12759 break;
12760 default:
12761 return false;
12762 }
12763 if (incr_var == NULL)
12764 return false;
12765 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12766 return false;
12767#endif
12768 // return loop information if requested
12769 if (ivar != NULL)
12770 *ivar = ivarname;
12771 if (lb != NULL)
12772 *lb = lbast;
12773 if (ub != NULL)
12774 *ub = ubast;
12775 if (step != NULL)
12776 *step = incr;
12777 if (body != NULL) {
12778 *body = fs->get_body();
12779 }
12780 return true;
12781}
12782//TODO: expose it to the namespace once it matures.
12784// with a single entry at the top and a single exit at the bottom, or an OpenMP construct.
12785/*
12786From OpenMP 4.5 Specification
12787
127881.2.2 OpenMP Language Terminology
12789
12790For C/C++, an executable statement, possibly compound, with a single entry at the
12791top and a single exit at the bottom, or an OpenMP construct.
12792
12793For Fortran, a block of executable statements with a single entry at the top and a
12794single exit at the bottom, or an OpenMP construct.
12795
12796COMMENTS:
12797
12798For all base languages:
12799* Access to the structured block must not be the result of a branch; and
12800* The point of exit cannot be a branch out of the structured block.
12801
12802 For C/C++:
12803* The point of entry must not be a call to setjmp();
12804* longjmp() and throw() must not violate the entry/exit criteria;
12805* Calls to exit() are allowed in a structured block; and
12806* 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.
12807
12808For Fortran:
12809* STOP statements are allowed in a structured block.
12810
12811*/
12812bool isStructuredBlock(SgStatement* s)
12813{
12814 bool rt = true;
12815 ROSE_ASSERT (s != NULL);
12816
12817 // contain break;
12818 std::set<SgNode*> bset = SgNodeHelper::loopRelevantBreakStmtNodes (s);
12819 if (bset.size()!=0 )
12820 rt = false;
12821 //TODO: contain goto statement, jumping to outside targets
12822 // longjump(), throw(),
12823 // calls to exit() are allowed.
12824
12825 return rt;
12826
12827}
12828
12830//TODO check the loop index is not being written in the loop body
12831bool 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*/)
12832{
12833 ROSE_ASSERT(loop != NULL);
12834 SgForStatement* fs = isSgForStatement(loop);
12835 //SgFortranDo* fs2 = isSgFortranDo(loop);
12836 if (fs == NULL)
12837 {
12838 // if (fs2)
12839 // return isCanonicalDoLoop (fs2, ivar, lb, ub, step, body, hasIncrementalIterationSpace, isInclusiveUpperBound);
12840 // else
12841 return false;
12842 }
12843 // 1. Check initialization statement is something like i=xx;
12844 SgStatementPtrList & init = fs->get_init_stmt();
12845 if (init.size() !=1)
12846 return false;
12847 SgStatement* init1 = init.front();
12848 SgExpression* ivarast=NULL, *lbast=NULL, *ubast=NULL, *stepast=NULL;
12849 SgInitializedName* ivarname=NULL;
12850
12851 bool isCase1=false, isCase2=false;
12852 //consider C99 style: for (int i=0;...)
12853 if (isSgVariableDeclaration(init1))
12854 {
12855 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12856 ivarname = decl->get_variables().front();
12857 ROSE_ASSERT(ivarname != NULL);
12858 SgInitializer * initor = ivarname->get_initializer();
12859 if (isSgAssignInitializer(initor))
12860 {
12861 lbast = isSgAssignInitializer(initor)->get_operand();
12862 isCase1 = true;
12863 }
12864 }// other regular case: for (i=0;..)
12865 else if (isAssignmentStatement(init1, &ivarast, &lbast))
12866 {
12867 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12868 if (var)
12869 {
12870 ivarname = var->get_symbol()->get_declaration();
12871 isCase2 = true;
12872 }
12873 }
12874 // Cannot be both true
12875 ROSE_ASSERT(!(isCase1&&isCase2));
12876 // if not either case is true
12877 if (!(isCase1||isCase2))
12878 return false;
12879
12880 //Check loop index's type
12881 if (!isStrictIntegerType(ivarname->get_type()))
12882 return false;
12883
12884 //2. Check test expression i [<=, >=, <, > ,!=] bound
12885 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12886 if (test == NULL)
12887 return false;
12888 switch (test->variantT()) {
12889 case V_SgLessOrEqualOp:
12890 if (isInclusiveUpperBound != NULL)
12891 *isInclusiveUpperBound = true;
12892 if (hasIncrementalIterationSpace != NULL)
12893 *hasIncrementalIterationSpace = true;
12894 break;
12895 case V_SgLessThanOp:
12896 if (isInclusiveUpperBound != NULL)
12897 *isInclusiveUpperBound = false;
12898 if (hasIncrementalIterationSpace != NULL)
12899 *hasIncrementalIterationSpace = true;
12900 break;
12901 case V_SgGreaterOrEqualOp:
12902 if (isInclusiveUpperBound != NULL)
12903 *isInclusiveUpperBound = true;
12904 if (hasIncrementalIterationSpace != NULL)
12905 *hasIncrementalIterationSpace = false;
12906 break;
12907 case V_SgGreaterThanOp:
12908 if (isInclusiveUpperBound != NULL)
12909 *isInclusiveUpperBound = false;
12910 if (hasIncrementalIterationSpace != NULL)
12911 *hasIncrementalIterationSpace = false;
12912 break;
12913// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12914 break;
12915 default:
12916 return false;
12917 }
12918 // check the tested variable is the same as the loop index
12919 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12920 if (testvar == NULL)
12921 return false;
12922 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12923 return false;
12924 //grab the upper bound
12925 ubast = test->get_rhs_operand();
12926
12927 //3. Check the increment expression
12928 /* Allowed forms
12929 ++var
12930 var++
12931 --var
12932 var--
12933
12934 var += incr
12935 var -= incr
12936
12937 var = var + incr
12938 var = incr + var
12939 var = var - incr
12940 */
12941 SgExpression* incr = fs->get_increment();
12942 SgVarRefExp* incr_var = NULL;
12943 switch (incr->variantT()) {
12944 case V_SgPlusAssignOp: //+=
12945 case V_SgMinusAssignOp://-=
12946 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12947 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12948 break;
12949 case V_SgPlusPlusOp: //++
12950 case V_SgMinusMinusOp: //--
12951 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12952 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12953 break;
12954 case V_SgAssignOp: { // cases : var + incr, var - incr, incr + var (not allowed: incr-var)
12955 incr_var=isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12956 if(incr_var == NULL)
12957 return false;
12958 SgAddOp* addOp=isSgAddOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
12959 SgSubtractOp* subtractOp=isSgSubtractOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
12960 SgBinaryOp* arithOp=0;
12961 if(addOp)
12962 arithOp=addOp;
12963 else if(subtractOp)
12964 arithOp=subtractOp;
12965 else
12966 return false;
12967 ROSE_ASSERT(arithOp!=0);
12968 if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_lhs_operand()))) {
12969 // cases : var + incr, var - incr
12970 incr_var=varRefExp;
12971 stepast=isSgBinaryOp(arithOp)->get_rhs_operand();
12972 } else if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_rhs_operand()))) {
12973 if(isSgAddOp(arithOp)) {
12974 // case : incr + var (not allowed: incr-var)
12975 incr_var=varRefExp;
12976 stepast=isSgBinaryOp(arithOp)->get_lhs_operand();
12977 }
12978 }
12979 break;
12980 } // end of V_AssignOp
12981 default:
12982 return false;
12983 }
12984
12985 if (incr_var == NULL)
12986 return false;
12987 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12988 return false;
12989
12990
12991 // single entry and single exit?
12992 // only for C for loop for now
12993 // TODO: Fortran support later
12994 if (fs && !isStructuredBlock(fs->get_loop_body()) )
12995 return false;
12996
12997 // return loop information if requested
12998 if (ivar != NULL)
12999 *ivar = ivarname;
13000 if (lb != NULL)
13001 *lb = lbast;
13002 if (ub != NULL)
13003 *ub = ubast;
13004 if (step != NULL)
13005 *step = stepast;
13006 if (body != NULL) {
13007 *body = fs->get_loop_body();
13008 }
13009 return true;
13010}
13011
13014{
13015 ROSE_ASSERT(loop != NULL);
13016 ROSE_ASSERT(lb != NULL);
13017 SgForStatement* forstmt = isSgForStatement(loop);
13018 SgFortranDo* dostmt = isSgFortranDo(loop);
13019 // ROSE_ASSERT(forstmt!= NULL);
13020
13021 if (forstmt != NULL)
13022 {
13023 // two cases: init_stmt is
13024 // SgExprStatement (assignment) like i=0;
13025 // SgVariableDeclaration int i =0 or
13026 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignOp);
13027 if (testList.size()>0) // assignment statement
13028 {
13029 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13030 SgAssignOp * assignop = isSgAssignOp((*testList.begin()));
13031 ROSE_ASSERT(assignop);
13032 if( assignop->get_rhs_operand()->get_lvalue())
13033 lb->set_lvalue(true);
13034 assignop->set_rhs_operand(lb);
13035 lb->set_parent(assignop);
13036 //TODO what happens to the original rhs operand?
13037 }
13038 else // variable declaration case
13039 {
13040 // SgVariableDeclaration
13041 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignInitializer );
13042 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13043 SgAssignInitializer* init = isSgAssignInitializer((*testList.begin()));
13044 ROSE_ASSERT(init != NULL);
13045 init->set_operand(lb);
13046 lb->set_parent(init);
13047 //TODO what happens to the original rhs operand?
13048 }
13049 }
13050 else if (dostmt != NULL)
13051 {
13052 SgExpression* init = dostmt->get_initialization();
13053 ROSE_ASSERT (init != NULL);
13054 SgAssignOp * a_op = isSgAssignOp (init);
13055 ROSE_ASSERT (a_op!=NULL);
13056 a_op->set_rhs_operand(lb);
13057 lb->set_parent(a_op);
13058 //TODO delete the previous operand?
13059 }
13060 else
13061 {
13062 cerr<<"Error. SageInterface::setLoopLowerBound(), illegal loop type:"<< loop->class_name()<<endl;
13063 ROSE_ASSERT (false);
13064 }
13065}
13066
13069{
13070 ROSE_ASSERT(loop != NULL);
13071 ROSE_ASSERT(ub != NULL);
13072 SgForStatement* forstmt = isSgForStatement(loop);
13073 // ROSE_ASSERT(forstmt!= NULL);
13074 SgFortranDo* dostmt = isSgFortranDo(loop);
13075 if (forstmt != NULL)
13076 {
13077 // set upper bound expression
13078 SgBinaryOp * binop= isSgBinaryOp(isSgExprStatement(forstmt->get_test())->get_expression());
13079 ROSE_ASSERT(binop != NULL);
13080 binop->set_rhs_operand(ub);
13081 ub->set_parent(binop);
13082 }
13083 else if (dostmt != NULL)
13084 {
13085 dostmt->set_bound(ub);
13086 ub->set_parent(dostmt);
13087 //TODO delete the original bound expression
13088 }
13089 else
13090 {
13091 cerr<<"Error. SageInterface::setLoopUpperBound(), illegal loop type:"<< loop->class_name()<<endl;
13092 ROSE_ASSERT (false);
13093 }
13094
13095}
13096
13099{
13100 ROSE_ASSERT(loop != NULL);
13101 ROSE_ASSERT(stride != NULL);
13102 SgForStatement* forstmt = isSgForStatement(loop);
13103 SgFortranDo * dostmt = isSgFortranDo (loop);
13104 // ROSE_ASSERT(forstmt!= NULL);
13105 if (dostmt != NULL)
13106 {
13107 dostmt->set_increment(stride);
13108 stride->set_parent(dostmt);
13109 //TODO delete original increment expression
13110 }
13111 else if (forstmt != NULL)
13112 {
13113 // set stride expression
13114 // case 1: i++ change to i+=stride
13115 Rose_STL_Container<SgNode*> testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusPlusOp);
13116 if (testList.size()>0)
13117 {
13118 ROSE_ASSERT(testList.size() == 1); // should have only one
13119 SgVarRefExp *loopvarexp = isSgVarRefExp(SageInterface::deepCopy
13120 (isSgPlusPlusOp( *testList.begin())->get_operand()));
13121 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13122 forstmt->set_increment(plusassignop);
13123 }
13124
13125 // case 1.5: i-- also changed to i+=stride
13126 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusMinusOp);
13127 if (testList.size()>0)
13128 {
13129 ROSE_ASSERT(testList.size()==1);// should have only one
13130 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13131 (isSgMinusMinusOp(*testList.begin())->get_operand()));
13132 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13133 forstmt->set_increment(plusassignop);
13134 }
13135
13136 // case 2: i+=X
13137 testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusAssignOp);
13138 if (testList.size()>0)
13139 {
13140 ROSE_ASSERT(testList.size()==1);// should have only one
13141 SgPlusAssignOp * assignop = isSgPlusAssignOp(*(testList.begin()));
13142 ROSE_ASSERT(assignop!=NULL);
13143 assignop->set_rhs_operand(stride);
13144 }
13145
13146 // case 2.5: i-=X changed to i+=stride
13147 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusAssignOp);
13148 if (testList.size()>0)
13149 {
13150 ROSE_ASSERT(testList.size()==1);// should have only one
13151 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13152 (isSgMinusAssignOp(*testList.begin())->get_lhs_operand()));
13153 SgExprStatement* exprstmt = isSgExprStatement((*testList.begin())->get_parent());
13154 ROSE_ASSERT(exprstmt !=NULL);
13155 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13156 exprstmt->set_expression(plusassignop);
13157 }
13158
13159#if 0 // [Robb Matzke 2021-03-17]
13160 // DQ (1/3/2007): I think this is a meaningless statement.
13161 testList.empty();
13162#endif
13163 // case 3: i=i + X or i =X +i i
13164 // TODO; what if users use i*=,etc ??
13165 // send out a warning: not canonical FOR/DO loop
13166 // or do this in the real frontend. MUST conform to canonical form
13167 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgAddOp);
13168 if (testList.size()>0)
13169 {
13170 ROSE_ASSERT(testList.size()==1);// should have only one ??
13171 // consider only the top first one
13172 SgAddOp * addop = isSgAddOp(*(testList.begin()));
13173 ROSE_ASSERT(addop!=NULL);
13174 string loopvar= (isSgVarRefExp(isSgAssignOp(addop->get_parent())->get_lhs_operand())->get_symbol()->get_name()).getString();
13175 if (isSgVarRefExp(addop->get_rhs_operand())!=NULL)
13176 {
13177 if ((isSgVarRefExp(addop->get_rhs_operand())->get_symbol()->get_name()).getString() ==loopvar)
13178 addop->set_lhs_operand(stride);
13179 else
13180 addop->set_rhs_operand(stride);
13181 }
13182 else
13183 addop->set_rhs_operand(stride);
13184 }
13185
13186 // case 3.5: i=i - X
13187 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgSubtractOp);
13188 if (testList.size()>0)
13189 {
13190 ROSE_ASSERT(testList.size()==1);// should have only one ??
13191 // consider only the top first one
13192 SgSubtractOp * subtractop = isSgSubtractOp(*(testList.begin()));
13193 ROSE_ASSERT(subtractop!=NULL);
13194 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13195 (isSgSubtractOp(*testList.begin())->get_lhs_operand()));
13196 SgAssignOp *assignop = isSgAssignOp((*testList.begin())->get_parent());
13197 ROSE_ASSERT(assignop !=NULL);
13198 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13199 assignop->set_rhs_operand(plusassignop);
13200 }
13201 }
13202 else
13203 {
13204 cerr<<"Error. SageInterface::setLoopStride(), illegal loop type:"<< loop->class_name()<<endl;
13205 ROSE_ASSERT (false);
13206
13207 }
13208}
13209
13213bool SageInterface::isAssignmentStatement(SgNode* s, SgExpression** lhs/*=NULL*/, SgExpression** rhs/*=NULL*/, bool* readlhs/*=NULL*/)
13214{
13215 SgExprStatement *n = isSgExprStatement(s);
13216 SgExpression *exp = (n != 0)? n->get_expression() : isSgExpression(s);
13217 if (exp != 0) {
13218 switch (exp->variantT()) {
13219 case V_SgPlusAssignOp:
13220 case V_SgMinusAssignOp:
13221 case V_SgAndAssignOp:
13222 case V_SgIorAssignOp:
13223 case V_SgMultAssignOp:
13224 case V_SgDivAssignOp:
13225 case V_SgModAssignOp:
13226 case V_SgXorAssignOp:
13227 case V_SgAssignOp:
13228 {
13229 SgBinaryOp* s2 = isSgBinaryOp(exp);
13230 if (lhs != 0)
13231 *lhs = s2->get_lhs_operand();
13232 if (rhs != 0) {
13233 SgExpression* init = s2->get_rhs_operand();
13234 if ( init->variantT() == V_SgAssignInitializer)
13235 init = isSgAssignInitializer(init)->get_operand();
13236 *rhs = init;
13237 }
13238 if (readlhs != 0)
13239 *readlhs = (exp->variantT() != V_SgAssignOp);
13240 return true;
13241 }
13242 default:
13243 return false;
13244 }
13245 }
13246 return false;
13247}
13248
13249
13250void
13252 {
13253 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,V_SgGotoStatement);
13254 for (size_t i = 0; i < gotos.size(); ++i)
13255 {
13256 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13257 SgLabelStatement* ls = gs->get_label();
13258 SgBasicBlock* lsParent = isSgBasicBlock(ls->get_parent());
13259 if (!lsParent) continue;
13260 SgStatementPtrList& bbStatements = lsParent->get_statements();
13261
13262 size_t j = std::find(bbStatements.begin(), bbStatements.end(), ls) - bbStatements.begin();
13263
13264 ROSE_ASSERT (j != bbStatements.size());
13265
13266 while (j < bbStatements.size() - 1 && isSgLabelStatement(bbStatements[j + 1]))
13267 {
13268 ++j;
13269 }
13270 gs->set_label(isSgLabelStatement(bbStatements[j]));
13271 }
13272 }
13273
13274bool SageInterface::mergeDeclarationAndAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt, bool removeAssignStmt /*= true*/)
13275{
13276 return mergeAssignmentWithDeclaration (assign_stmt, decl, removeAssignStmt);
13277}
13279
13283bool SageInterface::mergeAssignmentWithDeclaration(SgExprStatement* assign_stmt, SgVariableDeclaration* decl, bool removeAssignStmt /*= true*/)
13284{
13285 bool rt= true;
13286 ROSE_ASSERT(decl != NULL);
13287 ROSE_ASSERT(assign_stmt != NULL);
13288
13289 // Sanity check of assign statement: must be a form of var = xxx;
13290 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13291 if (assign_op == NULL)
13292 return false;
13293 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13294 if (assign_op_var == NULL) return false;
13295
13296 // Sanity check of the variable declaration: it should not have an existing initializer
13298 if (decl_var->get_initptr()!= NULL ) return false;
13299
13300 // check if two variables match
13301 // In translation, it is possible the declaration has not yet been inserted into its scope.
13302 // finding its symbol can return NULL.
13303 // But we still want to do the merge.
13304 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13305 if (decl_var_symbol!=NULL)
13306 {
13307 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13308 if (assign_op_var->get_symbol() != decl_var_symbol) return false;
13309 }
13310 else
13311 { // fallback to comparing variable names instead
13312 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13313 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name()) return false;
13314 }
13315
13316 // Everything looks fine now. Do the merge.
13318
13319 // Must preserve the proprecessing information of the original assign_stmt
13320 // use appending (not prepending) so the order of decl's comments and assign_stmt's comments can be preserved
13321 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13322
13323 // removeStatement() does not support removing a statement which is not inside a container.
13324 // But sometimes we do need to remove such a statement and replace it with a new one.
13325 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13326 // TODO: improve removeStatement() which uses low level rewritting.
13327 if (removeAssignStmt)
13328 SageInterface::removeStatement (assign_stmt);
13329// SageInterface::deepDelete (assign_stmt);
13331 decl_var->set_initptr(initor);
13332 initor->set_parent(decl_var);
13333
13334 return rt;
13335}
13336
13338{
13339 bool rt= true;
13340
13341 // Sanity check of assign statement: must be a form of var = xxx;
13342 ROSE_ASSERT(assign_stmt != NULL);
13343 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13344 if (assign_op == NULL)
13345 return false;
13346 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13347 if (assign_op_var == NULL)
13348 return false;
13349
13350 // Sanity check of the variable declaration: it should not have an existing initializer
13351 ROSE_ASSERT(decl != NULL);
13353 if (decl_var->get_initptr()!= NULL)
13354 return false;
13355
13356 // check if two variables match
13357 // In translation, it is possible the declaration has not yet been inserted into its scope.
13358 // finding its symbol can return NULL.
13359 // But we still want to do the merge.
13360 ROSE_ASSERT(decl_var != NULL);
13361 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13362 if (decl_var_symbol != NULL) {
13363 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13364 if (assign_op_var->get_symbol() != decl_var_symbol)
13365 return false;
13366 }
13367 else
13368 { // fallback to comparing variable names instead
13369 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13370 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name())
13371 return false;
13372 }
13373
13374 // Everything looks fine now. Do the merge.
13375 // It is implemented by
13376 // 1. copy rhs to the decl's rhs,
13377 // 2. then move the decl to the place of the assignment,
13378 // 3. then remove the assignment
13379 //
13380 // Copy rhs to be initializer
13383 decl_var->set_initptr(initor);
13384 initor->set_parent(decl_var);
13385
13386 // move proprocessing info. attached before decl to its next statement's front, using prepending to preserve the original order
13387 SgStatement* next_stmt = SageInterface::getNextStatement (decl);
13388 SageInterface::movePreprocessingInfo(decl, next_stmt, PreprocessingInfo::before, PreprocessingInfo::before, true);
13389
13390 // removeStatement() does not support removing a statement which is not inside a container.
13391 // But sometimes we do need to remove such a statement and replace it with a new one.
13392 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13393 // TODO: improve removeStatement() which uses low level rewritting.
13394
13395 // Now move the declaration to a new position, right before the assignment statement
13397 SageInterface::insertStatementBefore(assign_stmt, decl, false);
13398
13399 // preserve preprocessing info. attached to assign_stmt before removing it , using append (last false)
13400 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13401
13402 // Original assignment statement should be removed
13403 SageInterface::removeStatement (assign_stmt);
13404 // SageInterface::deepDelete (decl);
13405
13406 return rt;
13407}
13408// Split a variable declaration with an rhs assignment into two statements: a declaration and an assignment.
13409// Return the generated assignment statement, if any
13411{
13412 SgExprStatement* rt = NULL;
13413 ROSE_ASSERT (decl != NULL);
13414
13416 SgInitializer* initor = decl_var ->get_initptr();
13417 if (initor == NULL)
13418 rt = NULL;
13419 else
13420 {
13421 // Liao, 2021/10/21, we have to support all sorts of initializers, including aggregate initializer
13422 SgExpression * rhs=NULL;
13423 if (SgAssignInitializer * ainitor = isSgAssignInitializer (initor))
13424 rhs = ainitor->get_operand();
13425 else
13426 rhs = initor;
13427
13428 // we deep copy the rhs operand
13429 rt = buildAssignStatement (buildVarRefExp(decl_var) , deepCopy(rhs));
13430 decl_var->set_initptr(NULL);
13431 //TODO clean up initor
13432 insertStatementAfter ( decl, rt );
13433 }
13434 return rt;
13435}
13437ROSE_DLL_API int SageInterface::splitVariableDeclaration (SgScopeStatement* scope, bool topLevelOnly /* = true */)
13438{
13439 int count = 0;
13440 if (!topLevelOnly)
13441 {
13442 cerr<<"SageInterface::splitVariableDeclaration() topLevelOnly == false is not yet implemented."<<endl;
13443 ROSE_ASSERT (false);
13444 }
13445
13446 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVariableDeclaration);
13447 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13448 {
13449 SgVariableDeclaration *decl= isSgVariableDeclaration(*i);
13450 if (topLevelOnly)
13451 {
13452 ROSE_ASSERT(decl != NULL);
13453 if (decl->get_scope() == scope)
13454 {
13456 count ++;
13457 }
13458 }
13459 }
13460 return count;
13461}
13462
13463void SageInterface::collectVarRefs(SgLocatedNode* root, std::vector<SgVarRefExp* > & result)
13464{
13465 ROSE_ASSERT (root != NULL);
13466// std::vector<SgVarRefExp* > result;
13467
13468 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgVarRefExp);
13469 // AST query won't find variables used in types
13471
13472 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13473 {
13474 SgVarRefExp *vRef = isSgVarRefExp(*i);
13475 ROSE_ASSERT (vRef != NULL);
13476 result.push_back(vRef);
13477 }
13478}
13479
13480int SageInterface::collectVariableReferencesInArrayTypes(SgLocatedNode* root, Rose_STL_Container<SgNode*> & currentVarRefList)
13481{
13482 int rt = 0;
13483 ROSE_ASSERT (root != NULL);
13484 Rose_STL_Container<SgNode*> constructorList= NodeQuery::querySubTree(root, V_SgConstructorInitializer);
13485 for (size_t i =0; i< constructorList.size(); i++)
13486 {
13487 SgConstructorInitializer * c_init = isSgConstructorInitializer (constructorList[i]);
13488 if (SgArrayType* a_type = isSgArrayType(c_init->get_expression_type()))
13489 {
13490 Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree (a_type->get_index(),V_SgVarRefExp);
13491 for (size_t j =0 ; j< varList.size(); j++)
13492 {
13493 SgVarRefExp* var_exp = isSgVarRefExp(varList[j]) ;
13494 currentVarRefList.push_back(var_exp);
13495//TODO: these variable references do have special scopes, how to communicate to users?
13496// specialVarRefScopeExp[var_exp] = c_init ;
13497 rt ++;
13498 }
13499 }
13500 }
13501 return rt;
13502}
13503
13504namespace SageInterface { // A few internal helper classes
13505
13507 {
13508 SgAndOp* op;
13509
13510 public:
13511 AndOpGenerator(SgAndOp* op): op(op) {}
13512
13513 virtual SgStatement* generate(SgExpression* lhs)
13514 {
13515 if (lhs==NULL)
13516 return NULL;
13517 SgTreeCopy treeCopy;
13518 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13519 ROSE_ASSERT (lhsCopy);
13520 SgIfStmt* tree =
13527 return tree;
13528 }
13529 };
13530
13532 {
13533 SgOrOp* op;
13534
13535 public:
13536 OrOpGenerator(SgOrOp* op): op(op) {}
13537
13538 virtual SgStatement* generate(SgExpression* lhs)
13539 {
13540 if (lhs==NULL)
13541 return NULL;
13542 SgTreeCopy treeCopy;
13543 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13544 ROSE_ASSERT (lhsCopy);
13545 SgIfStmt* tree =
13552 return tree;
13553 }
13554 };
13555
13557 {
13558 SgConditionalExp* op;
13559
13560 public:
13562
13563 virtual SgStatement* generate(SgExpression* lhs)
13564 {
13565 if (lhs==NULL)
13566 return NULL;
13567 SgTreeCopy treeCopy;
13568 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13569 ROSE_ASSERT (lhsCopy);
13570 SgIfStmt* tree =
13577 return tree;
13578 }
13579 };
13580
13581} // end of namespace for the helper classes
13582
13585{
13586 ROSE_ASSERT(from != NULL);
13587
13588#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
13589#if 0 // This is not accurate for template class specializations. We disable this assertion for now. The worst case is compilation error later.
13591 std::cerr << "Type " << from->get_type()->unparseToString() << " of expression " << from->unparseToString() << " is not copy constructible" << std::endl;
13592 ROSE_ASSERT (false);
13593 }
13594
13595 assert (SageInterface::isCopyConstructible(from->get_type())); // How do we report errors?
13596#endif
13597 SgStatement* stmt = getStatementOfExpression(from);
13598 assert (stmt);
13599 if (!isSgForInitStatement(stmt->get_parent())) {
13600 //SageInterface::ensureBasicBlockAsParent(stmt);
13601 // no return value is accepted. Only the optional transformation matters
13602 if (isBodyStatement(stmt) && !isSgBasicBlock(stmt))
13604 }
13605
13606 SgScopeStatement* parent = isSgScopeStatement(stmt->get_parent());
13607 // cout << "parent is a " << (parent ? parent->sage_class_name() : "NULL") << endl;
13608 if (!parent && isSgForInitStatement(stmt->get_parent()))
13609 parent = isSgScopeStatement(stmt->get_parent()->get_parent()->get_parent());
13610 assert (parent);
13611 // cout << "parent is a " << parent->sage_class_name() << endl;
13612 // cout << "parent is " << parent->unparseToString() << endl;
13613 // cout << "stmt is " << stmt->unparseToString() << endl;
13614 SgName varname = "rose_temp__";
13615 if (newName == "") {
13616 varname << ++SageInterface::gensym_counter;
13617 } else {
13618 varname = newName;
13619 }
13620
13621 SgType* vartype = from->get_type();
13622 SgNode* fromparent = from->get_parent();
13623 vector<SgExpression*> ancestors;
13624 for (SgExpression *expr = from, *anc = isSgExpression(fromparent); anc != 0;
13625 expr = anc, anc = isSgExpression(anc->get_parent()))
13626 {
13627 if ((isSgAndOp(anc) && expr != isSgAndOp(anc)->get_lhs_operand()) ||
13628 (isSgOrOp(anc) && expr != isSgOrOp(anc)->get_lhs_operand()) ||
13629 (isSgConditionalExp(anc) && expr != isSgConditionalExp(anc)->get_conditional_exp()))
13630 ancestors.push_back(anc); // Closest first
13631 }
13632 // cout << "This expression to split has " << ancestors.size() << " ancestor(s)" << endl;
13633 for (vector<SgExpression*>::reverse_iterator ai = ancestors.rbegin(); ai != ancestors.rend(); ++ai)
13634 {
13635 StatementGenerator* gen;
13636 switch ((*ai)->variantT()) {
13637 case V_SgAndOp:
13638 gen = new AndOpGenerator(isSgAndOp(*ai)); break;
13639 case V_SgOrOp:
13640 gen = new OrOpGenerator(isSgOrOp(*ai)); break;
13641 case V_SgConditionalExp:
13642 gen = new ConditionalExpGenerator(isSgConditionalExp(*ai)); break;
13643 default: assert (!"Should not happen"); abort();
13644 }
13646 delete gen;
13647 } // for
13648 if (ancestors.size() != 0) {
13649 return splitExpression(from);
13650 // Need to recompute everything if there were ancestors
13651 }
13652 SgVariableDeclaration* vardecl = SageBuilder::buildVariableDeclaration(varname, vartype, NULL, parent);
13654 ROSE_ASSERT (sym);
13655 SgInitializedName* initname = sym->get_declaration();
13656 ROSE_ASSERT (initname);
13658 replaceExpressionWithExpression(from, varref);
13659 // std::cout << "Unparsed 3: " << fromparent->sage_class_name() << " --- " << fromparent->unparseToString() << endl;
13660 // cout << "From is a " << from->sage_class_name() << endl;
13662 initname->set_initializer(ai);
13663 ai->set_parent(initname);
13664 myStatementInsert(stmt, vardecl, true);
13665 // vardecl->set_parent(stmt->get_parent());
13666 // FixSgTree(vardecl);
13667 // FixSgTree(parent);
13668 return ai;
13669
13670#else
13671 return NULL;
13672#endif
13673
13674} //splitExpression()
13675
13678 struct SplitStatementGenerator: public StatementGenerator {
13679 SgExpression* expr;
13680 virtual SgStatement* generate(SgExpression* answer) {
13681 using namespace SageBuilder;
13682 return buildBasicBlock(buildAssignStatement(answer, expr));
13683 }
13684 };
13685 SplitStatementGenerator gen;
13686 gen.expr = expr;
13688 }
13689
13691 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,
13692 V_SgGotoStatement);
13693 map<SgLabelStatement*, SgLabelStatement*> labelsToReplace; for
13694 (size_t i = 0; i < gotos.size(); ++i) {
13695 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13696 SgBasicBlock* gsParent = isSgBasicBlock(gs->get_parent());
13697 if (!gsParent) continue;
13698 SgStatementPtrList& bbStatements = gsParent->get_statements();
13699 size_t j = std::find(bbStatements.begin(), bbStatements.end(), gs)
13700 - bbStatements.begin();
13701 ROSE_ASSERT (j != bbStatements.size());
13702 if (j == 0) continue;
13703 if (isSgLabelStatement(bbStatements[j - 1])) {
13704 labelsToReplace[isSgLabelStatement(bbStatements[j - 1])] =
13705 gs->get_label();
13706 }
13707 }
13708 for (size_t i = 0; i < gotos.size(); ++i) {
13709 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13710 SgLabelStatement* oldLabel = gs->get_label();
13711 while (labelsToReplace.find(oldLabel) != labelsToReplace.end()) {
13712 oldLabel = labelsToReplace[oldLabel];
13713 }
13714 gs->set_label(oldLabel);
13715 }
13716 }
13717
13719 switch (e->variantT()) {
13720#ifdef _MSC_VER
13721 // DQ (11/28/2009): This fixes a warning in MSVC (likely p_value should be a "bool" instead of an "int").
13722 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() != 0);
13723#else
13724 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() == true);
13725#endif
13726 case V_SgIntVal: return isSgIntVal(e)->get_value() != 0;
13727 case V_SgCastExp: return isConstantTrue(isSgCastExp(e)->get_operand());
13728 case V_SgNotOp: return isConstantFalse(isSgNotOp(e)->get_operand());
13729 case V_SgAddressOfOp: return true;
13730 default: return false;
13731 }
13732 }
13733
13735 switch (e->variantT()) {
13736 case V_SgBoolValExp: return isSgBoolValExp(e)->get_value() == false;
13737 case V_SgIntVal: return isSgIntVal(e)->get_value() == 0;
13738 case V_SgCastExp: return
13739 isConstantFalse(isSgCastExp(e)->get_operand());
13740 case V_SgNotOp: return isConstantTrue(isSgNotOp(e)->get_operand());
13741 default: return false;
13742 }
13743 }
13744
13746 SgExpression* e) {
13747 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13748 if (!fc) return false;
13749 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13750 if (fr == NULL) return false;
13751 return fr->get_symbol()->get_declaration() == decl;
13752 }
13753
13754 bool SageInterface::isCallToParticularFunction(const std::string& qualifiedName, size_t
13755 arity, SgExpression* e) {
13756 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13757 if (!fc) return false;
13758 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13759 if (fr == NULL) return false;
13760 string name =
13761 fr->get_symbol()->get_declaration()->get_qualified_name().getString();
13762 return (name == qualifiedName &&
13763 fc->get_args()->get_expressions().size() == arity);
13764 }
13765
13767 {
13768 ROSE_ASSERT( e != NULL);
13769 // We enforce that the source expression is fully attached to the AST
13770 // Too strict, the source expression can be just built and not attached.
13771 // Liao, 9/21/2009
13772// ROSE_ASSERT( e->get_parent() != NULL);
13773 return deepCopy(e);
13774 }
13775
13777 {
13778 return deepCopy(s);
13779 }
13780
13781 //----------------- add into AST tree --------------------
13783 {
13784 ROSE_ASSERT(expList);
13785 ROSE_ASSERT(exp);
13786 expList->append_expression(exp);
13787 exp->set_parent(expList);
13788 }
13789
13790 void SageInterface::appendExpressionList(SgExprListExp *expList, const std::vector<SgExpression*>& exp)
13791 {
13792 for (size_t i = 0; i < exp.size(); ++i)
13793 appendExpression(expList, exp[i]);
13794 }
13795
13796# if 0
13797 // DQ (11/25/2011): Moved to the header file so that it could be seen as a template function.
13798
13799 // TODO consider the difference between C++ and Fortran
13800 // fixup the scope of arguments,no symbols for nondefining function declaration's arguments
13801template <class actualFunction>
13802void
13803// SageInterface::setParameterList(SgFunctionDeclaration * func,SgFunctionParameterList * paralist)
13804SageInterface::setParameterList(actualFunction * func,SgFunctionParameterList * paralist)
13805 {
13806 // DQ (11/25/2011): Modified this to be a templated function so that we can handle both
13807 // SgFunctionDeclaration and SgTemplateFunctionDeclaration (and their associated member
13808 // function derived classes).
13809
13810 ROSE_ASSERT(func);
13811 ROSE_ASSERT(paralist);
13812
13813 // Warn to users if a paralist is being shared
13814 if (paralist->get_parent() !=NULL)
13815 {
13816 cerr << "Waring! Setting a used SgFunctionParameterList to function: "
13817 << (func->get_name()).getString()<<endl
13818 << " Sharing parameter lists can corrupt symbol tables!"<<endl
13819 << " Please use deepCopy() to get an exclusive parameter list for each function declaration!"<<endl;
13820 // ROSE_ASSERT(false);
13821 }
13822
13823 // Liao,2/5/2008 constructor of SgFunctionDeclaration will automatically generate SgFunctionParameterList, so be cautious when set new paralist!!
13824 if (func->get_parameterList() != NULL)
13825 if (func->get_parameterList() != paralist)
13826 delete func->get_parameterList();
13827
13828 func->set_parameterList(paralist);
13829 paralist->set_parent(func);
13830 }
13831#endif
13832
13833// static
13834SgVariableSymbol* addArg(SgFunctionParameterList *paraList, SgInitializedName* initName, bool isPrepend)
13835 {
13836 ROSE_ASSERT(paraList != NULL);
13837 ROSE_ASSERT(initName != NULL);
13838
13839 if (isPrepend == true)
13840 paraList->prepend_arg(initName);
13841 else
13842 paraList->append_arg(initName);
13843
13844 // DQ (12/4/2011): If this is going to be set, make sure it will not be over written.
13845 // initName->set_parent(paraList);
13846 if (initName->get_parent() == NULL)
13847 initName->set_parent(paraList);
13848
13849 ROSE_ASSERT(initName->get_parent() == paraList);
13850
13851 SgFunctionDeclaration* func_decl= isSgFunctionDeclaration(paraList->get_parent());
13852
13853 // DQ (12/4/2011): This will not be true for function parameter lists in SgTemplateFunctionDeclaration cases.
13854 // Also in typical use the SgFunctionDeclaration is not known yet so the parent is not set.
13855 // ROSE_ASSERT(paraList->get_parent() != NULL);
13856 // ROSE_ASSERT(func_decl != NULL);
13857
13858 SgScopeStatement* scope = NULL;
13859 if (func_decl != NULL)
13860 {
13861 if ((func_decl->get_definingDeclaration()) == func_decl )
13862 {
13863 // defining function declaration, set scope and symbol table
13864 SgFunctionDefinition* func_def = func_decl->get_definition();
13865 ROSE_ASSERT(func_def);
13866 scope = func_def;
13867 }
13868 else
13869 {
13870 // nondefining declaration, set scope only, currently set to decl's scope, TODO
13871 scope = func_decl->get_scope();
13872 }
13873
13874 // fix up declptr of the init name
13875 initName->set_declptr(func_decl);
13876 }
13877
13878 // 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
13879 // that initName already has a scope.
13880 //
13881 // DQ (12/4/2011): Added check...(fails for case of SgTypeEllipse).
13882 // ROSE_ASSERT(initName->get_scope() != NULL);
13883 // ROSE_ASSERT(initName->get_scope() != NULL || isSgTypeEllipse(initName->get_type()) != NULL);
13884
13885 // ROSE_ASSERT (scope); -- scope may not be set because the function declaration may not have been inserted anywhere
13886
13887 initName->set_scope(scope);
13888 if (scope != NULL)
13889 {
13890 SgVariableSymbol* sym = isSgVariableSymbol(initName->get_symbol_from_symbol_table());
13891 if (sym == NULL)
13892 {
13893 sym = new SgVariableSymbol(initName);
13894 scope->insert_symbol(initName->get_name(), sym);
13895 sym->set_parent(scope->get_symbol_table());
13896 }
13897 return sym;
13898 }
13899 else
13900 {
13901 return NULL;
13902 }
13903 }
13904
13906{
13907 return addArg(paraList,initName,false);
13908}
13909
13911{
13912 return addArg(paraList,initName,true);
13913}
13914
13916{
13917 ROSE_ASSERT(decl);
13918 ROSE_ASSERT(pragma);
13919 if (decl->get_pragma()!=NULL) delete (decl->get_pragma());
13920 decl->set_pragma(pragma);
13921 pragma->set_parent(decl);
13922}
13923
13924
13926//TODO should we ensureBasicBlockAsScope(scope) ? like ensureBasicBlockAsParent(targetStmt);
13927//It might be well legal to append the first and only statement in a scope!
13929 {
13930 // DQ (4/3/2012): Simple globally visible function to call (used for debugging in ROSE).
13931 void testAstForUniqueNodes ( SgNode* node );
13932
13933#if 0
13934 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
13935#endif
13936
13937 // DQ (6/19/2012): Exit as a test...
13938 // ROSE_ASSERT(isSgClassDeclaration(stmt) == NULL);
13939
13940 if (scope == NULL)
13941 {
13942#if 0
13943 printf (" --- scope was not specified as input! \n");
13944#endif
13946 }
13947
13948 ROSE_ASSERT(stmt != NULL);
13949 ROSE_ASSERT(scope != NULL);
13950
13951#if 0
13952 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
13953#endif
13954
13955#if 0
13956 // DQ (2/2/2010): This fails in the projects/OpenMP_Translator "make check" tests.
13957 // DQ (1/2/2010): Introducing test that are enforced at lower levels to catch errors as early as possible.
13958 SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(stmt);
13959 if (declarationStatement != NULL)
13960 {
13961 ROSE_ASSERT(declarationStatement->get_firstNondefiningDeclaration() != NULL);
13962 ROSE_ASSERT(declarationStatement->get_definingDeclaration() != NULL);
13963 }
13964#endif
13965
13966#if 0
13967 // This fix breaks other transformations.
13968 // It is better to do this explicitly as needed before calling appendStatement();
13969 // Liao 10/19/2010
13970 // In rare cases, we are moving the statement from its original scope to another scope
13971 // We have to remove it from its original scope before append it to the new scope
13972 SgNode* old_parent= stmt->get_parent();
13973 if (old_parent)
13974 {
13975 removeStatement(stmt);
13976 }
13977#endif
13978
13979#if 0
13980 // catch-all for statement fixup
13981 // Must fix it before insert it into the scope,
13982 fixStatement(stmt,scope);
13983
13984 //-----------------------
13985 // append the statement finally
13986 // scope->append_statement (stmt);
13987 scope->insertStatementInScope(stmt,false);
13988 stmt->set_parent(scope); // needed?
13989#else
13990 // DQ (7/12/2012): Skip adding when this is a non-autonomous type declaration.
13991 bool skipAddingStatement = false;
13992 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
13993 if (classDeclaration != NULL)
13994 {
13995 // DQ (7/9/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
13996#if 0
13997 if (classDeclaration->get_parent() != NULL)
13998 {
13999 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());
14000 }
14001#endif
14002
14003#if 1
14004 // DQ (6/9/2013): This is the original code...
14005 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false);
14006#else
14007 // 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).
14008 // This fails to add enough statements to the AST.
14009 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false) || (classDeclaration->get_parent() != NULL);
14010#endif
14011
14012 // DQ (6/26/2013): Don't just check for SgTemplateInstantiationDecl, but also for SgClassDeclaration.
14013 // DQ (6/9/2013): Check if this is a SgTemplateInstantiationDecl, since it might be appearing
14014 // twice as a result of a template argument being instantiated and we only want to add it into
14015 // the scope once. This happens for test2013_198.C and I can't find a better solution.
14016 if (classDeclaration != NULL && scope->containsOnlyDeclarations() == true)
14017 {
14018 // Check if this instnatiated template has already been added to the scope.
14019
14020 // DQ (6/26/2013): This is a newer alternative to test for an existing statement in a scope.
14021 // const SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
14022 // SgDeclarationStatementPtrList::const_iterator existingDeclaration = find(declarationList.begin(),declarationList.end(),classDeclaration);
14023 bool statementAlreadyExistsInScope = scope->statementExistsInScope(classDeclaration);
14024 if (statementAlreadyExistsInScope == true)
14025 {
14026 if (isSgTemplateInstantiationDecl(classDeclaration) != NULL)
14027 {
14028// DQ (9/13/2014): Clean up this output when not printing developer warnings.
14029// #if 1
14030#if PRINT_DEVELOPER_WARNINGS
14031 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",
14032 classDeclaration,classDeclaration->class_name().c_str(),scope,scope->class_name().c_str());
14033#endif
14034 }
14035#if 1
14036 else
14037 {
14038#if 1
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 }
14043#endif
14044 skipAddingStatement = true;
14045 }
14046 }
14047 }
14048 else
14049 {
14050 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(stmt);
14051 if (enumDeclaration != NULL)
14052 {
14053 // DQ (7/12/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14054 skipAddingStatement = (enumDeclaration->get_isAutonomousDeclaration() == false);
14055 }
14056 }
14057
14058#if 0
14059 // DQ (6/26/2013): This is an attempt to support better testing of possible redundant statements
14060 // that would be inserted into the current scope. This is however a bit expensive so we are using
14061 // this as a way to also debug the new cases where this happens.
14062 bool statementAlreadyExistsInScope = scope->statementExistsInScope(stmt);
14063 if (skipAddingStatement == false && statementAlreadyExistsInScope == true)
14064 {
14065#if 0
14066 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",
14067 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14068#endif
14069#if 0
14070 printf ("Exiting as a test! \n");
14071 ROSE_ABORT();
14072#endif
14073 skipAddingStatement = true;
14074 }
14075#endif
14076
14077#if 0
14078 printf (" --- skipAddingStatement = %s \n",skipAddingStatement ? "true" : "false");
14079#endif
14080
14081 if (skipAddingStatement == false)
14082 {
14083 // catch-all for statement fixup
14084 // Must fix it before insert it into the scope,
14085 // printf ("In appendStatementList(): Calling fixStatement() \n");
14086 fixStatement(stmt,scope);
14087 // printf ("DONE: In appendStatementList(): Calling fixStatement() \n");
14088
14089 //-----------------------
14090 // append the statement finally
14091 // scope->append_statement (stmt);
14092#if 0
14093 printf (" --- calling insertStatementInScope(): scope = %p = %s stmt = %p = %s \n",scope,scope->class_name().c_str(),stmt,stmt->class_name().c_str());
14094#endif
14095 scope->insertStatementInScope(stmt,false);
14096
14097 // DQ (6/9/2013): Added comment only: This is needed because some declaration have to have the
14098 // setting of there paremtn pointes delayed until now based on if they appear nested inside of
14099 // other declarations (e.g. "typedef struct { int x; } y;").
14100 stmt->set_parent(scope); // needed?
14101 }
14102#endif
14103
14104 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14105 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14106 // this). Also since this is only operating within a single scope it is likely too specific to C
14107 // instead of addressing the details of C++ where functions can be placed in alternative scopes and
14108 // use name qualification).
14109 // update the links after insertion!
14111 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14112 {
14113 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14114 }
14115
14116#if 0
14117 // DQ (6/26/2013): Turn on this test for debugging ROSE compiling rose.h header file.
14118 // Note that this is a stronger AST subtree test and not the weaker test for a redundant
14119 // statement in a single scope.
14120 // DQ (9/1/2012): this is a debugging mode that we need to more easily turn on and off.
14121 // DQ (4/3/2012): Added test to make sure that the pointers are unique.
14122 testAstForUniqueNodes(scope);
14123#else
14124 // printf ("In SageInterface::appendStatement(): Skipping test for unique statements in subtree \n");
14125#endif
14126 }
14127
14130{
14131 ROSE_ASSERT (stmt != NULL);
14132 ROSE_ASSERT (for_init_stmt != NULL);
14133
14134#if 0
14135 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());
14136#endif
14137
14138 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14139 // to record it being moved (and thus the macroExpansions that it might be associated with having
14140 // to force the macroExpansion's associated statements to be marked as a transformation.
14142
14143#if 0
14144 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());
14145#endif
14146
14147 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14148 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14149 // prepend, we only need to look at the scope.
14151
14152 for_init_stmt->append_init_stmt (stmt);
14153}
14154
14155void
14156SageInterface::appendStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14157 {
14158 for (size_t i = 0; i < stmts.size(); ++i)
14159 {
14160#if 0
14161#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14162 printf ("In appendStatementList(): stmts[i = %" PRIuPTR "] = %p = %s \n",i,stmts[i],stmts[i]->class_name().c_str());
14163 // printf ("In appendStatementList(): stmts[i = %" PRIuPTR "]->get_parent() = %p \n",i,stmts[i]->get_parent());
14164#endif
14165#endif
14166 appendStatement(stmts[i], scope); // Liao 5/15/2013, defer the logic of checking parent pointers to appendStatement()
14167#if 0
14168 if (stmts[i]->get_parent() != NULL)
14169 {
14170#if 0
14171#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14172 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());
14173#endif
14174#endif
14175 appendStatement(stmts[i], scope);
14176 }
14177 else
14178 {
14179 printf (" --- WARNING: In appendStatementList(): stmts[i = %" PRIuPTR "] not added to scope (because stmts[i]->get_parent() == NULL) \n",i);
14180 }
14181#endif
14182 }
14183 }
14184
14187 {
14188 ROSE_ASSERT (stmt != NULL);
14189
14190#if 0
14191 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14192#endif
14193
14194 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.1") == false);
14195
14196 if (scope == NULL)
14197 {
14199 }
14200
14201 ROSE_ASSERT(scope != NULL);
14202 // TODO handle side effect like SageBuilder::appendStatement() does
14203
14204 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.1a") == false);
14205
14206 // Must fix it before insert it into the scope,
14207 // otherwise assertions in insertStatementInScope() would fail
14208 fixStatement(stmt,scope);
14209
14210#if 0
14211 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",
14212 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14213#endif
14214
14215 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.2") == false);
14216
14217 // DQ (12/1/2015): If this is a moved statement then cause it to update internal data structures
14218 // to record it being moved (and thus the macroExpansions that it might be associated with having
14219 // to force the macroExpansion's associated statements to be marked as a transformation.
14221
14222#if 0
14223 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",
14224 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14225#endif
14226
14227 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.3") == false);
14228
14229 // DQ (12/1/2015): Also look at the statements on either side of the location where this statement
14230 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14231 // prepend, we only need to look at the scope.
14233
14234#if 0
14235 printf ("Calling insertStatementInScope() \n");
14236#endif
14237
14238 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.4") == false);
14239 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.4a") == false);
14240
14241 scope->insertStatementInScope(stmt,true);
14242 stmt->set_parent(scope); // needed?
14243
14244 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.5") == false);
14245
14246 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14247 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14248 // this). Also since this is only operating within a single scope it is likely too specific to C
14249 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14250 // use name qualification).
14251 // update the links after insertion!
14253 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14254 {
14255 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14256 }
14257
14258 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.6") == false);
14259
14260#if 0
14261 printf ("Leaving SageInterface::prependStatement() \n");
14262#endif
14263 } // prependStatement()
14264
14265
14268{
14269 ROSE_ASSERT (stmt != NULL);
14270 ROSE_ASSERT (for_init_stmt != NULL);
14271
14272#if 0
14273 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());
14274#endif
14275
14276 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14277 // to record it being moved (and thus the macroExpansions that it might be associated with having
14278 // to force the macroExpansion's associated statements to be marked as a transformation.
14280
14281#if 0
14282 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());
14283#endif
14284
14285 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14286 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14287 // prepend, we only need to look at the scope.
14289
14290 for_init_stmt->prepend_init_stmt (stmt);
14291}
14292
14293void SageInterface::prependStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14294 {
14295 for (size_t i = stmts.size(); i > 0; --i)
14296 {
14297 prependStatement(stmts[i - 1], scope);
14298 }
14299 }
14300
14305{
14306 bool rt = false;
14307 ROSE_ASSERT (scope != NULL);
14308 switch (scope->variantT())
14309 {
14310 case V_SgBasicBlock:
14311 case V_SgClassDefinition:
14312 case V_SgFunctionDefinition:
14313 case V_SgGlobal:
14314 case V_SgNamespaceDefinitionStatement: //?
14315 rt = true;
14316 break;
14317
14318 case V_SgAssociateStatement :
14319 case V_SgBlockDataStatement :
14320 case V_SgCatchOptionStmt:
14321 case V_SgDoWhileStmt:
14322 case V_SgForAllStatement:
14323 case V_SgForStatement:
14324 case V_SgFortranDo:
14325 case V_SgIfStmt:
14326 case V_SgSwitchStatement:
14327 case V_SgUpcForAllStatement:
14328 case V_SgWhileStmt:
14329 rt = false;
14330 break;
14331
14332 default:
14333 cout<<"unrecognized or unhandled scope type for SageInterface::hasSimpleChildrenList() "<<endl;
14334 break;
14335 }
14336 return rt;
14337}
14338
14339
14340// 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.
14342 {
14343 // When inserting a statement into global scope, if inserting at the top of scope it is best to insert
14344 // after the last statement from the preinclude file rose_edg_required_macros_and_functions.h.
14345
14346 SgDeclarationStatementPtrList & declarationList = globalScope->get_declarations();
14347
14348 SgStatement* last_statement = NULL;
14349 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
14350 // while (i != declarationList.end())
14351 while (i != declarationList.end() && (*i)->get_file_info() != NULL && (*i)->get_file_info()->isFrontendSpecific() == true)
14352 {
14353#if 0
14354 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");
14355#endif
14356 last_statement = *i;
14357
14358 i++;
14359 }
14360
14361 ROSE_ASSERT(last_statement != NULL);
14362#if 1
14363 printf ("last_statement = %p = %s \n",last_statement,last_statement->class_name().c_str());
14364#endif
14365#if 0
14366 printf ("Exiting as a test! \n");
14367 ROSE_ABORT();
14368#endif
14369
14370 return last_statement;
14371 }
14372
14373
14374 //TODO handle more side effect like SageBuilder::append_statement() does
14375 //Merge myStatementInsert()
14376 // insert SageInterface::insertStatement()
14377void SageInterface::insertStatement(SgStatement *targetStmt, SgStatement* newStmt, bool insertBefore, bool autoMovePreprocessingInfo /*= true */)
14378 {
14379 ROSE_ASSERT(targetStmt &&newStmt);
14380 ROSE_ASSERT(targetStmt != newStmt); // should not share statement nodes!
14381 SgNode* parent = targetStmt->get_parent();
14382 if (parent == NULL)
14383 {
14384 cerr << "Empty parent pointer for target statement. May be caused by the wrong order of target and new statements in insertStatement(targetStmt, newStmt)"<<endl;
14385 ROSE_ASSERT(parent);
14386 }
14387
14388 if (isSgLabelStatement(parent) != NULL)
14389 {
14390#if 0
14391 printf ("In SageInterface::insertStatement(): Detected case of label statement as parent, using parent of label statement \n");
14392#endif
14393 SgLabelStatement* labelStatement = isSgLabelStatement(parent);
14394 // parent = labelStatement->get_scope();
14395 parent = labelStatement->get_parent();
14396 ROSE_ASSERT(isSgLabelStatement(parent) == NULL);
14397 }
14398
14399#if 0
14400 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());
14401#endif
14402
14403 // DQ (12/2/2014): Not sure why this was here in the first place (likely debugging code from the fix for the SgLableStatement insertion.
14404 // SgFunctionDefinition* functionDefinition = SageInterface::getEnclosingProcedure(targetStmt);
14405 // ROSE_ASSERT(functionDefinition != NULL);
14406
14407 // Liao 3/2/2012. The semantics of ensureBasicBlockAsParent() are messy. input targetStmt may be
14408 // returned as it is if it is already a basic block as a body of if/while/catch/ etc.
14409 // We now have single statement true/false body for IfStmt etc
14410 // However, IfStmt::insert_child() is ambiguous and not implemented
14411 // So we make SgBasicBlock out of the single statement and
14412 // essentially call SgBasicBlock::insert_child() instead.
14413 // TODO: add test cases for If, variable, variable/struct inside if, etc
14414 // parent = ensureBasicBlockAsParent(targetStmt);
14415
14416 // must get the new scope after ensureBasicBlockAsParent ()
14417 SgScopeStatement* scope = targetStmt->get_scope();
14418 ROSE_ASSERT(scope);
14419
14420#if 0
14421 printf ("targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14422 printf ("scope = %p = %s \n",scope,scope->class_name().c_str());
14423#endif
14424
14425 // DQ (11/16/2014): This step is problematic if the targetStmt has been transformed to be associated with a SgLabelStatement.
14426 // The reason is that the targetStmt's parent will have been reset to be the SgLabelStatement and the logic in the set_parent()
14427 // function will assert fail when the parent is being set to itself (which is a good idea in general). A better solution might
14428 // 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
14429 // more sense in this special case of a SgLabelStatement.
14430 // newStmt->set_parent(targetStmt->get_parent());
14431 newStmt->set_parent(scope);
14432
14433 // 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.
14434 // The fix was the reuse the one that was found.
14435 fixStatement(newStmt,scope);
14436
14437 // DQ (9/16/2010): Added assertion that appears to be required to be true.
14438 // However, if this is required to be true then what about statements in
14439 // SgStatementExpression IR nodes?
14440 ROSE_ASSERT(isSgStatement(parent) != NULL);
14441
14442 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
14443 // appear before the statement to be attached to the inserted statement (and marked
14444 // to appear before that statement).
14445 ROSE_ASSERT(targetStmt != NULL);
14446 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
14447
14448#if 0
14449 printf ("In SageInterface::insertStatement(): after checking for associated comments \n");
14450 reportNodesMarkedAsModified(scope);
14451#endif
14452
14453 // TODO refactor this portion of code into a separate function
14454 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14455 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
14456 if (autoMovePreprocessingInfo) // Do this only if automatically handling of preprocessing information is request by users
14457 {
14458 if (comments != NULL && isSgBasicBlock(newStmt) == NULL)
14459 {
14460 vector<int> captureList;
14461#if 0
14462 printf ("Found attached comments (at %p = %s, inserting %p = %s insertBefore = %s): comments->size() = %" PRIuPTR " \n",
14463 targetStmt,targetStmt->class_name().c_str(),newStmt,newStmt->class_name().c_str(),insertBefore ? "true" : "false",comments->size());
14464#endif
14465 // DQ (9/17/2010): Assert that the new statement being inserted has no attached comments or CPP directives.
14466 if (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false)
14467 {
14468 // If the inserted statment has attached comments or CPP directives then this is gets a little
14469 // bit more comple and we don't support that at present.
14470 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");
14471 }
14472 // DQ (9/17/2010): commented out because it fails test in projects/OpenMP_Translator/for_firstprivate.c
14473 ROSE_ASSERT((newStmt->getAttachedPreprocessingInfo() == NULL) || (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false));
14474
14475 int commentIndex = 0;
14476 AttachedPreprocessingInfoType::iterator i;
14477 for (i = comments->begin(); i != comments->end(); i++)
14478 {
14479 ROSE_ASSERT ( (*i) != NULL );
14480#if 0
14481 printf (" Attached Comment (relativePosition=%s): %s\n",
14482 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
14483 (*i)->getString().c_str());
14484 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
14485 (*i)->get_file_info()->display("comment/directive location");
14486#endif
14487 PreprocessingInfo::RelativePositionType relativePosition = (insertBefore == true) ? PreprocessingInfo::before : PreprocessingInfo::after;
14488 if ((*i)->getRelativePosition() == relativePosition)
14489 {
14490 // accumulate into list
14491 captureList.push_back(commentIndex);
14492 }
14493
14494 commentIndex++;
14495 }
14496
14497 // printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
14498 if (captureList.empty() == false)
14499 {
14500 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
14501 // SgStatement* surroundingStatement = (insertBefore == true) ? getPreviousStatement(targetStmt) : getNextStatement(targetStmt);
14502 // SgStatement* surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14503 SgStatement* surroundingStatement = newStmt;
14504 ROSE_ASSERT(surroundingStatement != targetStmt);
14505 ROSE_ASSERT(surroundingStatement != NULL);
14506#if 0
14507 if (surroundingStatement == NULL)
14508 {
14509 // printf ("Warning: the surrounding statement for insertBefore = %s is NULL (so use the newStmt) \n",insertBefore ? "true" : "false");
14510 surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14511 }
14512#endif
14513 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
14514 // printf ("This is a valid surrounding statement = %s for insertBefore = %s \n",surroundingStatement->class_name().c_str(),insertBefore ? "true" : "false");
14515 vector<int>::iterator j = captureList.begin();
14516 while (j != captureList.end())
14517 {
14518 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
14519 // printf ("Attaching comments to newStmt = %p = %s \n",newStmt,newStmt->class_name().c_str());
14520 newStmt->addToAttachedPreprocessingInfo((*comments)[*j]);
14521
14522 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
14523 // printf ("Removing entry from comments list on targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14524 (*comments)[*j] = NULL;
14525
14526 j++;
14527 }
14528
14529 // Now remove each NULL entries in the comments vector.
14530 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
14531 for (size_t n = 0; n < captureList.size(); n++)
14532 {
14533 AttachedPreprocessingInfoType::iterator k = comments->begin();
14534 while (k != comments->end())
14535 {
14536 // Only modify the list once per iteration over the captureList
14537 if (*k == NULL)
14538 {
14539 comments->erase(k);
14540 break;
14541 }
14542 k++;
14543 }
14544 }
14545 }
14546 }
14547 else
14548 {
14549 // printf ("No attached comments (at %p of type: %s): \n",targetStmt,targetStmt->class_name().c_str());
14550 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14551 // I think that special rules apply to inserting a SgBasicBlock so disable comment relocation when inserting a SgBasicBlock.
14552 if (comments != NULL)
14553 {
14554 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");
14555 }
14556 }
14557 } // end if autoMovePreprocessingInfo
14558
14559
14560#if 0
14561 printf ("In SageInterface::insertStatement(): after processing associated comments \n");
14562 reportNodesMarkedAsModified(scope);
14563#endif
14564
14565 if (isSgIfStmt(parent))
14566 {
14567 if (isSgIfStmt(parent)->get_conditional()==targetStmt)
14568 {
14569 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14570 }
14571 else
14572 {
14573 if (isSgIfStmt(parent)->get_true_body()==targetStmt)
14574 {
14575 // Liao 3/2/2012
14576 // We have some choices:
14577 // 1) if the targeStmt is a basic block, we can append/prepend the new stmt
14578 // within the targetStmt. But this is not the exact semantics of insertStatment. It will break the outliner.
14579 // Since the targetStmt will have new content inside of it, which is not the semantics of
14580 // inserting anything before/or after it.
14581 // 2) always insert a padding basic block between parent and targetStmt
14582 // and we can legally insert before/after the target statement within the
14583 // padding basic block.
14584 //TODO: this insertion of padding basic block should ideally go into some AST normalization phase
14585 // so the transformation function (insertStatement) only does what it means to do, no more and no less.
14586 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14587 isSgIfStmt(parent)->set_true_body(newparent);
14588 newparent->set_parent(parent);
14589 insertStatement(targetStmt, newStmt,insertBefore);
14590 }
14591 else
14592 {
14593 if (isSgIfStmt(parent)->get_false_body()==targetStmt)
14594 {
14595 // ensureBasicBlockAsParent(targetStmt);
14596 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14597 isSgIfStmt(parent)->set_false_body(newparent);
14598 newparent->set_parent(parent);
14599 insertStatement(targetStmt, newStmt,insertBefore);
14600 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14601 }
14602 }
14603 }
14604 }
14605 else
14606 {
14607 if (isSgWhileStmt(parent))
14608 {
14609 if (isSgWhileStmt(parent)->get_condition()==targetStmt)
14610 {
14611 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14612 }
14613 else
14614 {
14615 if (isSgWhileStmt(parent)->get_body()==targetStmt)
14616 {
14617 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14618 isSgWhileStmt(parent)->set_body(newparent);
14619 newparent->set_parent(parent);
14620 insertStatement(targetStmt, newStmt,insertBefore);
14621 // ensureBasicBlockAsParent(targetStmt);
14622 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14623 }
14624 }
14625 }
14626 else
14627 {
14628 if (isSgDoWhileStmt(parent))
14629 {
14630 if (isSgDoWhileStmt(parent)->get_condition()==targetStmt)
14631 {
14632 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14633 }
14634 else
14635 {
14636 if (isSgDoWhileStmt(parent)->get_body()==targetStmt)
14637 {
14638 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14639 isSgDoWhileStmt(parent)->set_body(newparent);
14640 newparent->set_parent(parent);
14641 insertStatement(targetStmt, newStmt,insertBefore);
14642 // ensureBasicBlockAsParent(targetStmt);
14643 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14644 }
14645 }
14646 }
14647 else
14648 {
14649 if (isSgForStatement(parent))
14650 {
14651 if (isSgForStatement(parent)->get_loop_body()==targetStmt)
14652 {
14653 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14654 isSgForStatement(parent)->set_loop_body(newparent);
14655 newparent->set_parent(parent);
14656 insertStatement(targetStmt, newStmt,insertBefore);
14657 // ensureBasicBlockAsParent(targetStmt);
14658 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14659 }
14660 else
14661 {
14662 if (isSgForStatement(parent)->get_test()==targetStmt)
14663 {
14664 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14665 }
14666 }
14667 }
14668 else // \pp (2/24/2011) added support for UpcForAll
14669 {
14670 if (SgUpcForAllStatement* p = isSgUpcForAllStatement(parent))
14671 {
14672 //const bool stmt_present = (p->get_loop_body() == targetStmt || p->get_test() == targetStmt);
14673
14674 // \pp \todo what if !stmt_present
14675 // ROSE_ASSERT(stmt_present != NULL);
14676 insertStatement(p, newStmt, insertBefore);
14677 }
14678 else
14679 {
14680 if (SgOmpBodyStatement * p = isSgOmpBodyStatement (parent))
14681 {
14682 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14683 p->set_body(newparent);
14684 newparent->set_parent(parent);
14685 insertStatement(targetStmt, newStmt,insertBefore);
14686 }
14687 else
14688 {
14689 // It appears that all of the recursive calls are untimately calling this location.
14690 SgStatement* stmnt = isSgStatement(parent);
14691 ROSE_ASSERT(stmnt != NULL);
14692 stmnt->insert_statement(targetStmt,newStmt,insertBefore);
14693 }
14694 }
14695 }
14696 }
14697 }
14698 }
14699
14700 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14701 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14702 // this). Also since this is only operating within a single scope it is likely too specific to C
14703 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14704 // use name qualification).
14705 // update the links after insertion!
14707 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(newStmt) != NULL) )
14708 {
14709 updateDefiningNondefiningLinks(isSgFunctionDeclaration(newStmt),scope);
14710 }
14711
14712#if 0
14713 printf ("In SageInterface::insertStatement(): at BASE of function \n");
14714 reportNodesMarkedAsModified(scope);
14715#endif
14716 }
14717
14718
14719void SageInterface::insertStatementList(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts, bool insertBefore)
14720 {
14721 if (insertBefore)
14722 {
14723 for (size_t i = 0; i < newStmts.size(); ++i)
14724 {
14725 insertStatementBefore(targetStmt, newStmts[i]);
14726 }
14727 }
14728 else
14729 {
14730 for (size_t i = newStmts.size(); i > 0; --i)
14731 {
14732 insertStatementAfter(targetStmt, newStmts[i - 1]);
14733 }
14734 }
14735 }
14736
14737void SageInterface::insertStatementAfter(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true*/)
14738 {
14739 insertStatement(targetStmt,newStmt,false, autoMovePreprocessingInfo);
14740 }
14741
14742void SageInterface::insertStatementListAfter(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14743 {
14744 insertStatementList(targetStmt,newStmts,false);
14745 }
14746
14749 {
14750 ROSE_ASSERT (stmt != NULL);
14751 ROSE_ASSERT (scope != NULL);
14752 // Insert to be the declaration after current declaration sequence, if any
14753 SgStatement* l_stmt = findLastDeclarationStatement (scope);
14754 if (l_stmt)
14755 insertStatementAfter(l_stmt,stmt);
14756 else
14757 prependStatement(stmt, scope);
14758 }
14759
14761void SageInterface::insertStatementAfterLastDeclaration(std::vector<SgStatement*> stmt_list, SgScopeStatement* scope)
14762 {
14763 ROSE_ASSERT (scope != NULL);
14764 vector <SgStatement* >::iterator iter;
14765 SgStatement* prev_stmt = NULL;
14766 for (iter= stmt_list.begin(); iter != stmt_list.end(); iter++)
14767 {
14768 if (iter == stmt_list.begin())
14769 {
14771 }
14772 else
14773 {
14774 ROSE_ASSERT (prev_stmt != NULL);
14775 insertStatementAfter (prev_stmt, *iter);
14776 }
14777 prev_stmt = *iter;
14778 }
14779 }
14780
14782{
14783 ROSE_ASSERT(newStmt!=NULL);
14784 ROSE_ASSERT(scope!=NULL);
14785 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14786 if (!isSgDeclarationStatement(targetStmt)) {
14787 insertStatementBefore(targetStmt, newStmt, movePreprocessingInfo);
14788 return;
14789 }
14790 }
14791 appendStatement(newStmt, scope);
14792}
14793
14794void SageInterface::insertStatementListBeforeFirstNonDeclaration(const std::vector<SgStatement*> &newStmts,SgScopeStatement *scope)
14795{
14796 ROSE_ASSERT(scope!=NULL);
14797 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14798 if (!isSgDeclarationStatement(targetStmt)) {
14799 insertStatementListBefore(targetStmt, newStmts);
14800 return;
14801 }
14802 }
14803 appendStatementList(newStmts, scope);
14804}
14805
14806void SageInterface::insertStatementBefore(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true */)
14807 {
14808 insertStatement(targetStmt,newStmt,true, autoMovePreprocessingInfo);
14809 }
14810
14811void SageInterface::insertStatementListBefore(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14812 {
14813 insertStatementList(targetStmt,newStmts,true);
14814 }
14815
14816 //a wrapper for set_expression(), set_operand(), set_operand_exp() etc
14817 // special concern for lvalue, parent,
14818 // todo: warning overwriting existing operands
14820 {
14821 ROSE_ASSERT(target);
14822 ROSE_ASSERT(operand);
14823 ROSE_ASSERT(target!=operand);
14824 switch (target->variantT())
14825 {
14826 case V_SgActualArgumentExpression:
14827 isSgActualArgumentExpression(target)->set_expression(operand);
14828 break;
14829 case V_SgAsmOp:
14830 isSgAsmOp(target)->set_expression(operand);
14831 break;
14832 case V_SgSizeOfOp:
14833 isSgSizeOfOp(target)->set_operand_expr(operand);
14834 break;
14835 case V_SgTypeIdOp:
14836 isSgTypeIdOp(target)->set_operand_expr(operand);
14837 break;
14838 case V_SgVarArgOp:
14839 isSgVarArgOp(target)->set_operand_expr(operand);
14840 break;
14841 case V_SgVarArgStartOneOperandOp:
14842 isSgVarArgStartOneOperandOp(target)->set_operand_expr(operand);
14843 break;
14844 case V_SgAssignInitializer:
14845 isSgAssignInitializer (target)->set_operand(operand);
14846 break;
14847 default:
14848 if (isSgUnaryOp(target)!=NULL)
14849 isSgUnaryOp(target)->set_operand_i(operand);
14850 else
14851 {
14852 cerr<<"\tSageInterface::setOperand(): unhandled case for target expression of type "
14853 <<target->class_name()<<endl;
14854 ROSE_ABORT();
14855 }
14856 }// end switch
14857 operand->set_parent(target);
14858 markLhsValues(target);
14859 }
14860
14861 // binary and SgVarArgCopyOp, SgVarArgStartOp
14863 {
14864 ROSE_ASSERT(target);
14865 ROSE_ASSERT(lhs);
14866 ROSE_ASSERT(target!=lhs);
14867 bool hasrhs = false;
14868
14869 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14870 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14871 SgBinaryOp* binary = isSgBinaryOp(target);
14872
14873 if (varargcopy!=NULL)
14874 {
14875 varargcopy->set_lhs_operand(lhs);
14876 if( varargcopy->get_rhs_operand()!=NULL) hasrhs= true;
14877 }
14878 else if(varargstart!=NULL)
14879 {
14880 varargstart->set_lhs_operand(lhs);
14881 if( varargstart->get_rhs_operand()!=NULL) hasrhs= true;
14882 }
14883 else if(binary!=NULL)
14884 {
14885 binary->set_lhs_operand(lhs);
14886 if( binary->get_rhs_operand()!=NULL) hasrhs= true;
14887 }
14888 else
14889 {
14890 cout<<"SageInterface::setLhsOperand(): unhandled case for target expression of type "
14891 <<target->class_name()<<endl;
14892 ROSE_ABORT();
14893 }
14894 lhs->set_parent(target);
14895// only when both lhs and rhs are available, can we set lvalue
14896// there is assertion(rhs!=NULL) in markLhsValues()
14897 if (hasrhs)
14898 markLhsValues(target);
14899 }
14900
14902 {
14903 ROSE_ASSERT(target);
14904 ROSE_ASSERT(rhs);
14905 ROSE_ASSERT(target!=rhs);
14906 bool haslhs = false;
14907
14908 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14909 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14910 SgBinaryOp* binary = isSgBinaryOp(target);
14911
14912 if (varargcopy!=NULL)
14913 {
14914 varargcopy->set_rhs_operand(rhs);
14915 if( varargcopy->get_lhs_operand()!=NULL) haslhs= true;
14916 }
14917 else if(varargstart!=NULL)
14918 {
14919 varargstart->set_rhs_operand(rhs);
14920 if( varargstart->get_lhs_operand()!=NULL) haslhs= true;
14921 }
14922 else if(binary!=NULL)
14923 {
14924 binary->set_rhs_operand(rhs);
14925 if( binary->get_lhs_operand()!=NULL) haslhs= true;
14926 }
14927 else
14928 {
14929 cout<<"SageInterface::setRhsOperand(): unhandled case for target expression of type "
14930 <<target->class_name()<<endl;
14931 ROSE_ABORT();
14932 }
14933 rhs->set_parent(target);
14934// only when both lhs and rhs are available, can we set lvalue
14935 if (haslhs)
14936 markLhsValues(target);
14937 }
14938
14939// DQ (1/25/2010): Added to simplify handling of directories (e.g. for code generation).
14940void SageInterface::moveToSubdirectory ( std::string directoryName, SgFile* file )
14941 {
14942 // This support makes use of the new SgDirectory IR node. It causes the unparser to
14943 // generate a subdirectory and unparse the file into the subdirectory. It works
14944 // by internally calling the system function "system()" to call "mkdir directoryName"
14945 // and then chdir()" to change the current directory. These steps are handled by the
14946 // unparser.
14947
14948 // This function just does the transformation to insert a SgDirectory IR node between
14949 // the referenced SgFile and it's project (fixing up parents and file lists etc.).
14950
14951 // Add a directory and unparse the code (to the new directory)
14952 SgDirectory* directory = new SgDirectory(directoryName);
14953
14954 SgFileList* parentFileList = isSgFileList(file->get_parent());
14955 ROSE_ASSERT(parentFileList != NULL);
14956 directory->set_parent(file->get_parent());
14957
14958 SgProject* project = NULL;
14959 SgDirectory* parentDirectory = isSgDirectory(parentFileList->get_parent());
14960
14961 if (parentDirectory != NULL)
14962 {
14963 // Add a directory to the list in the SgDirectory node.
14964 parentDirectory->get_directoryList()->get_listOfDirectories().push_back(directory);
14965
14966 // Erase the reference to the file in the project's file list.
14967 // parentDirectory->get_fileList().erase(find(parentDirectory->get_fileList().begin(),parentDirectory->get_fileList().end(),file));
14968 }
14969 else
14970 {
14971 project = isSgProject(parentFileList->get_parent());
14972 ROSE_ASSERT(project != NULL);
14973
14974 // Add a directory to the list in the SgProject node.
14975 project->get_directoryList()->get_listOfDirectories().push_back(directory);
14976
14977 // Erase the reference to the file in the project's file list.
14978 // project->get_fileList().erase(find(project->get_fileList().begin(),project->get_fileList().end(),file));
14979 }
14980
14981 // Put the file into the new directory.
14982 directory->get_fileList()->get_listOfFiles().push_back(file);
14983
14984 // Erase the reference to the file in the project's file list.
14985 parentFileList->get_listOfFiles().erase(find(parentFileList->get_listOfFiles().begin(),parentFileList->get_listOfFiles().end(),file));
14986
14987 file->set_parent(directory);
14988}
14989
14990
14991//------------------------- AST repair----------------------------
14992//----------------------------------------------------------------
14994 {
14995 ROSE_ASSERT(structDecl != NULL);
14996 ROSE_ASSERT(scope != NULL);
14997 SgClassDeclaration* nondefdecl = isSgClassDeclaration(structDecl->get_firstNondefiningDeclaration());
14998 ROSE_ASSERT(nondefdecl != NULL);
14999
15000 // ROSE_ASSERT(structDecl->get_definingDeclaration() != NULL);
15001 SgClassDeclaration* defdecl = isSgClassDeclaration(structDecl->get_definingDeclaration());
15002 // ROSE_ASSERT(defdecl != NULL);
15003
15004 // Liao, 9/2/2009
15005 // fixup missing scope when bottomup AST building is used
15006 if (structDecl->get_scope() == NULL)
15007 structDecl->set_scope(scope);
15008 if (nondefdecl->get_scope() == NULL)
15009 nondefdecl->set_scope(scope);
15010
15011#if 0
15012 if (structDecl->get_parent() == NULL)
15013 structDecl->set_parent(scope);
15014 if (nondefdecl->get_parent() == NULL)
15015 nondefdecl->set_parent(scope);
15016#else
15017 // 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");
15018
15019 // DQ (7/21/2012): Can we assert this here? NO!
15020 // ROSE_ASSERT(structDecl->get_parent() == NULL);
15021 // ROSE_ASSERT(nondefdecl->get_parent() == NULL);
15022#endif
15023
15024 SgName name = structDecl->get_name();
15025
15026 // This is rare case (translation error) when scope->lookup_class_symbol(name) will find something
15027 // but nondefdecl->get_symbol_from_symbol_table() returns NULL
15028 // But symbols are associated with nondefining declarations whenever possible
15029 // and AST consistent check will check the nondefining declarations first
15030 // Liao, 9/2/2009
15031 // SgClassSymbol* mysymbol = scope->lookup_class_symbol(name);
15032 SgClassSymbol* mysymbol = isSgClassSymbol(nondefdecl->get_symbol_from_symbol_table());
15033
15034 // DQ (3/14/2014): This is false for a copy of a class declaration being inserted into the AST.
15035 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15036 // ROSE_ASSERT(mysymbol != NULL);
15037
15038 if (mysymbol == NULL)
15039 {
15040 printf ("Note: SageInterface::fixStructDeclaration(): structDecl = %p nondefdecl = %p (mysymbol == NULL) \n",structDecl,nondefdecl);
15041
15042 // 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...
15043 // DQ (12/4/2011): Only generate symbols and set the scope if this is the correct scope.
15044 ROSE_ASSERT(structDecl->get_scope() != NULL);
15045
15046 if (scope == structDecl->get_scope())
15047 {
15048 mysymbol = new SgClassSymbol(nondefdecl);
15049 ROSE_ASSERT(mysymbol);
15050
15051 // I need to check the rest of these functions.
15052 printf ("############## DANGER:DANGER:DANGER ################\n");
15053
15054 printf ("In SageInterface::fixStructDeclaration(): Adding class symbol to scope = %p = %s \n",scope,scope->class_name().c_str());
15055 scope->insert_symbol(name, mysymbol);
15056
15057 // ROSE_ASSERT(defdecl != NULL);
15058 if (defdecl)
15059 defdecl->set_scope(scope);
15060 nondefdecl->set_scope(scope);
15061
15062 printf ("*** WARNING: In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Commented out the setting of the parent to be the same as the scope \n");
15063#if 0
15064 if (defdecl)
15065 defdecl->set_parent(scope);
15066 nondefdecl->set_parent(scope);
15067#endif
15068 }
15069 else
15070 {
15071 printf ("In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Skipped building an associated symbol! \n");
15072 }
15073 }
15074
15075 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15076 ROSE_ASSERT(nondefdecl->get_type() != NULL);
15077
15078 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15079 ROSE_ASSERT(nondefdecl->get_type()->variantT() != V_SgNode);
15080
15081 // DQ (9/4/2012): This should be a SgClassType IR node.
15082 ROSE_ASSERT(isSgClassType(nondefdecl->get_type()) != NULL);
15083
15084 // fixup SgClassType, which is associated with the first non-defining declaration only
15085 // and the other declarations share it.
15086 if (nondefdecl->get_type() == NULL)
15087 {
15088 nondefdecl->set_type(SgClassType::createType(nondefdecl));
15089 }
15090 ROSE_ASSERT (nondefdecl->get_type() != NULL);
15091
15092 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15093 if (defdecl != NULL)
15094 {
15095 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15096 ROSE_ASSERT(defdecl->get_type()->variantT() != V_SgNode);
15097
15098 // DQ (9/4/2012): This should be a SgClassType IR node.
15099 ROSE_ASSERT(isSgClassType(defdecl->get_type()) != NULL);
15100 }
15101
15102 // ROSE_ASSERT(defdecl != NULL);
15103 if (defdecl != NULL)
15104 {
15105 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15106 ROSE_ASSERT(defdecl->get_type() != NULL);
15107 if (defdecl->get_type() != nondefdecl->get_type())
15108 {
15109 printf ("ERROR: defdecl->get_type() != nondefdecl->get_type(): what are these: \n");
15110 printf (" defdecl->get_type() = %p = %s \n",defdecl ->get_type(),defdecl ->get_type()->class_name().c_str());
15111 SgNamedType* namedType_definingDecl = isSgNamedType(defdecl->get_type());
15112 if (namedType_definingDecl != NULL)
15113 {
15114 printf ("namedType_definingDecl->get_declaration() = %p = %s \n",namedType_definingDecl->get_declaration(),namedType_definingDecl->get_declaration()->class_name().c_str());
15115 }
15116 printf (" nondefdecl->get_type() = %p = %s \n",nondefdecl->get_type(),nondefdecl->get_type()->class_name().c_str());
15117 SgNamedType* namedType_nondefiningDecl = isSgNamedType(nondefdecl->get_type());
15118 if (namedType_nondefiningDecl != NULL)
15119 {
15120 printf ("namedType_nondefiningDecl->get_declaration() = %p = %s \n",namedType_nondefiningDecl->get_declaration(),namedType_nondefiningDecl->get_declaration()->class_name().c_str());
15121 }
15122 }
15123 //ROSE_ASSERT(defdecl->get_type() == nondefdecl->get_type());
15124 }
15125 }
15126
15127
15129 {
15130 fixStructDeclaration(classDecl,scope);
15131 }
15132
15133
15135 {
15136 ROSE_ASSERT(structDecl);
15137 ROSE_ASSERT(scope);
15138 SgNamespaceDeclarationStatement* nondefdecl = isSgNamespaceDeclarationStatement(structDecl->get_firstNondefiningDeclaration());
15139 ROSE_ASSERT(nondefdecl);
15140 // Liao, 9/2/2009
15141 // fixup missing scope when bottomup AST building is used
15142 if (structDecl->get_parent() == NULL)
15143 structDecl->set_parent(scope);
15144 if (nondefdecl->get_parent() == NULL)
15145 nondefdecl->set_parent(scope);
15146
15147 // tps : (09/03/2009) Namespace should not have a scope
15148 /*
15149 if (structDecl->get_scope() == NULL)
15150 structDecl->set_scope(scope);
15151 if (nondefdecl->get_scope() == NULL)
15152 nondefdecl->set_scope(scope);
15153 */
15154
15155 SgName name= structDecl->get_name();
15156 // SgNamespaceSymbol* mysymbol = scope->lookup_namespace_symbol(name);
15157 SgNamespaceSymbol* mysymbol = isSgNamespaceSymbol(nondefdecl->get_symbol_from_symbol_table());
15158 if (mysymbol==NULL)
15159 {
15160 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15161 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15162 if (scope == structDecl->get_scope())
15163 {
15164 mysymbol = new SgNamespaceSymbol(name,nondefdecl);
15165 ROSE_ASSERT(mysymbol);
15166
15167 printf ("In SageInterface::fixNamespaceDeclaration(): inserting namespace symbol into scope = %p = %s \n",scope,scope->class_name().c_str());
15168 scope->insert_symbol(name, mysymbol);
15169
15170 SgNamespaceDeclarationStatement* defdecl = isSgNamespaceDeclarationStatement(structDecl->get_definingDeclaration());
15171 ROSE_ASSERT(defdecl);
15172 defdecl->set_scope(scope);
15173 nondefdecl->set_scope(scope);
15174
15175 defdecl->set_parent(scope);
15176 nondefdecl->set_parent(scope);
15177 }
15178 }
15179 }
15180
15181#define DEBUG__SageInterface__fixVariableDeclaration 0
15182
15184 {
15185 ROSE_ASSERT(varDecl != NULL);
15186 ROSE_ASSERT(scope != NULL);
15187
15188 SgInitializedNamePtrList namelist = varDecl->get_variables();
15189 SgTemplateVariableInstantiation * tplinst = isSgTemplateVariableInstantiation(varDecl);
15190
15191 // printf ("In SageInterface::fixVariableDeclaration(): Is this a recursive call! \n");
15192
15193#if DEBUG__SageInterface__fixVariableDeclaration
15194 printf ("In SageInterface::fixVariableDeclaration():\n");
15195 printf (" varDecl = %p scope = %p = %s \n", varDecl);
15196 printf (" scope = %p : %s \n", scope, scope->class_name().c_str());
15197#endif
15198
15199 ROSE_ASSERT(namelist.size() > 0);
15200
15201 SgInitializedNamePtrList::iterator i;
15202 for (i = namelist.begin(); i != namelist.end(); i++)
15203 {
15204 SgInitializedName *initName = *i;
15205 ROSE_ASSERT(initName != NULL);
15206#if DEBUG__SageInterface__fixVariableDeclaration
15207 printf (" initName = %p\n", initName);
15208 printf (" initName->get_scope() = %p : %s\n", initName->get_scope(), initName->get_scope() ? initName->get_scope()->class_name().c_str() : "");
15209#endif
15210
15211 SgName name = initName->get_name();
15212#if DEBUG__SageInterface__fixVariableDeclaration
15213 printf (" name = %s\n", name.str());
15214#endif
15215 if (tplinst) {
15216 name = appendTemplateArgumentsToName(name, tplinst->get_templateArguments());
15217 }
15218#if DEBUG__SageInterface__fixVariableDeclaration
15219 printf (" name = %s\n", name.str());
15220#endif
15221
15222 // DQ (11/19/2011): When used with C++, the variable may already have an associated scope
15223 // and be using name qualification, so might not be associated with the current scope.
15224 SgScopeStatement* requiredScope = scope;
15225 SgScopeStatement* preAssociatedScope = initName->get_scope();
15226 if (preAssociatedScope != NULL) {
15227 requiredScope = preAssociatedScope;
15228 }
15229
15230 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15231 initName->set_scope(requiredScope);
15232 if (topScopeStack() != NULL) {
15233 varDecl->set_parent(topScopeStack());
15234 ROSE_ASSERT(varDecl->get_parent() != NULL);
15235 }
15236 ROSE_ASSERT(requiredScope != NULL);
15237 SgVariableSymbol* varSymbol = requiredScope->lookup_variable_symbol(name);
15238#if DEBUG__SageInterface__fixVariableDeclaration
15239 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15240#endif
15241 if (varSymbol == NULL) {
15242 if (scope == initName->get_scope()) {
15243 if (isSgTemplateVariableDeclaration(varDecl)) {
15244 varSymbol = new SgTemplateVariableSymbol(initName);
15245 } else {
15246 varSymbol = new SgVariableSymbol(initName);
15247 }
15248 ROSE_ASSERT(varSymbol);
15249 scope->insert_symbol(name, varSymbol);
15250 }
15251 } else {
15252 SgInitializedName* prev_decl = varSymbol->get_declaration();
15253 ROSE_ASSERT(prev_decl);
15254 if (initName != prev_decl) {
15255 initName->set_prev_decl_item(prev_decl);
15256 }
15257 ROSE_ASSERT(initName->get_prev_decl_item() != initName);
15258 }
15259#if DEBUG__SageInterface__fixVariableDeclaration
15260 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15261#endif
15262 } //end for
15263
15264 // Liao 12/8/2010
15265 // For Fortran, a common statement may refer to a variable which is declared later.
15266 // In this case, a fake symbol is used for that variable reference.
15267 // But we have to replace the fake one with the real one once the variable declaration is inserted into AST
15269 {
15270 fixVariableReferences(scope);
15271 }
15272 }
15273
15274int SageInterface::fixVariableReferences(SgNode* root, bool cleanUnusedSymbols/*=true*/)
15275{
15276 ROSE_ASSERT(root);
15277 int counter=0;
15278 Rose_STL_Container<SgNode*> varList;
15279
15280 SgVarRefExp* varRef=NULL;
15281 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(root, V_SgVarRefExp);
15282 for (Rose_STL_Container<SgNode*>::iterator i=reflist.begin();i!=reflist.end();i++)
15283 {
15284 varRef= isSgVarRefExp(*i);
15285 ROSE_ASSERT(varRef->get_symbol());
15286 SgInitializedName* initname= varRef->get_symbol()->get_declaration();
15287
15288 ROSE_ASSERT (initname != NULL);
15289 if (initname->get_type()==SgTypeUnknown::createType())
15290 {
15291 SgName varName=initname->get_name();
15292 SgSymbol* realSymbol = NULL;
15293
15294#if 1
15295 // CH (5/7/2010): Before searching SgVarRefExp objects, we should first deal with class/structure
15296 // members. Or else, it is possible that we assign the wrong symbol to those members if there is another
15297 // variable with the same name in parent scopes. Those members include normal member referenced using . or ->
15298 // operators, and static members using :: operators.
15299 //
15300 if (SgArrowExp* arrowExp = isSgArrowExp(varRef->get_parent()))
15301 {
15302 if (varRef == arrowExp->get_rhs_operand_i())
15303 {
15304 // make sure the lhs operand has been fixed
15305 counter += fixVariableReferences(arrowExp->get_lhs_operand_i());
15306 SgType* lhs_type = arrowExp->get_lhs_operand_i()->get_type() ;
15307 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15308 SgPointerType* ptrType = isSgPointerType(lhs_type);
15309 ROSE_ASSERT(ptrType);
15310 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));
15311 ROSE_ASSERT(clsType);
15312 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15313 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15314 ROSE_ASSERT(decl);
15315
15316 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15317 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15318 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15319 }
15320 else
15321 {
15322 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15323 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15324 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15325 }
15326 }
15327 else if (SgDotExp* dotExp = isSgDotExp(varRef->get_parent()))
15328 {
15329 if (varRef == dotExp->get_rhs_operand_i())
15330 {
15331 // make sure the lhs operand has been fixed
15332 counter += fixVariableReferences(dotExp->get_lhs_operand_i());
15333
15334 SgType* lhs_type = dotExp->get_lhs_operand_i()->get_type() ;
15335 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15336 SgClassType* clsType = isSgClassType(lhs_type);
15337 ROSE_ASSERT(clsType);
15338 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15339 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15340 ROSE_ASSERT(decl);
15341
15342 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15343 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15344 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15345 }
15346 else
15347 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15348 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15349 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15350 }
15351 else
15352#endif
15353 {
15354 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15355 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15356 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15357 }
15358
15359 // should find a real symbol at this final fixing stage!
15360 // This function can be called any time, not just final fixing stage
15361 if (realSymbol==NULL)
15362 {
15363 //cerr<<"Error: cannot find a symbol for "<<varName.getString()<<endl;
15364 //ROSE_ASSERT(realSymbol);
15365 }
15366 else {
15367 // release placeholder initname and symbol
15368 ROSE_ASSERT(realSymbol!=(varRef->get_symbol()));
15369#if 0
15370 // CH (5/12/2010):
15371 // To delete a symbol node, first check if there is any node in memory
15372 // pool which points to this symbol node. Only if no such node exists,
15373 // this symbol together with its initialized name can be deleted.
15374 //
15375 bool toDelete = true;
15376
15377 SgSymbol* symbolToDelete = varRef->get_symbol();
15378 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15379 counter ++;
15380
15381 if (varList.empty())
15382 {
15383 VariantVector vv(V_SgVarRefExp);
15384 varList = NodeQuery::queryMemoryPool(vv);
15385 }
15386
15387 for (Rose_STL_Container<SgNode*>::iterator i = varList.begin();
15388 i != varList.end(); ++i)
15389 {
15390 if (SgVarRefExp* var = isSgVarRefExp(*i))
15391 {
15392 if (var->get_symbol() == symbolToDelete)
15393 {
15394 toDelete = false;
15395 break;
15396 }
15397 }
15398 }
15399 if (toDelete)
15400 {
15401 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15402 delete symbolToDelete;
15403 }
15404
15405#else
15406
15407 // CH (2010/7/26): We cannot delete those initname and symbol here, since there may be other variable references
15408 // which point to them. We will delay this clear just before AstTests.
15409#if 0
15410 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15411 delete (varRef->get_symbol());
15412#endif
15413
15414 //std::cout << "Fixed variable reference: " << realSymbol->get_name().str() << std::endl;
15415 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15416 counter ++;
15417#endif
15418 }
15419 }
15420 } // end for
15421 // Liao 2/1/2013: delete unused initname and symbol, considering possible use by the current subtree from root node
15422 if (cleanUnusedSymbols)
15424 return counter;
15425}
15426
15428{
15429 Rose_STL_Container<SgNode*> symbolList;
15430 VariantVector sym_vv(V_SgVariableSymbol);
15431 symbolList = NodeQuery::queryMemoryPool(sym_vv);
15432
15433 Rose_STL_Container<SgNode*> varList;
15434 VariantVector var_vv(V_SgVarRefExp);
15435 //varList = NodeQuery::queryMemoryPool(var_vv);
15436 if (root != NULL)
15437 {
15438 varList = NodeQuery::querySubTree(root, V_SgVarRefExp);
15439 }
15440
15441 for (Rose_STL_Container<SgNode*>::iterator i = symbolList.begin();
15442 i != symbolList.end(); ++i)
15443 {
15444 SgVariableSymbol* symbolToDelete = isSgVariableSymbol(*i);
15445 ROSE_ASSERT(symbolToDelete);
15446 if (symbolToDelete->get_declaration()->get_type() != SgTypeUnknown::createType())
15447 continue;
15448 // symbol with a declaration of SgTypeUnknown will be deleted
15449 bool toDelete = true;
15450
15451 if (root != NULL) // if root is specified. We further check if the symbol is referenced by any nodes of the tree rooted at "root"
15452 {
15453 for (Rose_STL_Container<SgNode*>::iterator j = varList.begin();
15454 j != varList.end(); ++j)
15455 {
15456 SgVarRefExp* var = isSgVarRefExp(*j);
15457 ROSE_ASSERT(var);
15458
15459 if (var->get_symbol() == symbolToDelete)
15460 {
15461 toDelete = false;
15462 break;
15463 }
15464 }
15465 }
15466
15467 if (toDelete)
15468 {
15469#if 0
15470 std::cout << "Symbol " << symbolToDelete->get_name().str() << ' ' << symbolToDelete <<
15471 ' ' << symbolToDelete->get_declaration() << " is deleted." << std::endl;
15472#endif
15473 delete symbolToDelete->get_declaration();
15474 delete symbolToDelete;
15475 }
15476 }
15477}
15478
15479
15481/*
15482 * label statement has special scope: the closest function definition , not SgBasicBlock or others!
15483 */
15485 {
15486 SgLabelStatement* label_stmt = isSgLabelStatement(stmt);
15487 ROSE_ASSERT(label_stmt);
15488 SgName name = label_stmt->get_label();
15489
15490 // PP (07/18/23): In Ada, label symbols should be inserted in the current scope's symbol table
15491 const bool symbolAtFunctionLevel = !is_Ada_language();
15492 SgScopeStatement* label_scope = symbolAtFunctionLevel ? getEnclosingFunctionDefinition(scope,true)
15493 : scope;
15494
15495 // DQ (11/16/2014): Added error checking for when the input scope is the SgFunctionDefinition instead of a nested scope.
15496 if (isSgFunctionDefinition(scope) != nullptr)
15497 {
15498 ASSERT_not_null(label_scope);
15499 }
15500
15501 if (label_scope) //Should we assert this instead? No for bottom up AST building
15502 {
15503 label_stmt->set_scope(label_scope);
15504 SgLabelSymbol* lsymbol = label_scope->lookup_label_symbol(name);
15505
15506 if (lsymbol == nullptr)
15507 {
15508 // SgLabelStatement should always be in the function scope
15509 // PP (07/18/23): in Ada symbols should be at the innermost scope
15510 lsymbol= new SgLabelSymbol(label_stmt);
15511 ASSERT_not_null(lsymbol);
15512 label_scope->insert_symbol(lsymbol->get_name(), lsymbol);
15513 }
15514 }
15515 }
15516
15517
15519//efExp are created transparently as needed.
15521 SgLabelSymbol::label_type_enum label_type, SgScopeStatement* label_scope)
15522 {
15523 ROSE_ASSERT (stmt != NULL);
15524 ROSE_ASSERT (label_value >0 && label_value <=99999); //five digits for Fortran label
15525
15526 // Added optional label_type and label_scope [Rasmussen 2019.01.20]
15527 if (label_scope == NULL)
15528 {
15529 label_scope = getEnclosingFunctionDefinition(stmt);
15530 }
15531 ROSE_ASSERT (label_scope != NULL);
15532 SgName label_name(StringUtility::numberToString(label_value));
15533 SgLabelSymbol * symbol = label_scope->lookup_label_symbol (label_name);
15534 if (symbol == NULL)
15535 {
15536 // DQ (12/4/2011): This is the correct handling for SgLabelStatement (always in the function scope, same as C and C++).
15537 // DQ (2/2/2011): We want to call the old constructor (we now have another constructor that takes a SgInitializedName pointer).
15538 // symbol = new SgLabelSymbol(NULL);
15539 symbol = new SgLabelSymbol((SgLabelStatement*) NULL);
15540 ROSE_ASSERT(symbol != NULL);
15541 symbol->set_fortran_statement(stmt);
15542 symbol->set_numeric_label_value(label_value);
15543 label_scope->insert_symbol(label_name,symbol);
15544 }
15545 else
15546 {
15547 cerr<<"Error. SageInterface::setFortranNumericLabel() tries to set a duplicated label value!"<<endl;
15548 ROSE_ASSERT (false);
15549 }
15550
15551 // SgLabelRefExp
15552 SgLabelRefExp* ref_exp = buildLabelRefExp(symbol);
15553 ref_exp->set_parent(stmt);
15554
15555 switch(label_type)
15556 {
15557 case SgLabelSymbol::e_start_label_type:
15558 {
15559 stmt->set_numeric_label(ref_exp);
15560 break;
15561 }
15562 case SgLabelSymbol::e_end_label_type:
15563 {
15564 stmt->set_end_numeric_label(ref_exp);
15565 break;
15566 }
15567 default:
15568 {
15569 std::cerr << "SageInterface::setFortranNumericLabel: unimplemented for label_type " << label_type << "\n";
15570 ROSE_ABORT(); // NOT IMPLEMENTED
15571 }
15572 }
15573
15574 }
15575
15576
15579{
15580 int result =10;
15581 ROSE_ASSERT (func_def != NULL);
15582 ROSE_ASSERT (SageInterface::is_Fortran_language()== true);
15583 std::set<SgNode*> symbols = func_def->get_symbol_table()->get_symbols();
15584
15585 // find the max label value, +10 to be the suggested next label value
15586 std::set<SgNode*>::iterator iter ;
15587 for (iter=symbols.begin(); iter !=symbols.end(); iter++)
15588 {
15589 SgLabelSymbol * l_symbol = isSgLabelSymbol(*iter);
15590 if (l_symbol)
15591 {
15592 int cur_val = l_symbol->get_numeric_label_value();
15593 if (result <=cur_val)
15594 result = cur_val +10;
15595 }
15596 }
15597
15598 ROSE_ASSERT (result <= 99999); // max 5 digits for F77 label
15599 return result;
15600}
15601
15603/*
15604 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15605 */
15607 {
15608 // DQ (3/5/2012): Added test.
15609 ROSE_ASSERT(scope != NULL);
15610
15611 // fix function type table's parent edge
15612 // Liao 5/4/2010
15614 ROSE_ASSERT(fTable != NULL);
15615
15616 if (fTable->get_parent() == NULL)
15617 {
15618 // DQ (3/5/2012): This is a problem for test2012_13.C (test code taken from test2004_42.C).
15619 // fTable->set_parent(getGlobalScope(scope));
15620#if 0
15621 printf ("WARNING: Skip setting the scope of the SgFunctionTypeTable scope = %p = %s \n",scope,scope->class_name().c_str());
15622#endif
15623 fTable->set_parent(getGlobalScope(scope));
15624 }
15625
15626#if 0
15627 printf ("In SageInterface::fixStatement(): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15628#endif
15629
15630 // Liao 4/23/2010, Fix function symbol
15631 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15632 // Added SgProgramHeaderStatement [Rasmussen, 2020.01.19]
15633 SgFunctionDeclaration * func = isSgFunctionDeclaration(stmt);
15634 SgMemberFunctionDeclaration * mfunc = isSgMemberFunctionDeclaration(stmt);
15635 SgTemplateFunctionDeclaration * tfunc = isSgTemplateFunctionDeclaration(stmt);
15636 SgTemplateMemberFunctionDeclaration * tmfunc = isSgTemplateMemberFunctionDeclaration(stmt);
15637 SgProcedureHeaderStatement * procfunc = isSgProcedureHeaderStatement(stmt);
15638 SgProgramHeaderStatement * progfunc = isSgProgramHeaderStatement(stmt);
15639
15640 if (tmfunc != NULL)
15641 assert(tmfunc->variantT() == V_SgTemplateMemberFunctionDeclaration);
15642 else if (mfunc != NULL)
15643 assert(mfunc->variantT() == V_SgMemberFunctionDeclaration || mfunc->variantT() == V_SgTemplateInstantiationMemberFunctionDecl);
15644 else if (tfunc != NULL)
15645 assert(tfunc->variantT() == V_SgTemplateFunctionDeclaration);
15646 else if (procfunc != NULL)
15647 assert(procfunc->variantT() == V_SgProcedureHeaderStatement);
15648 else if (progfunc != NULL)
15649 assert(progfunc->variantT() == V_SgProgramHeaderStatement);
15650 else if (func != NULL)
15651 assert(func->variantT() == V_SgFunctionDeclaration || func->variantT() == V_SgTemplateInstantiationFunctionDecl);
15652 else ROSE_ABORT();
15653
15654#if 0
15655 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15656 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15657#endif
15658
15659 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15660 // It is an error to put the symbol for a function into the current scope if the function's scope
15661 // is explicitly set to be different. So this should be allowed only if the function's scope is
15662 // not explicitly set, or if the scopes match. This is an example of something different for C++
15663 // than for C or other simpler languages.
15664 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15665 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15666 {
15667#if 0
15668 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());
15669#endif
15670 SgFunctionSymbol* func_symbol = NULL;
15671
15672 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
15673 // In this case these are unavailable from this point.
15674 if (tmfunc != NULL)
15675 {
15676 SgTemplateParameterPtrList & templateParameterList = tmfunc->get_templateParameters();
15677 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type());
15678 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),NULL);
15679 func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15680 }
15681 else if (mfunc != NULL)
15682 {
15683 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(mfunc);
15684 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationMemberFunctionDecl != NULL) ? &(templateInstantiationMemberFunctionDecl->get_templateArguments()) : NULL;
15685 // func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),NULL);
15686 func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15687 }
15688 else if (tfunc != NULL)
15689 {
15690 SgTemplateParameterPtrList & templateParameterList = tfunc->get_templateParameters();
15691#if 0
15692 printf ("In SageInterface::fixStatement(): templateParameterList.size() = %" PRIuPTR " \n",templateParameterList.size());
15693#endif
15694 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type());
15695 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),NULL);
15696 func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15697 }
15698 else if (procfunc != NULL)
15699 {
15700#if 0
15701 printf ("In SageInterface::fixStatement(): procfunc->get_name() = %s calling lookup_function_symbol() \n",procfunc->get_name().str());
15702#endif
15703 func_symbol = scope->lookup_function_symbol (procfunc->get_name(), procfunc->get_type());
15704 assert(func_symbol != NULL);
15705 }
15706 else if (progfunc != NULL)
15707 {
15708 func_symbol = scope->lookup_function_symbol (progfunc->get_name(), progfunc->get_type());
15709 assert(func_symbol != NULL);
15710 }
15711 else if (func != NULL)
15712 {
15713#if 0
15714 printf ("In SageInterface::fixStatement(): func->get_name() = %s calling lookup_function_symbol() \n",func->get_name().str());
15715#endif
15716 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(func);
15717 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationFunctionDecl != NULL) ? &(templateInstantiationFunctionDecl->get_templateArguments()) : NULL;
15718 // func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),NULL);
15719 func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15720
15721 // 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
15722 // 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
15723 // opportunity to fixup the function to have a symbol in the scope's symbol table.
15724 if (func_symbol == NULL)
15725 {
15726 // scope->print_symboltable("In SageInterface::fixStatement()");
15727 func_symbol = new SgFunctionSymbol(func);
15728 scope->insert_symbol(func->get_name(), func_symbol);
15729 }
15730 }
15731 else
15732 {
15733 ROSE_ABORT();
15734 }
15735#if 0
15736 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15737#endif
15738 assert(func_symbol != NULL);
15739 }
15740 }
15741
15743/*
15744 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15745 */
15747 {
15748 // DQ (12/4/2011): This function has not been implemented yet. It will assert fail if it is required.
15749 printf ("Need to handle SgTemplateDeclaration IR nodes as well...(implement later) \n");
15750 }
15751
15752
15755 {
15756 // fix symbol table
15757 if (isSgVariableDeclaration(stmt))
15758 {
15759 fixVariableDeclaration(isSgVariableDeclaration(stmt), scope);
15760 }
15761 else if (isStructDeclaration(stmt))
15762 {
15763 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
15764 ROSE_ASSERT(classDeclaration != nullptr);
15765 fixStructDeclaration(classDeclaration,scope);
15766 }
15767 else if (isSgClassDeclaration(stmt))
15768 {
15769 fixClassDeclaration(isSgClassDeclaration(stmt),scope);
15770 }
15771 else if (isSgLabelStatement(stmt))
15772 {
15773 fixLabelStatement(isSgLabelStatement(stmt),scope);
15774 }
15775 else if (isSgFunctionDeclaration(stmt))
15776 {
15777#if 1
15778 fixFunctionDeclaration(isSgFunctionDeclaration(stmt),scope);
15779#else
15780 // fix function type table's parent edge
15781 // Liao 5/4/2010
15783 ROSE_ASSERT(fTable);
15784 if (fTable->get_parent() == NULL)
15785 fTable->set_parent(getGlobalScope(scope));
15786
15787 // Liao 4/23/2010, Fix function symbol
15788 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15789 SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt);
15790 SgMemberFunctionDeclaration* mfunc = isSgMemberFunctionDeclaration(stmt);
15791
15792 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15793 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15794
15795 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15796 // It is an error to put the symbol for a function into the current scope if the function's scope
15797 // is explicitly set to be different. So this should be allowed only if the function's scope is
15798 // not explicitly set, or if the scopes match. This is an example of something different for C++
15799 // than for C or other simpler languages.
15800 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15801 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15802 {
15803#if 0
15804 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());
15805#endif
15806 SgFunctionSymbol* func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type());
15807
15808 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15809 if (func_symbol == NULL)
15810 {
15811 // DQ (12/3/2011): Added support for C++ member functions.
15812 // func_symbol = new SgFunctionSymbol (func);
15813 if (mfunc != NULL)
15814 {
15815 func_symbol = new SgMemberFunctionSymbol (func);
15816 }
15817 else
15818 {
15819 func_symbol = new SgFunctionSymbol (func);
15820 }
15821 ROSE_ASSERT (func_symbol != NULL);
15822
15823 scope->insert_symbol(func->get_name(), func_symbol);
15824 }
15825 else
15826 {
15827 printf ("In SageInterface::fixStatement(): found a valid function so no need to insert new symbol \n");
15828 }
15829 }
15830#if 0
15831 // Fix local symbol, a symbol directly refer to this function declaration
15832 // This could happen when a non-defining func decl is copied, the corresonding symbol will point to the original source func
15833 // symbolTable->find(this) used inside get_symbol_from_symbol_table() won't find the copied decl
15834 SgSymbol* local_symbol = func ->get_symbol_from_symbol_table();
15835 if (local_symbol == NULL) //
15836 {
15837 if (func->get_definingDeclaration() == NULL) // prototype function
15838 {
15839 SgFunctionDeclaration * src_func = func_symbol->get_declaration();
15840 if (func != src_func )
15841 {
15842 ROSE_ASSERT (src_func->get_firstNondefiningDeclaration () == src_func);
15843 func->set_firstNondefiningDeclaration (func_symbol->get_declaration());
15844 }
15845 }
15846 }
15847#endif
15848#endif
15849 }
15850 else if (isSgTemplateDeclaration(stmt) != NULL)
15851 {
15852 // DQ (12/3/2011): Added new case for SgTemplateDeclaration (adding template declarations to the AST).
15853 fixTemplateDeclaration(isSgTemplateDeclaration(stmt),scope);
15854 }
15855
15856#if 0
15857 // DQ (12/4/2011): This WAS not the correct behavior for C++ since declarations can appear structureally in different
15858 // scopes than where the are positioned (e.g. member functions defined outside of there associated class).
15859 // This this code is very dangerous.
15860
15861 // fix scope pointer for statements explicitly storing scope pointer
15862 switch (stmt->variantT())
15863 {
15864 // The case of SgLabelStatement should maybe be included.
15865 case V_SgEnumDeclaration:
15866 case V_SgTemplateDeclaration:
15867 case V_SgTypedefDeclaration:
15868 case V_SgFunctionDeclaration:
15869 case V_SgMemberFunctionDeclaration:
15870 case V_SgTemplateInstantiationFunctionDecl:
15871 {
15872 // DQ (12/4/2011): We can't just set the scope this simily (except in C). In C++ the scope should have
15873 // already been set or we can let it default to the current scope where it si located structurally.
15874 // stmt->set_scope(scope);
15875 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
15876 {
15877 stmt->set_scope(scope);
15878 }
15879 break;
15880 }
15881
15882 default:
15883 {
15884 // debugging support...
15885 printf ("In SageInterface::fixStatement(): switch default case used (likely OK): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15886 ROSE_ASSERT(stmt->hasExplicitScope() == false);
15887#if 0
15888 printf ("switch case not handled properly: stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15889 ROSE_ABORT();
15890#endif
15891 break;
15892 }
15893 }
15894#else
15895 // If the scoep has to be set and it has not yet been set, then set it directly.
15896 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
15897 {
15898 stmt->set_scope(scope);
15899 }
15900#endif
15901 }
15902
15903
15916 {
15917 // DQ (11/19/2012): Note that this appears to be an expensive function presently taking 22.5% of the total time
15918 // to process the tests/CompilerTests/Cxx_tests/rosePerformance.C file. So this is a performance problem.
15919
15920 ROSE_ASSERT(func != NULL && scope != NULL);
15921
15922 ROSE_ASSERT(func != NULL);
15923 ROSE_ASSERT(scope != NULL);
15924
15925 SgStatementPtrList stmtList, sameFuncList;
15926
15927 // SgFunctionDeclaration* first_nondef = NULL;
15928 // Some annoying part of scope
15929 if (scope->containsOnlyDeclarations())
15930 {
15931 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
15932 SgDeclarationStatementPtrList::iterator i;
15933 for (i=declList.begin();i!=declList.end();i++)
15934 stmtList.push_back(*i);
15935 }
15936 else
15937 {
15938 stmtList = scope->getStatementList();
15939 }
15940
15941 SgFunctionDeclaration* firstNondefiningFunctionDeclaration = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
15942 if (firstNondefiningFunctionDeclaration != NULL)
15943 {
15944 // If there exists a non-NULL reference to a firstNondefiningFunctionDeclaration
15945 // then use it (unless we want to handle where it might be set wrong).
15946#if 0
15947 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid pointer to a firstNondefiningFunctionDeclaration = %p \n",func,firstNondefiningFunctionDeclaration);
15948#endif
15949 }
15950
15951 // DQ (3/12/2012): Added assertion
15952 // ROSE_ASSERT(scope == func->get_firstNondefiningDeclaration()->get_scope());
15953 ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope() != NULL);
15954
15955 // 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.
15956 if (func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) == NULL)
15957 {
15958 printf ("WARNING: symbol for func->get_firstNondefiningDeclaration() = %p = %s = %s is not present in the scope = %p = %s associated with the firstNondefiningDeclaration \n",
15959 func->get_firstNondefiningDeclaration(),func->get_firstNondefiningDeclaration()->class_name().c_str(),func->get_name().str(),
15961 }
15962 // ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) != NULL);
15963
15964#if 0
15965 // It would be better to find the first non-defining declaration via the symbol.
15966 SgSymbol* functionSymbol = scope->lookup_function_symbol(func->get_name(),func->get_type());
15967 if (functionSymbol != NULL)
15968 {
15969 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid symbol = %p \n",func,functionSymbol);
15970 }
15971 else
15972 {
15973 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p functionSymbol == NULL \n",func);
15974 }
15975#endif
15976
15977 // Find the same function declaration list, including func itself
15978 SgStatementPtrList::iterator j;
15979 for (j = stmtList.begin(); j != stmtList.end(); j++)
15980 {
15981 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
15982 if (func_decl != NULL)
15983 {
15984 // DQ (11/19/2012): This call to the isSameFunction() function is taking a total of 22.1%
15985 // of the total execution time of the tests/CompilerTests/Cxx_tests/rosePerformance.C file.
15986 if (isSameFunction(func_decl, func))
15987 {
15988 // Assume all defining functions have definingdeclaration links set properly already!!
15989 sameFuncList.push_back(func_decl);
15990 }
15991 }
15992 }
15993
15994#if 0
15995 printf ("func = %p \n",func);
15996 printf ("func->get_definingDeclaration() = %p \n",func->get_definingDeclaration());
15997#endif
15998
15999 ROSE_ASSERT(func != NULL);
16000
16001 if (func->get_definingDeclaration() == func)
16002 {
16003 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16004 isSgFunctionDeclaration(*j)->set_definingDeclaration(func);
16005 }
16006 else
16007 {
16008 ROSE_ASSERT(func != NULL);
16009
16010 // DQ (3/9/2012): Added assertion to avoid empty list that would be an error in both cases below.
16011 ROSE_ASSERT(sameFuncList.empty() == false);
16012
16013 if (func == isSgFunctionDeclaration(*(sameFuncList.begin()))) // is first_nondefining declaration
16014 {
16015 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16016 {
16017 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16018#if 0
16019 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Testing j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16020#endif
16021 // DQ (3/9/2012): Avoid setting the function to be it's own firstNondefiningDeclaration.
16022 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16023 if (func_decl != func)
16024 {
16025 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16026 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16027 if (func_decl->get_firstNondefiningDeclaration() == NULL)
16028 {
16029#if 0
16030 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Calling j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16031#endif
16032 func_decl->set_firstNondefiningDeclaration(func);
16033 }
16034 }
16035 }
16036 }
16037 else // is a following nondefining declaration, grab any other's first nondefining link then
16038 {
16039#if 0
16040 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Testing func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16041#endif
16042 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16043 // func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16044 if (func->get_firstNondefiningDeclaration() == NULL)
16045 {
16046#if 0
16047 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Calling func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16048#endif
16049 func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16050 }
16051 }
16052 }
16053 }
16054
16055PreprocessingInfo* SageInterface::attachComment(SgSourceFile * source_file, const std::string & content, PreprocessingInfo::DirectiveType directive_type, PreprocessingInfo::RelativePositionType position) {
16056 assert(source_file != NULL);
16057 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16058
16059 SgGlobal * global_scope = source_file->get_globalScope();
16060
16061 PreprocessingInfo* result = new PreprocessingInfo(directive_type, content, "Transformation generated",0, 0, 0, position);
16062 ROSE_ASSERT(result);
16063
16064 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16065 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16066 // when multiple files are used on the command line.
16067 result->get_file_info()->setTransformation();
16068
16069 global_scope->addToAttachedPreprocessingInfo(result, position);
16070
16071 return result;
16072}
16073
16074//---------------------------------------------------------------
16076 SgLocatedNode* target, const string& content,
16077 PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/,
16078 PreprocessingInfo::DirectiveType dtype /* PreprocessingInfo::CpreprocessorUnknownDeclaration */)
16079 {
16080 ASSERT_not_null(target); //dangling comment is not allowed
16081
16082 PreprocessingInfo* result = NULL;
16083 PreprocessingInfo::DirectiveType mytype=dtype;
16084 string comment;
16085
16086 // Rasmussen (11/3/2020): Added Ada and Jovial style comments
16087 // DQ (5/5/2010): infer comment type from target's language
16088 if (mytype == PreprocessingInfo::CpreprocessorUnknownDeclaration)
16089 {
16090 // This is a rather expensive way to detect the language type (chases pointers back to the SgFile object).
16091 if (is_C_language() || is_C99_language())
16092 {
16093 // Comment = "/* "+ content + " */";
16094 mytype = PreprocessingInfo::C_StyleComment;
16095 }
16096 else if (is_Cxx_language() || is_Java_language())
16097 {
16098 // Comment = "// "+ content;
16099 mytype = PreprocessingInfo::CplusplusStyleComment;
16100 }
16101 else if (is_Fortran_language() || is_CAF_language()) //FMZ:3/23/2009
16102 {
16103 // Comment = "! "+ content;
16104 mytype = PreprocessingInfo::F90StyleComment;
16105 }
16106 else if (is_Ada_language())
16107 {
16108 // Comment = "-- " + content;
16109 mytype = PreprocessingInfo::AdaStyleComment;
16110 }
16111 else if (is_Jovial_language())
16112 {
16113 // Comment = "% " + content + " %";
16114 mytype = PreprocessingInfo::JovialStyleComment;
16115 }
16116 else
16117 {
16118 cout << "WARNING: SageInterface::attachComment(): Unknown programming language \n";
16119 ROSE_ABORT();
16120 }
16121 }
16122
16123 // Once the langauge type is set (discovered automatically or more directly specified by the user).
16124 bool resetPositionInfo = false;
16125 switch (mytype)
16126 {
16127 case PreprocessingInfo::C_StyleComment: comment = "/* " + content + " */"; break;
16128 case PreprocessingInfo::CplusplusStyleComment: comment = "// " + content; break;
16129 case PreprocessingInfo::FortranStyleComment: comment = " C " + content; break;
16130 case PreprocessingInfo::F90StyleComment: comment = "!" + content; break;
16131 case PreprocessingInfo::AdaStyleComment: comment = "-- " + content; break;
16132 case PreprocessingInfo::JovialStyleComment:
16133 // The Jovial comment content will already have the comment delimiters, '%' or '"'
16134 comment = content;
16135 break;
16136 case PreprocessingInfo::CpreprocessorLineDeclaration:
16137 comment = "#myline " + content;
16138 mytype = PreprocessingInfo::CplusplusStyleComment;
16139 resetPositionInfo = true;
16140 break;
16141 case PreprocessingInfo::CpreprocessorIfndefDeclaration: comment = "#ifndef " + content + "\n"; break;
16142 case PreprocessingInfo::CpreprocessorDefineDeclaration: comment = "#define " + content + "\n"; break;
16143 case PreprocessingInfo::CpreprocessorEndifDeclaration: comment = "#endif" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16144 case PreprocessingInfo::CpreprocessorEnd_ifDeclaration: comment = "#end if" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16145
16146 default:
16147 {
16148 printf ("Error: default in switch reached in SageInterface::attachComment() PreprocessingInfo::DirectiveType == %d \n",mytype);
16149 ROSE_ABORT();
16150 }
16151 }
16152
16153 result = new PreprocessingInfo (mytype,comment, "transformation-generated", 0, 0, 0, position);
16154
16155 // If this is a Cpp Line declaration then we have to set the position to match the statement.
16156 if (resetPositionInfo == true)
16157 {
16158 // Call the Sg_File_Info::operator=() member function.
16159 *(result->get_file_info()) = *(target->get_file_info());
16160 }
16161 else
16162 {
16163 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16164 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16165 // when multiple files are used on the command line.
16166 result->get_file_info()->setTransformation();
16167 }
16168
16169 ASSERT_not_null(result);
16170 target->addToAttachedPreprocessingInfo(result);
16171 return result;
16172 }
16173
16174void SageInterface::guardNode(SgLocatedNode * target, std::string guard) {
16175 PreprocessingInfo * if_macro = new PreprocessingInfo(
16176 PreprocessingInfo::CpreprocessorIfDeclaration,
16177 "#if " + guard,
16178 "transformation-generated", 0, 0, 0,
16179 PreprocessingInfo::before
16180 );
16181 target->addToAttachedPreprocessingInfo(if_macro);
16182
16183 PreprocessingInfo * endif_macro = new PreprocessingInfo(
16184 PreprocessingInfo::CpreprocessorEndifDeclaration,
16185 "#endif",
16186 "transformation-generated", 0, 0, 0,
16187 PreprocessingInfo::after
16188 );
16189 target->addToAttachedPreprocessingInfo(endif_macro);
16190
16191// DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16192// This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16193// when multiple files are used on the command line.
16194 if_macro->get_file_info()->setTransformation();
16195 endif_macro->get_file_info()->setTransformation();
16196}
16197
16198// internal hash table to cache the results: fileHeaderDict[file][header-key]
16199// header-key:
16200// system header : <header.h>
16201// non-system headers : "header.h"
16202static map<SgSourceFile*, map<string, PreprocessingInfo*> > fileHeaderDict;
16204PreprocessingInfo * SageInterface::findHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader)
16205{
16206 string header_key;
16207 if (isSystemHeader)
16208 header_key="<"+header_file_name+">";
16209 else
16210 header_key="\""+header_file_name+"\"";
16211
16212 if (fileHeaderDict.count(source_file) && fileHeaderDict[source_file].count(header_key))
16213 return fileHeaderDict[source_file][header_key];
16214
16215 vector<SgLocatedNode*> candidates;
16216 // do a fresh check. we only check global scope's declarations since we insert header into global scope
16217 // check SgGlobal
16218 SgGlobal* global= source_file -> get_globalScope();
16219
16220 candidates.push_back(global);
16221
16222 //check declarations within the global scope
16223 SgDeclarationStatementPtrList decl_stmt_list = global->get_declarations();
16224 for (SgDeclarationStatementPtrList::iterator iter= decl_stmt_list.begin(); iter!=decl_stmt_list.end(); iter++)
16225 candidates.push_back(*iter);
16226
16227 bool found = false;
16228 for (size_t ci=0; ci<candidates.size(); ci++)
16229 {
16230 SgLocatedNode* locatedNode= candidates[ci];
16231 AttachedPreprocessingInfoType *comments = locatedNode->getAttachedPreprocessingInfo ();
16232
16233 if (comments == NULL) continue;
16234 AttachedPreprocessingInfoType::iterator i;
16235 for (i = comments->begin (); i != comments->end (); i++)
16236 {
16237 if ((*i)->getTypeOfDirective () != PreprocessingInfo::CpreprocessorIncludeDeclaration) continue;
16238 string content = (*i)->getString ();
16239 if (content.find(header_key) != string::npos)
16240 {
16241 fileHeaderDict[source_file][header_key] = *i;
16242 found =true;
16243 break;
16244 }
16245
16246 } // each comment
16247
16248 if (found) break;
16249 } // each node
16250
16251 if (found)
16252 return fileHeaderDict[source_file][header_key];
16253 return NULL;
16254}
16255
16257SageInterface::insertHeader(SgSourceFile * source_file, const string & header_file_name, bool isSystemHeader, PreprocessingInfo::RelativePositionType position)
16258 {
16259 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16260 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16261 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16262 bool supportTokenUnparsing = false;
16263
16264 assert(source_file != NULL);
16265 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16266
16267 SgGlobal * global_scope = source_file->get_globalScope();
16268
16269 string content;
16270 if (isSystemHeader)
16271 content = "#include <" + header_file_name + "> \n";
16272 else
16273 content = "#include \"" + header_file_name + "\" \n";
16274
16275 PreprocessingInfo* result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, position);
16276 ROSE_ASSERT(result);
16277
16278 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16279 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16280 // when multiple files are used on the command line.
16281 result->get_file_info()->setTransformation();
16282
16283 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16284 supportTokenUnparsing = source_file->get_unparse_tokens();
16285 bool supportUnparseHeaders = source_file->get_unparseHeaderFiles();
16286
16287#if 0
16288 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16289 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16290 printf ("source_file = %p \n",source_file);
16291 printf ("global_scope = %p \n",global_scope);
16292#endif
16293#if 0
16294 printf ("Exiting as a test! \n");
16295 ROSE_ABORT();
16296#endif
16297
16298 // global_scope->addToAttachedPreprocessingInfo(result, position);
16299 if (supportTokenUnparsing == false)
16300 {
16301 global_scope->addToAttachedPreprocessingInfo(result, position);
16302 }
16303 else
16304 {
16305 // global_scope->prepend_statement(null_statement);
16306 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16307
16308 if (supportUnparseHeaders == true)
16309 {
16310 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16311 int physical_file_id = global_scope->get_startOfConstruct()->get_physical_file_id();
16312#if 0
16313 printf ("physical_file_id = %d \n",physical_file_id);
16314#endif
16315 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16316 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16317#if 0
16318 printf ("Exiting as a test! \n");
16319 ROSE_ABORT();
16320#endif
16321 }
16322
16323 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16324
16325 global_scope->prepend_statement(emptyDeclaration);
16326 }
16327
16328#if 0
16329 printf ("Exiting as a test! \n");
16330 ROSE_ASSERT(false);
16331#endif
16332
16333 return result;
16334 }
16335
16336PreprocessingInfo* SageInterface::insertHeader(const string& filename, PreprocessingInfo::RelativePositionType position /*=after*/, bool isSystemHeader /*=false*/, SgScopeStatement* scope /*=NULL*/)
16337 {
16338 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16339 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16340 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16341 bool supportTokenUnparsing = false;
16342
16343 // DQ (8/12/2020): This is a compiler warning.
16344 // bool successful = false;
16345
16346#if 0
16347 printf ("In SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16348 printf (" --- position = %s \n",PreprocessingInfo::relativePositionName(position).c_str());
16349#endif
16350
16351 if (scope == NULL)
16353
16354 ROSE_ASSERT(scope);
16355
16356 SgGlobal* globalScope = getGlobalScope(scope);
16357 ROSE_ASSERT(globalScope != NULL);
16358
16359 // 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
16360 // if the input scope is within a header file,
16361 // its global scope will jump to a .cpp file. Later looping will not find a match.
16362 SgScopeStatement* srcScope = globalScope;
16363 PreprocessingInfo* result=NULL;
16364 string content;
16365 if (isSystemHeader)
16366 content = "#include <" + filename + "> \n";
16367 else
16368 content = "#include \"" + filename + "\" \n";
16369
16370 // DQ (11/21/2019): Token based unparsing has an additional requirement, we need to mark that the
16371 // whitespace around the statement has been modified. This will trigger the unparser to output
16372 // the comments and CPP directives when using the token-based unparsing. The insertion of a header
16373 // file requires this support else the original token stream will not have the added header file.
16374
16375 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16376 SgSourceFile* sourceFile = getEnclosingSourceFile(scope);
16377 ROSE_ASSERT(sourceFile != NULL);
16378
16379 supportTokenUnparsing = sourceFile->get_unparse_tokens();
16380
16381 bool supportUnparseHeaders = sourceFile->get_unparseHeaderFiles();
16382 // if unparsing header and the scope is within a header file, we adjust srcScope to be scope, not its enclosing global scope
16383 if (supportUnparseHeaders)
16384 {
16385 string filename= scope->get_file_info()->get_filename();
16386 string suffix = Rose::StringUtility ::fileNameSuffix(filename);
16387
16388 // vector.tcc: This is an internal header file, included by other library headers
16389 if (suffix=="h" ||suffix=="hpp"|| suffix=="hh"||suffix=="H" ||suffix=="hxx"||suffix=="h++" ||suffix=="tcc")
16390 srcScope = scope;
16391 }
16392
16393#if 0
16394 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16395 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16396 printf ("sourceFile = %p \n",sourceFile);
16397 printf ("globalScope = %p \n",globalScope);
16398#endif
16399#if 0
16400 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16401#endif
16402#if 0
16403 printf ("Exiting as a test! \n");
16404 ROSE_ABORT();
16405#endif
16406
16407 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations();
16408
16409#if 0
16410 printf ("stmtList.size() = %zu \n",stmtList.size());
16411#endif
16412
16413 if (stmtList.size() > 0) // the source file is not empty
16414 {
16415 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16416 {
16417 // must have this judgement, otherwise wrong file will be modified!
16418 // It could also be the transformation generated statements with #include attached
16419 if ( ((*j)->get_file_info())->isSameFile(srcScope->get_file_info ()) || ((*j)->get_file_info ())->isTransformation() )
16420 {
16421 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16422 ROSE_ASSERT(result != NULL);
16423#if 0
16424 printf ("Building a PreprocessingInfo: result = %p \n",result);
16425#endif
16426 // DQ (3/22/2019): Fixing this to work with the token-based unparsing.
16427 // add to the last position
16428 // TODO: support to add to the first,
16429 // TODO: support fine positioning with #include directives
16430 // (*j)->addToAttachedPreprocessingInfo(result,position);
16431
16432 if (supportTokenUnparsing == false)
16433 {
16434 (*j)->addToAttachedPreprocessingInfo(result,position);
16435 }
16436 else
16437 {
16438 (*j)->addToAttachedPreprocessingInfo(result,position);
16439#if 0
16440 printf ("In SageInterface::insertHeader(): Calling set_containsTransformationToSurroundingWhitespace(true) \n");
16441#endif
16442#if 1
16443 // DQ (12/31/2020): Set the whitespace around the statement as being modified.
16444 (*j)->set_containsTransformationToSurroundingWhitespace(true);
16445#endif
16446#if 0
16447 SgDeclarationStatement* declarationStatement = *j;
16448
16449 // DQ (1/5/2021): Don't call unparseToString, since this triggers the unparer which then unparses
16450 // from the token stream and makrs some token stream elements as already unparsed.
16451 // printf ("declarationStatement = %p = %s unparseToString() = %s \n",declarationStatement,
16452 // declarationStatement->class_name().c_str(),declarationStatement->unparseToString().c_str());
16453 printf ("In SageInterface::insertHeader(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
16454 printf ("In SageInterface::insertHeader(): declarationStatement->get_containsTransformationToSurroundingWhitespace() = %s \n",
16455 declarationStatement->get_containsTransformationToSurroundingWhitespace() ? "true" : "false");
16456#endif
16457#if 0
16458 // Liao, let's try the new way.
16459 // global_scope->prepend_statement(null_statement);
16460 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16461
16462 if (supportUnparseHeaders == true)
16463 {
16464 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16465 int physical_file_id = globalScope->get_startOfConstruct()->get_physical_file_id();
16466#if 0
16467 printf ("physical_file_id = %d \n",physical_file_id);
16468#endif
16469 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16470 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16471#if 0
16472 printf ("Exiting as a test! \n");
16473 ROSE_ASSERT(false);
16474#endif
16475 }
16476
16477 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16478
16479 globalScope->insert_statement(*j,emptyDeclaration);
16480#endif
16481 }
16482#if 0
16483 printf ("break out of for loop: result = %p \n",result);
16484#endif
16485 // DQ (8/12/2020): This is a compiler warning.
16486 // successful = true;
16487 break;
16488 }
16489 }
16490 }
16491 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16492 {
16493 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16494 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16495 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16496 ROSE_ASSERT(false);
16497 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16498 ROSE_ASSERT(result);
16499 globalScope->addToAttachedPreprocessingInfo(result,position);
16500
16501 // DQ (8/12/2020): This is a compiler warning.
16502 // successful = true;
16503 }
16504
16505 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16506 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16507 // when multiple files are used on the command line.
16508 // DQ (3/12/2019): This can be NULL for the omp tests.
16509 if (result != NULL)
16510 {
16511 result->get_file_info()->setTransformation();
16512 }
16513
16514 // must be inserted once somehow
16515 // 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
16516 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16517 // ROSE_ASSERT(successful==true);
16518
16519#if 0
16520 printf ("Exiting as a test! \n");
16521 ROSE_ASSERT(false);
16522#endif
16523
16524#if 0
16525 printf ("Leaving SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16526#endif
16527
16528#if 0
16529 printf ("Exiting as a test! \n");
16530 ROSE_ASSERT(false);
16531#endif
16532
16533 return result;
16534 }
16535
16536
16537// 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
16538void SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader)
16539{
16540 ROSE_ASSERT (stmt != NULL);
16541 ROSE_ASSERT (newheader != NULL);
16542
16543#if 0
16544 printf ("In SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader) \n");
16545#endif
16546
16548
16549 if (asLastHeader )
16550 position = PreprocessingInfo::after;
16551 else
16552 position = PreprocessingInfo::before;
16553
16554
16555 // Find existing first and last header.
16556 AttachedPreprocessingInfoType *comments = stmt->getAttachedPreprocessingInfo ();
16557
16558 if (comments != NULL)
16559 {
16560 PreprocessingInfo * firstExistingHeader = NULL;
16561 PreprocessingInfo * lastExistingHeader = NULL;
16562 PreprocessingInfo * firstExistingEndif = NULL;
16563
16564 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16565 // PreprocessingInfo * lastExistingEndif = NULL;
16566
16567 AttachedPreprocessingInfoType::iterator i, firsti, lasti;
16568 for (i = comments->begin (); i != comments->end (); i++)
16569 {
16570 // DQ (9/12/2020): this original code is not sufficent since when the final #include is enclosed in a
16571 // #ifdef #endif the added include directive might not be visible in the generated file.
16572 // This actually happened in the case of wget application: wget.c source file.
16573#if 0
16574 // Original version of code.
16575 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16576 {
16577 // Only set first header for the first time
16578 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16579 {
16580 if (firstExistingHeader == NULL)
16581 {
16582 firstExistingHeader = (*i);
16583 firsti = i;
16584 }
16585 // always updates last header
16586 lastExistingHeader = (*i);
16587 lasti = i;
16588 }
16589 }
16590#else
16591 // DQ (9/12/2020): New version of code. Addresses insertion after last endif if it is after any #include.
16592 if ( (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration ||
16593 (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration )
16594 {
16595 // Only set first header for the first time
16596 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16597 {
16598 if (firstExistingHeader == NULL)
16599 {
16600 firstExistingHeader = (*i);
16601 firsti = i;
16602 }
16603 // always updates last header
16604 lastExistingHeader = (*i);
16605 lasti = i;
16606 }
16607 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration)
16608 {
16609 if (firstExistingEndif == NULL)
16610 {
16611 firstExistingEndif = (*i);
16612 firsti = i;
16613 }
16614 // always updates last header
16615 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16616 // lastExistingEndif = (*i);
16617 lasti = i;
16618 }
16619 }
16620#endif
16621 }
16622
16623 // based on existing header positions, insert the new header
16624 if (asLastHeader)
16625 {
16626 if (lastExistingHeader == NULL) // No last header at all, just append to after
16627 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16628 else
16629 {
16630 comments->insert (lasti+1, newheader);
16631 }
16632 }
16633 else // add as the first header
16634 {
16635 if (firstExistingHeader == NULL) // no existing header at all, just append to after
16636 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16637 else
16638 {
16639 comments->insert (firsti, newheader);
16640 }
16641 }
16642 }
16643 else // No comments at all, first and last header mean the same, just attach to the located node
16644 stmt->addToAttachedPreprocessingInfo(newheader, position);
16645
16646#if 0
16647 printf ("Exiting as a test! \n");
16648 ROSE_ASSERT(false);
16649#endif
16650
16651}
16652
16653
16654// The recommended version
16655PreprocessingInfo* SageInterface::insertHeader(SgSourceFile * source_file, const std::string & filename, bool isSystemHeader , bool asLastHeader)
16656{
16657 ROSE_ASSERT (source_file != NULL);
16658 SgGlobal* globalScope = source_file->get_globalScope();
16659 ROSE_ASSERT (globalScope != NULL);
16660
16661 PreprocessingInfo* result=NULL;
16662 string content;
16663 if (isSystemHeader)
16664 content = "#include <" + filename + "> \n";
16665 else
16666 content = "#include \"" + filename + "\" \n";
16667
16668#if 0
16669 // 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.
16671
16672 if (asLastHeader )
16673 position = PreprocessingInfo::after;
16674 else
16675 position = PreprocessingInfo::before;
16676#endif
16677
16678 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations ();
16679 if (stmtList.size()>0) // the source file is not empty
16680 {
16681 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16682 {
16683 // Attach to the first eligible located statement
16684 //must have this judgement, otherwise wrong file will be modified!
16685 //It could also be the transformation generated statements with #include attached
16686 if ( (*j)->get_file_info()->isSameFile(globalScope->get_file_info()) || (*j)->get_file_info()->isTransformation() )
16687 {
16688#if 0
16689 printf ("In SageInterface::insertHeader(): Found statement to attached #include: *j = %p = %s \n",*j,(*j)->class_name().c_str());
16690 printf (" --- unparseToString() = %s \n",(*j)->unparseToString().c_str());
16691#endif
16692 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16693 ROSE_ASSERT(result);
16694 insertHeader (*j, result, asLastHeader);
16695 //successful = true;
16696#if 0
16697 printf ("Exiting as a test! \n");
16698 ROSE_ABORT();
16699#endif
16700 break;
16701 }
16702 } // end for
16703 }
16704 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16705 {
16706 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16707 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16708 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16709 ROSE_ABORT();
16710#if 0 // [Robb Matzke 2021-03-24]: unreachable
16711 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration,
16712 content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16713 ROSE_ASSERT(result);
16714 globalScope->addToAttachedPreprocessingInfo(result,position);
16715#endif
16716 // successful = true;
16717 }
16718
16719#if 0
16720 printf ("In SageInterface::insertHeader(): Marking include file for filename = %s as a transformation \n",filename.c_str());
16721#endif
16722
16723 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16724 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16725 // when multiple files are used on the command line.
16726 if (result)
16727 result->get_file_info()->setTransformation();
16728
16729#if 0
16730 printf ("Exiting as a test! \n");
16731 ROSE_ASSERT(false);
16732#endif
16733
16734 // must be inserted once somehow
16735 // 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
16736 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16737 // ROSE_ASSERT(successful==true);
16738 return result;
16739
16740} // end insertHeader
16741
16742
16745SageInterface::attachArbitraryText(SgLocatedNode* target, const std::string & text, PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/)
16746 {
16747 // DQ (1/13/2014): This function needs a better mechanism than attaching text to the AST unparser as a CPP directive.
16748
16749 ROSE_ASSERT(target != NULL); //dangling #define xxx is not allowed in the ROSE AST
16750 PreprocessingInfo* result = NULL;
16751
16752 // DQ (1/13/2014): It is a mistake to attach arbitrary test to the AST as a #define
16753 // (since we evaluate all #define CPP declarations to be a self-referential macro).
16754 // For now I will make it a #if CPP declaration, since these are not evaluated internally.
16755 // PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorDefineDeclaration;
16756 PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorIfDeclaration;
16757
16758 // DQ (1/13/2014): Output a warning so that this can be fixed whereever it is used.
16759 printf ("Warning: attachArbitraryText(): attaching arbitrary text to the AST as a #if declaration: text = %s \n",text.c_str());
16760
16761 result = new PreprocessingInfo (mytype,text, "transformation-generated", 0, 0, 0, position);
16762 ROSE_ASSERT(result);
16763
16764 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16765 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16766 // when multiple files are used on the command line.
16767 result->get_file_info()->setTransformation();
16768
16769 target->addToAttachedPreprocessingInfo(result);
16770
16771 return result;
16772 }
16773
16774
16776// 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.
16778{
16779 // This is part of Wave support in ROSE.
16780// #if CAN_NOT_COMPILE_WITH_ROSE != true
16781// #if CAN_NOT_COMPILE_WITH_ROSE == 0
16782#ifndef USE_ROSE
16783 ROSE_ASSERT(target != NULL);
16784 AttachedPreprocessingInfoType *info= target->getAttachedPreprocessingInfo ();
16785 if (info == NULL) return;
16786 AttachedPreprocessingInfoType::iterator j;
16787 for (j = info->begin (); j != info->end (); j++)
16788 {
16789 if ((*j)->getTypeOfDirective()==PreprocessingInfo::CMacroCall)
16790 {
16791#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
16792 // DQ (2/17/2016): The token_container type is not defined if Wave is not available.
16793 std::ostringstream os;
16794 token_container tc = (*j)->get_macro_call()->expanded_macro;
16795 token_container::const_iterator iter;
16796 for (iter=tc.begin(); iter!=tc.end(); iter++)
16797 os<<(*iter).get_value();
16798 //cout<<"Found a macro call: "<<(*j)->getString()<<
16799 //"\nexpanding it to: "<<os.str()<<endl;
16800 string pragmaText = target->get_pragma()->get_pragma();
16801 string targetString = (*j)->getString();
16802 string replacement = os.str();
16803 // repeat until not found
16804 size_t pos1 = pragmaText.find(targetString);
16805 while (pos1 != string::npos)
16806 {
16807 pragmaText.replace(pos1, targetString.size(), replacement);
16808 pos1 = pragmaText.find(targetString);
16809 }
16810 delete target->get_pragma();
16811 target->set_pragma(buildPragma(pragmaText));
16812#endif
16813 } // end if
16814 } // end for
16815#endif
16816}
16817
16822 using namespace SageBuilder;
16823 SgStatement* body = NULL;
16824 if (isSgWhileStmt(loopOrSwitch) || isSgDoWhileStmt(loopOrSwitch) ||
16825 isSgForStatement(loopOrSwitch)) {
16826 body = SageInterface::getLoopBody(isSgScopeStatement(loopOrSwitch));
16827 } else if (isSgSwitchStatement(loopOrSwitch)) {
16828 body = isSgSwitchStatement(loopOrSwitch)->get_body();
16829 }
16830 ROSE_ASSERT (body);
16831 std::vector<SgBreakStmt*> breaks = SageInterface::findBreakStmts(body);
16832 if (!breaks.empty()) {
16833 static int breakLabelCounter = 0;
16834 SgLabelStatement* breakLabel =
16835 buildLabelStatement("breakLabel" +
16836StringUtility::numberToString(++breakLabelCounter),
16838 isSgScopeStatement(loopOrSwitch->get_parent()));
16839 insertStatement(loopOrSwitch, breakLabel, false);
16840 for (size_t j = 0; j < breaks.size(); ++j) {
16841 SgGotoStatement* newGoto = buildGotoStatement(breakLabel);
16842
16843 isSgStatement(breaks[j]->get_parent())->replace_statement(breaks[j],
16844 newGoto);
16845 newGoto->set_parent(breaks[j]->get_parent());
16846 }
16847 }
16848 }
16849
16851 {
16852 ROSE_ASSERT(node!=NULL);
16853 SgClassDeclaration *decl = isSgClassDeclaration(node);
16854 if (decl==NULL)
16855 return false;
16856 else
16857 return (decl->get_class_type() == SgClassDeclaration::e_struct)? true:false;
16858 }
16859
16861 {
16862 ROSE_ASSERT(node!=NULL);
16863 SgClassDeclaration *decl = isSgClassDeclaration(node);
16864 if (decl==NULL)
16865 return false;
16866 else
16867 return (decl->get_class_type() == SgClassDeclaration::e_union)? true:false;
16868 }
16869
16870
16871void
16872SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
16873 PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
16874 {
16875 ROSE_ASSERT(stmt_src != NULL);
16876 ROSE_ASSERT(stmt_dst != NULL);
16877 AttachedPreprocessingInfoType* infoList = stmt_src->getAttachedPreprocessingInfo();
16878
16879 if (infoList == NULL)
16880 {
16881#if 0
16882 printf ("In SageInterface::movePreprocessingInfo(): infoList == NULL: exiting movePreprocessingInfo() \n");
16883#endif
16884 return;
16885 }
16886
16887 AttachedPreprocessingInfoType* infoToRemoveList = new AttachedPreprocessingInfoType();
16888
16889#if 0
16890 printf ("In SageInterface::movePreprocessingInfo(): \n");
16891 printf (" --- stmt_src = %p = %s src_position = %d \n",stmt_src,stmt_src->class_name().c_str(),src_position);
16892 SgDeclarationStatement* src_declarationStatement = isSgDeclarationStatement(stmt_src);
16893 if (src_declarationStatement != NULL)
16894 {
16895 printf ("src_declarationStatement->get_firstNondefiningDeclaration() = %p \n",src_declarationStatement->get_firstNondefiningDeclaration());
16896 printf ("src_declarationStatement->get_definingDeclaration() = %p \n",src_declarationStatement->get_definingDeclaration());
16897 }
16898 printf (" --- stmt_dst = %p = %s dst_position = %d \n",stmt_dst,stmt_dst->class_name().c_str(),dst_position);
16899 SgDeclarationStatement* dst_declarationStatement = isSgDeclarationStatement(stmt_dst);
16900 if (dst_declarationStatement != NULL)
16901 {
16902 printf ("dst_declarationStatement->get_firstNondefiningDeclaration() = %p \n",dst_declarationStatement->get_firstNondefiningDeclaration());
16903 printf ("dst_declarationStatement->get_definingDeclaration() = %p \n",dst_declarationStatement->get_definingDeclaration());
16904 }
16905 printf (" --- src_position = %s \n",PreprocessingInfo::relativePositionName(src_position).c_str());
16906 printf (" --- dst_position = %s \n",PreprocessingInfo::relativePositionName(dst_position).c_str());
16907 printf (" --- usePrepend = %s \n",usePrepend ? "true" : "false");
16908
16909 printf (" --- infoList = %p \n",infoList);
16910 printf (" --- infoToRemoveList = %p \n",infoToRemoveList);
16911
16912 AttachedPreprocessingInfoType* dst_infoList = stmt_dst->getAttachedPreprocessingInfo();
16913 printf (" --- dst_infoList = %p \n",dst_infoList);
16914#endif
16915#if 0
16916 printf ("****************************************************************** \n");
16917 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_src \n");
16919 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_dst \n");
16921 printf ("****************************************************************** \n");
16922#endif
16923
16924 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
16925 // This is a bug in the support for building a new prototype from a defining function declaration
16926 // and caused this problem. This assertion will prevent this sort of error from happening again.
16927 ROSE_ASSERT(infoList == NULL || stmt_src->getAttachedPreprocessingInfo() != stmt_dst->getAttachedPreprocessingInfo());
16928
16929
16930#if 0
16931 printf (" --- infoList->size() = %zu \n",infoList->size());
16932 printf (" --- infoToRemoveList->size() = %zu \n",infoToRemoveList->size());
16933#endif
16934
16935#if 0
16936 int counter = 0;
16937
16938 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
16939 {
16940 // DQ (11/19/2020): Added assertion.
16941 ROSE_ASSERT(*i != NULL);
16942
16943 // DQ (11/19/2020): Why do we have a dynamic cast here.
16944 // PreprocessingInfo * info = dynamic_cast<PreprocessingInfo*> (*i);
16945 PreprocessingInfo * info = *i;
16946 ROSE_ASSERT(info != NULL);
16947
16948 // printf ("counter = %d \n",counter);
16949 printf ("counter = %d Processing PreprocessingInfo = %s \n",counter,info->getString().c_str());
16950 counter++;
16951 }
16952
16953 counter = 0;
16954#endif
16955
16956 PreprocessingInfo* prevItem = NULL;
16957
16958 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
16959 {
16960 ROSE_ASSERT(*i != NULL);
16961
16962 PreprocessingInfo * info = *i;
16963 ROSE_ASSERT(info != NULL);
16964
16965 if ( // match enum values in http://rosecompiler.org/ROSE_HTML_Reference/classPreprocessingInfo.html
16966 (info->getTypeOfDirective()==PreprocessingInfo::C_StyleComment)||
16967 (info->getTypeOfDirective()==PreprocessingInfo::CplusplusStyleComment)||
16968 (info->getTypeOfDirective()==PreprocessingInfo::FortranStyleComment)||
16969 (info->getTypeOfDirective()==PreprocessingInfo::F90StyleComment)||
16970 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeDeclaration )||
16971 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeNextDeclaration )||
16972 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDefineDeclaration )||
16973 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorUndefDeclaration)||
16974 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfdefDeclaration )||
16975 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfndefDeclaration )||
16976 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfDeclaration )||
16977 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDeadIfDeclaration )||
16978 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElseDeclaration )||
16979 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElifDeclaration )||
16980 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEndifDeclaration ) ||
16981 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEnd_ifDeclaration ) ||
16982 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorLineDeclaration) ||
16983 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorErrorDeclaration) ||
16984 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorWarningDeclaration) ||
16985 // DQ (12/28/2020): Added support for C linkage specifications.
16986 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationStart) ||
16987 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationEnd)
16988 )
16989 {
16990 // move all source preprocessing info if the desired source type is not specified or matching
16991 // a specified desired source type
16992 if ( src_position == PreprocessingInfo::undef || info->getRelativePosition() == src_position)
16993 {
16994 if (usePrepend == true)
16995 {
16996 // Liao (1/27/2015): modification to fix order of CPP directives when a list of them are moved.
16997 if (prevItem == NULL)
16998 {
16999 // addToAttachedPreprocessingInfo() is poorly designed, the last parameter is used
17000 // to indicate appending or prepending by reusing the type of relative position.
17001 // this is very confusing for users
17002 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::before);
17003 }
17004 else // there is a previous item, insert after it
17005 {
17006 stmt_dst->insertToAttachedPreprocessingInfo(info, prevItem);
17007 }
17008 prevItem = info;
17009 }
17010 else
17011 {
17012 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::after);
17013 }
17014 // 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.
17015 info->setAsTransformation();
17016
17017 // DQ (10/13/2015): This is a problem for the token-based unparsing since we don't want to have this
17018 // set_containsTransformationToSurroundingWhitespace() function cause the isModified flag to be set.
17019 // So we have to detect it being set and reset it as needed. An alternative would be to have a
17020 // non-ROSETTA generate function that didn't have the isModified flag set for the seter access function.
17021 // Note that the inputmoveDeclarationToInnermostScope_test2015_123.C file demonstrates this problem.
17022 bool isMarkedAsModified = stmt_dst->get_isModified();
17023 stmt_dst->set_containsTransformationToSurroundingWhitespace(true);
17024 if (isMarkedAsModified == false)
17025 {
17026 if (stmt_dst->get_isModified() == true)
17027 {
17028 stmt_dst->set_isModified(false);
17029 }
17030 }
17031 (*infoToRemoveList).push_back(*i);
17032 }
17033
17034 // adjust dst position if needed
17035 if (dst_position != PreprocessingInfo::undef)
17036 {
17037 info->setRelativePosition(dst_position);
17038 }
17039 } // end if
17040 } // end for
17041
17042 // Remove the element from the list of comments at the current astNode
17043 AttachedPreprocessingInfoType::iterator j;
17044 for (j = (*infoToRemoveList).begin(); j != (*infoToRemoveList).end(); j++)
17045 {
17046 infoList->erase( find(infoList->begin(),infoList->end(),*j) );
17047 }
17048 }
17049
17050
17051//----------------------------
17052// Sometimes, the preprocessing info attached to a declaration has to be
17053// moved 'up' if another declaration is inserted before it.
17054// This is a workaround for the broken LowLevelRewrite::insert() and the private
17055// LowLevelRewrite::reassociatePreprocessorDeclarations()
17056//
17057// input:
17058// *stmt_dst: the new inserted declaration
17059// *stmt_src: the existing declaration with preprocessing information
17060// tasks:
17061// judge if stmt_src has propressingInfo with headers, ifdef, etc..
17062// add them into stmt_dst
17063// delete them from stmt_dst
17064// More general usage: move preprocessingInfo of stmt_src to stmt_dst, should used before any
17065// LoweLevel::remove(stmt_src)
17067 PreprocessingInfo::RelativePositionType src_position/*=PreprocessingInfo::undef*/,
17068 PreprocessingInfo::RelativePositionType dst_position/*=PreprocessingInfo::undef*/,
17069 bool usePrepend /*= false */)
17070 {
17071 movePreprocessingInfo (stmt_src, stmt_dst, src_position, dst_position, usePrepend);
17072 } // moveUpPreprocessingInfo()
17073
17074
17079static bool isNotRelPos (const PreprocessingInfo* info,
17081{
17082 return info && (info->getRelativePosition () != pos);
17083}
17084
17089static bool isRelPos (const PreprocessingInfo* info,
17091{
17092 return info && !isNotRelPos (info, pos);
17093}
17094
17095
17097void SageInterface::cutPreprocessingInfo (SgLocatedNode* src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17098{
17099 ASSERT_not_null(src_node);
17100
17101 // [Rasmussen,Sottile 2023.01.10]: Replaced deleted bind2nd (as of 2017)
17102 AttachedPreprocessingInfoType* info = src_node->get_attachedPreprocessingInfoPtr();
17103 if (info)
17104 {
17105 // copy elements to save_buf where isRelPos() is false
17106 remove_copy_if(info->begin(),
17107 info->end(),
17108 back_inserter(save_buf),
17109 [pos](auto x) { return !isRelPos(x, pos); }
17110 );
17111
17112 // delete copied elements from save_buf
17113 AttachedPreprocessingInfoType::iterator
17114 new_end = remove_if(info->begin(),
17115 info->end(),
17116 [pos](auto x) { return isRelPos(x, pos); }
17117 );
17118 info->erase(new_end, info->end());
17119 }
17120}
17121
17122static AttachedPreprocessingInfoType *
17123createInfoList (SgLocatedNode* s)
17124{
17125 ROSE_ASSERT (s);
17126 AttachedPreprocessingInfoType* info_list = s->get_attachedPreprocessingInfoPtr ();
17127 if (!info_list)
17128 {
17129 info_list = new AttachedPreprocessingInfoType;
17130 ROSE_ASSERT (info_list);
17131 s->set_attachedPreprocessingInfoPtr (info_list);
17132 }
17133
17134 // Guarantee a non-NULL pointer.
17135 ROSE_ASSERT (info_list);
17136 return info_list;
17137}
17138
17140void SageInterface::pastePreprocessingInfo (SgLocatedNode* dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17141{
17142 if (save_buf.size()==0) return;
17143 // if front
17144 AttachedPreprocessingInfoType* info = createInfoList (dst_node);
17145 ROSE_ASSERT (info);
17146
17147 // DQ (9/26/2007): Commented out as part of move from std::list to std::vector
17148 // printf ("Commented out front_inserter() as part of move from std::list to std::vector \n");
17149 // copy (save_buf.rbegin (), save_buf.rend (), front_inserter (*info));
17150
17151 // Liao (10/3/2007), vectors can only be appended at the rear
17152 if (pos==PreprocessingInfo::before)
17153 {
17154 for(AttachedPreprocessingInfoType::reverse_iterator i=save_buf.rbegin();i!=save_buf.rend();i++)
17155 info->insert(info->begin(),*i);
17156 }
17157 // if back
17158 else if (pos==PreprocessingInfo::after)
17159 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17160 else if (pos==PreprocessingInfo::inside)
17161 {
17162 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17163 cerr<<"SageInterface::pastePreprocessingInfo() pos==PreprocessingInfo::inside is not supported."<<endl;
17164 save_buf[0]->display("ttt");
17165 }
17166}
17167
17169{
17170 ROSE_ASSERT(locatedNode != NULL);
17171 AttachedPreprocessingInfoType *comments =
17172 locatedNode->getAttachedPreprocessingInfo ();
17173
17174 if (comments != NULL)
17175 {
17176 printf ("-----------------------------------------------\n");
17177 printf ("Found an IR node (at %p of type: %s) in file %s \n",
17178 locatedNode, locatedNode->class_name ().c_str (),
17179 (locatedNode->get_file_info ()->get_filenameString ()).c_str ());
17180 int counter = 0;
17181 AttachedPreprocessingInfoType::iterator i;
17182 for (i = comments->begin (); i != comments->end (); i++)
17183 {
17184 printf
17185 ("with attached preprocessingInfo numbering #%d :------------- \nclassification= %s:\nString format:%s\n",
17186 counter++,
17187 PreprocessingInfo::directiveTypeName ((*i)->getTypeOfDirective ()).
17188 c_str (), (*i)->getString ().c_str ());
17189 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
17190 printf ("relative position is: inside\n");
17191 else
17192 printf ("relative position is: %s\n", \
17193 ((*i)->getRelativePosition () == PreprocessingInfo::before) ? "before" : "after");
17194 }
17195 }
17196 else
17197 {
17198 printf ("No attached preprocessing info. (at %p of type: %s): \n", locatedNode,
17199 locatedNode->sage_class_name ());
17200 }
17201}
17202
17214template <class ParentNode>
17215static
17216SgBasicBlock* ensureBasicBlock_aux( ParentNode& stmt,
17217 SgStatement* (ParentNode::*getter) () const,
17218 void (ParentNode::*setter) (SgStatement*)
17219 )
17220{
17221 SgStatement* const body_stmt = (stmt.*getter)();
17222 SgBasicBlock* basicblock = isSgBasicBlock(body_stmt);
17223
17224 if (basicblock == NULL) {
17225 basicblock = SageBuilder::buildBasicBlock(body_stmt);
17226 (stmt.*setter)(basicblock);
17227 basicblock->set_parent(&stmt);
17228 }
17229
17230 ROSE_ASSERT (basicblock != NULL);
17231 return basicblock;
17232}
17233
17235{
17236 SgStatement* b = fs->get_loop_body();
17237 if (!isSgBasicBlock(b)) {
17239 fs->set_loop_body(b);
17240 b->set_parent(fs);
17241
17242 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17244 }
17245 ROSE_ASSERT (isSgBasicBlock(b));
17246 return isSgBasicBlock(b);
17247}
17248
17250{
17251 SgStatement* b = cs->get_body();
17252 if (!isSgBasicBlock(b)) {
17254 cs->set_body(b);
17255 b->set_parent(cs);
17256
17257 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17259 }
17260 ROSE_ASSERT (isSgBasicBlock(b));
17261 return isSgBasicBlock(b);
17262}
17263
17265{
17266 SgStatement* b = cs->get_body();
17267 if (!isSgBasicBlock(b)) {
17269 cs->set_body(b);
17270 b->set_parent(cs);
17271
17272 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17274 }
17275 ROSE_ASSERT (isSgBasicBlock(b));
17276 return isSgBasicBlock(b);
17277}
17278
17280{
17281 ROSE_ASSERT (fs != NULL);
17282
17283 return ensureBasicBlock_aux(*fs, &SgUpcForAllStatement::get_loop_body, &SgUpcForAllStatement::set_loop_body);
17284}
17285
17287 SgStatement* b = fs->get_body();
17288 if (!isSgBasicBlock(b)) {
17290 fs->set_body(b);
17291 b->set_parent(fs);
17292
17293 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17295 }
17296 ROSE_ASSERT (isSgBasicBlock(b));
17297 return isSgBasicBlock(b);
17298 }
17299
17301 SgStatement* b = fs->get_body();
17302 if (!isSgBasicBlock(b)) {
17304 fs->set_body(b);
17305 b->set_parent(fs);
17306
17307 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17309 }
17310 ROSE_ASSERT (isSgBasicBlock(b));
17311 return isSgBasicBlock(b);
17312 }
17313
17315 SgStatement* b = fs->get_body();
17316 if (!isSgBasicBlock(b)) {
17318 fs->set_body(b);
17319 b->set_parent(fs);
17320
17321 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17323 }
17324 ROSE_ASSERT (isSgBasicBlock(b));
17325 return isSgBasicBlock(b);
17326 }
17327
17329 SgStatement* b = fs->get_true_body();
17330 if (!isSgBasicBlock(b)) {
17332 fs->set_true_body(b);
17333 b->set_parent(fs);
17334
17335 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17337#if 0
17338 printf ("In SageInterface::ensureBasicBlockAsTrueBodyOfIf(): Added SgBasicBlock b = %p to addedBasicBlockNodes.size() = %zu \n",b,addedBasicBlockNodes.size());
17339#endif
17340 }
17341 ROSE_ASSERT (isSgBasicBlock(b));
17342 return isSgBasicBlock(b);
17343 }
17344
17345// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17347 {
17348 // Record where normalization have been done so that we can preform denormalizations as required
17349 // for the token-based unparsing to generate minimal diffs.
17350
17351 SgBasicBlock* bb = isSgBasicBlock(s);
17352 ROSE_ASSERT(bb != NULL);
17353 addedBasicBlockNodes.push_back(bb);
17354#if 0
17355 printf ("In SageInterface::recordNormalizations(): Added SgBasicBlock = %p to addedBasicBlockNodes.size() = %zu \n",bb,addedBasicBlockNodes.size());
17356#endif
17357 }
17358
17359// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17361 {
17362 // Remove unused basic block IR nodes added as part of normalization.
17363 // This function should be called before the unparse step.
17364
17365#if 0
17366 printf ("In SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17367#endif
17368
17369 for (vector<SgBasicBlock*>::iterator i = addedBasicBlockNodes.begin(); i != addedBasicBlockNodes.end(); i++)
17370 {
17371 SgBasicBlock* b = *i;
17372 ROSE_ASSERT(b != NULL);
17373 if (b->get_statements().size() == 1)
17374 {
17375#if 0
17376 printf ("This SgBasicBlock can be denormalized: b = %p \n",b);
17377#endif
17378 SgStatement* parentOfBlock = isSgStatement(b->get_parent());
17379 ROSE_ASSERT(parentOfBlock != NULL);
17380
17381 bool wasPreviouslyModified = parentOfBlock->get_isModified();
17382
17383 SgStatement* s = b->get_statements()[0];
17384 ROSE_ASSERT(s != NULL);
17385
17386 switch (parentOfBlock->variantT())
17387 {
17388 case V_SgIfStmt:
17389 {
17390 SgIfStmt* ifStatement = isSgIfStmt(parentOfBlock);
17391 if (b == ifStatement->get_true_body())
17392 {
17393#if 0
17394 printf ("Calling set_true_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17395#endif
17396 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17397 ifStatement->set_true_body(s);
17398#if 0
17399 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17400#endif
17401 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17402 s->set_parent(ifStatement);
17403#if 0
17404 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17405#endif
17406 *i = NULL;
17407 // delete b;
17408 }
17409 else
17410 {
17411 ROSE_ASSERT(b == ifStatement->get_false_body());
17412#if 0
17413 printf ("Calling set_false_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17414#endif
17415 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17416 ifStatement->set_false_body(s);
17417#if 0
17418 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17419#endif
17420 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17421 s->set_parent(ifStatement);
17422#if 0
17423 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17424#endif
17425 *i = nullptr;
17426#if 0
17427 printf ("Mark as NOT modified after calling set_false_body on ifStatement = %p = %n \n",ifStatement,ifStatement->class_name().c_str());
17428#endif
17429#if 0
17430 printf ("Error: case not handled in case V_SgIfStmt: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17431 ROSE_ABORT();
17432#endif
17433 }
17434 break;
17435 }
17436
17437 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17438 case V_SgWhileStmt:
17439 {
17440 SgWhileStmt* whileStatement = isSgWhileStmt(parentOfBlock);
17441 if (b == whileStatement->get_body())
17442 {
17443 whileStatement->set_body(s);
17444 s->set_parent(whileStatement);
17445 }
17446 break;
17447 }
17448
17449 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17450 case V_SgSwitchStatement:
17451 {
17452 SgSwitchStatement* switchStatement = isSgSwitchStatement(parentOfBlock);
17453 if (b == switchStatement->get_body())
17454 {
17455 switchStatement->set_body(s);
17456 s->set_parent(switchStatement);
17457 }
17458 break;
17459 }
17460
17461 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17462 case V_SgForStatement:
17463 {
17464 SgForStatement* forStatement = isSgForStatement(parentOfBlock);
17465 if (b == forStatement->get_loop_body())
17466 {
17467 forStatement->set_loop_body(s);
17468 s->set_parent(forStatement);
17469 }
17470 break;
17471 }
17472
17473 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17474 case V_SgCaseOptionStmt:
17475 {
17476 SgCaseOptionStmt* caseOptionStatement = isSgCaseOptionStmt(parentOfBlock);
17477 if (b == caseOptionStatement->get_body())
17478 {
17479 caseOptionStatement->set_body(s);
17480 s->set_parent(caseOptionStatement);
17481 }
17482 break;
17483 }
17484
17485 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17486 case V_SgDefaultOptionStmt:
17487 {
17488 SgDefaultOptionStmt* defaultOptionStatement = isSgDefaultOptionStmt(parentOfBlock);
17489 if (b == defaultOptionStatement->get_body())
17490 {
17491 defaultOptionStatement->set_body(s);
17492 s->set_parent(defaultOptionStatement);
17493 }
17494 break;
17495 }
17496
17497 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17498 case V_SgDoWhileStmt:
17499 {
17500 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(parentOfBlock);
17501 if (b == doWhileStatement->get_body())
17502 {
17503 doWhileStatement->set_body(s);
17504 s->set_parent(doWhileStatement);
17505 }
17506 break;
17507 }
17508
17509 default:
17510 {
17511 printf ("Error: case not handled in switch: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17512 ROSE_ABORT();
17513 }
17514 }
17515
17516 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17517 if (wasPreviouslyModified == false)
17518 {
17519 if (parentOfBlock->get_isModified() == true)
17520 {
17521#if 0
17522 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());
17523#endif
17524 parentOfBlock->set_isModified(false);
17525 }
17526
17527 }
17528#if 0
17529 printf ("Exiting as a test! \n");
17530 ROSE_ABORT();
17531#endif
17532 }
17533 }
17534
17535#if 0
17536 printf ("Leaving SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17537#endif
17538 }
17539
17540
17542 SgStatement* b = fs->get_false_body();
17543 // if no false body at all AND no-create-empty-body
17544 if (!createEmptyBody && (b == NULL || isSgNullStatement(b)))
17545 return NULL;
17546 if (!isSgBasicBlock(b)) {
17547 b = SageBuilder::buildBasicBlock(b); // This works if b is NULL as well (producing an empty block)
17548 fs->set_false_body(b);
17549 b->set_parent(fs);
17550
17551 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17553 }
17554 ROSE_ASSERT (isSgBasicBlock(b));
17555 return isSgBasicBlock(b);
17556 }
17557
17559 SgStatement* b = fs->get_body();
17560 if (!isSgBasicBlock(b)) {
17562 fs->set_body(b);
17563 b->set_parent(fs);
17564 }
17565 ROSE_ASSERT (isSgBasicBlock(b));
17566 return isSgBasicBlock(b);
17567 }
17568
17570{
17571 SgStatement* b = fs->get_body();
17572 if (!isSgBasicBlock(b)) {
17574 fs->set_body(b);
17575 b->set_parent(fs);
17576 }
17577 ROSE_ASSERT (isSgBasicBlock(b));
17578 return isSgBasicBlock(b);
17579}
17580
17582{
17583 bool rt = false;
17584 ROSE_ASSERT(s);
17585 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17586 ROSE_ASSERT(p);
17587
17588 switch (p->variantT())
17589 {
17590 case V_SgForStatement:
17591 {
17592 if (isSgForStatement(p)->get_loop_body() == s)
17593 rt = true;
17594 break;
17595 }
17596 case V_SgUpcForAllStatement: // PP
17597 {
17598 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17599 if (upcforall.get_loop_body() == s)
17600 rt = true;
17601 break;
17602 }
17603 case V_SgWhileStmt:
17604 {
17605 if (isSgWhileStmt(p)->get_body() == s)
17606 rt = true;
17607 break;
17608 }
17609 case V_SgDoWhileStmt:
17610 {
17611 if (isSgDoWhileStmt(p)->get_body() == s)
17612 rt = true;
17613 break;
17614 }
17615 case V_SgSwitchStatement:
17616 {
17617 if (isSgSwitchStatement(p)->get_body() == s)
17618 rt = true;
17619 break;
17620 }
17621 case V_SgCaseOptionStmt:
17622 {
17623 if (isSgCaseOptionStmt(p)->get_body() == s)
17624 rt = true;
17625 break;
17626 }
17627 case V_SgDefaultOptionStmt:
17628 {
17629 if (isSgDefaultOptionStmt(p)->get_body() == s)
17630 rt = true;
17631 break;
17632 }
17633 case V_SgCatchOptionStmt:
17634 {
17635 if (isSgCatchOptionStmt(p)->get_body() == s)
17636 rt = true;
17637 break;
17638 }
17639 case V_SgIfStmt:
17640 {
17641 if (isSgIfStmt(p)->get_true_body() == s)
17642 rt = true;
17643 else if (isSgIfStmt(p)->get_false_body() == s)
17644 rt = true;
17645 break;
17646 }
17647 default:
17648 {
17649 if (isSgOmpBodyStatement(p))
17650 rt = true;
17651 break;
17652 }
17653 }
17654 return rt;
17655}
17656
17658//etc.
17660{
17661 ROSE_ASSERT (singleStmt != NULL); // not NULL
17662 ROSE_ASSERT (isSgBasicBlock(singleStmt) == NULL); //not a block
17663 ROSE_ASSERT (isBodyStatement(singleStmt) == true); // is a body statement
17664
17665 SgBasicBlock* rt = NULL;
17666
17667
17668
17669 SgStatement* s = singleStmt;
17670 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17671 ROSE_ASSERT(p);
17672 switch (p->variantT())
17673 {
17674 case V_SgForStatement:
17675 {
17676 if (isSgForStatement(p)->get_loop_body() == s)
17677 rt = ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17678 break;
17679 }
17680 case V_SgUpcForAllStatement: // PP
17681 {
17682 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17683
17684 if (upcforall.get_loop_body() == s)
17685 rt = ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17686 break;
17687 }
17688 case V_SgWhileStmt:
17689 {
17690 if (isSgWhileStmt(p)->get_body() == s)
17691 rt = ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17692 break;
17693 }
17694 case V_SgDoWhileStmt:
17695 {
17696 if (isSgDoWhileStmt(p)->get_body() == s)
17697 rt = ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17698 break;
17699 }
17700 case V_SgSwitchStatement:
17701 {
17702 if (isSgSwitchStatement(p)->get_body() == s)
17703 rt = ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17704 break;
17705 }
17706 case V_SgCaseOptionStmt:
17707 {
17708 if (isSgCaseOptionStmt(p)->get_body() == s)
17709 rt = ensureBasicBlockAsBodyOfCaseOption(isSgCaseOptionStmt(p));
17710 break;
17711 }
17712 case V_SgDefaultOptionStmt:
17713 {
17714 if (isSgDefaultOptionStmt(p)->get_body() == s)
17715 rt = ensureBasicBlockAsBodyOfDefaultOption(isSgDefaultOptionStmt(p));
17716 break;
17717 }
17718 case V_SgCatchOptionStmt:
17719 {
17720 if (isSgCatchOptionStmt(p)->get_body() == s)
17721 rt = ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17722 break;
17723 }
17724 case V_SgIfStmt:
17725 {
17726 if (isSgIfStmt(p)->get_true_body() == s)
17727 rt = ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17728 else if (isSgIfStmt(p)->get_false_body() == s)
17729 rt = ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17730 break;
17731 }
17732 default:
17733 {
17734 if (isSgOmpBodyStatement(p))
17735 {
17736 rt = ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17737 }
17738 break;
17739 }
17740 }
17741 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.
17742 return rt;
17743}
17744
17745#if 0
17746SgLocatedNode* SageInterface::ensureBasicBlockAsParent(SgStatement* s)
17747{
17748 ROSE_ASSERT(s);
17749
17750 //Vulov: The parent of a statement is not necessarily a statement. It could be SgStatementExpression
17751 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17752 ROSE_ASSERT(p);
17753 switch (p->variantT())
17754 {
17755 case V_SgBasicBlock: return isSgBasicBlock(p);
17756 case V_SgForStatement:
17757 {
17758 if (isSgForStatement(p)->get_loop_body() == s)
17759 return ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17760 else if (isSgForStatement(p)->get_test() == s)
17761 {
17762 }
17763 else if (isSgForStatement(p)->get_for_init_stmt() == s)
17764 {
17765 }
17766 else ROSE_ABORT();
17767 break;
17768 }
17769 case V_SgUpcForAllStatement: // PP
17770 {
17771 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17772
17773 if (upcforall.get_loop_body() == s)
17774 return ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17775
17776 ROSE_ASSERT( (s == upcforall.get_for_init_stmt())
17777 || (s == upcforall.get_test())
17778 );
17779 break;
17780 }
17781 case V_SgWhileStmt:
17782 {
17783 if (isSgWhileStmt(p)->get_body() == s)
17784 return ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17785 else if (isSgWhileStmt(p)->get_condition() == s)
17786 {
17787 }
17788 else ROSE_ABORT();
17789 break;
17790 }
17791 case V_SgDoWhileStmt:
17792 {
17793 if (isSgDoWhileStmt(p)->get_body() == s)
17794 return ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17795 else if (isSgDoWhileStmt(p)->get_condition() == s)
17796 {
17797 }
17798 else ROSE_ABORT();
17799 break;
17800 }
17801 case V_SgSwitchStatement:
17802 {
17803 if (isSgSwitchStatement(p)->get_body() == s)
17804 return ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17805 else if (isSgSwitchStatement(p)->get_item_selector() == s)
17806 {
17807 }
17808 else ROSE_ABORT();
17809 break;
17810 }
17811 case V_SgCatchOptionStmt:
17812 {
17813 if (isSgCatchOptionStmt(p)->get_body() == s)
17814 return ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17815 else if (isSgCatchOptionStmt(p)->get_condition() == s)
17816 {
17817 }
17818 else ROSE_ABORT();
17819 break;
17820 }
17821 case V_SgIfStmt:
17822 {
17823 if (isSgIfStmt(p)->get_true_body() == s)
17824 return ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17825 else if (isSgIfStmt(p)->get_false_body() == s)
17826 return ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17827 else if (isSgIfStmt(p)->get_conditional() == s)
17828 {
17829 }
17830 else ROSE_ABORT();
17831 break;
17832 }
17833 default:
17834 {
17835 if (isSgOmpBodyStatement(p))
17836 {
17837 return ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17838 }
17839 else
17840 // Liao, 7/3/2008 We allow other conditions to fall through,
17841 // they are legal parents with list of statements as children.
17842 //cerr << "Unhandled parent block:"<< p->class_name() << endl;
17843 // ROSE_ASSERT (!"Bad parent in ensureBasicBlockAsParent");
17844 break;
17845 }
17846 }
17847 return p;
17848}
17849
17850 void SageInterface::changeAllLoopBodiesToBlocks(SgNode* top) {
17851 cerr<<"Warning: SageInterface::changeAllLoopBodiesToBlocks() is being replaced by SageInterface::changeAllBodiesToBlocks()."<<endl;
17852 cerr<<"Please use SageInterface::changeAllBodiesToBlocks() if you can."<<endl;
17854 }
17855
17856#endif
17857 void SageInterface::changeAllBodiesToBlocks(SgNode* top, bool createEmptyBody /*= true*/ ) {
17858 class Visitor: public AstSimpleProcessing {
17859 public:
17860 bool allowEmptyBody;
17861 Visitor (bool flag):allowEmptyBody(flag) {}
17862 virtual void visit(SgNode* n) {
17863
17864 bool wasPreviouslyModified = n->get_isModified();
17865
17866 switch (n->variantT()) {
17867 case V_SgForStatement: {
17868 ensureBasicBlockAsBodyOfFor(isSgForStatement(n));
17869 break;
17870 }
17871 case V_SgWhileStmt: {
17872 ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(n));
17873 break;
17874 }
17875 case V_SgDoWhileStmt: {
17876 ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(n));
17877 break;
17878 }
17879 case V_SgSwitchStatement: {
17880 ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(n));
17881 break;
17882 }
17883 case V_SgIfStmt: {
17884 ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(n));
17885 ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(n), allowEmptyBody);
17886#if 0
17887 // DQ (10/6/2015): Debugging why changes are being made to the AST for token-based unparsing.
17888 printf ("In changeAllBodiesToBlocks(): case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
17889#endif
17890#if 0
17891 // Reset this to false as a test.
17892 if (n->get_isModified() == true)
17893 {
17894 n->set_isModified(false);
17895 printf ("In changeAllBodiesToBlocks(): AFTER RESET: case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
17896 }
17897#endif
17898 break;
17899 }
17900 case V_SgCatchOptionStmt: {
17901 ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(n));
17902 break;
17903 }
17904 case V_SgUpcForAllStatement: {
17905 ensureBasicBlockAsBodyOfUpcForAll(isSgUpcForAllStatement(n));
17906 break;
17907 }
17908
17909 default:
17910 {
17911 if (isSgOmpBodyStatement(n))
17912 ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(n));
17913 break;
17914 }
17915 }
17916
17917 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17918 if (wasPreviouslyModified == false)
17919 {
17920 if (n->get_isModified() == true)
17921 {
17922#if 0
17923 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());
17924#endif
17925 n->set_isModified(false);
17926 }
17927
17928 }
17929
17930 }
17931 };
17932 Visitor(createEmptyBody).traverse(top, postorder);
17933 }
17934
17935
17936// Replace a given expression with a list of statements produced by a
17937// generator. The generator, when given a variable as input, must produce
17938// some code which leaves its result in the given variable. The output
17939// from the generator is then inserted into the original program in such a
17940// way that whenever the expression had previously been evaluated, the
17941// statements produced by the generator are run instead and their result is
17942// used in place of the expression.
17943// Assumptions: not currently traversing from or the statement it is in
17944void
17946 {
17947 // DQ (3/11/2006): The problem here is that the test expression for a "for loop" (SgForStmt)
17948 // is assumed to be a SgExpression. This was changed in Sage III as part of a bugfix and so
17949 // the original assumptions upon which this function was based are not incorrect, hence the bug!
17950 // Note that a number of cases were changed when this fix was made to SageIII (see documentation
17951 // for SgScopeStatement).
17952
17953#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
17954 SgStatement* enclosingStatement = getStatementOfExpression(from);
17955 SgExprStatement* exprStatement = isSgExprStatement(enclosingStatement);
17956
17957 SgForStatement* forStatement = isSgForStatement(enclosingStatement);
17958 SgReturnStmt* returnStatement = isSgReturnStmt(enclosingStatement);
17959 SgVariableDeclaration* varDeclarationStatement = isSgVariableDeclaration(enclosingStatement);
17960
17961
17962 // DQ (3/11/2006): Bugfix for special cases of conditional that are either SgStatement or SgExpression IR nodes.
17963
17964 ROSE_ASSERT (exprStatement || forStatement || returnStatement || varDeclarationStatement);
17965
17966 if (varDeclarationStatement)
17967 {
17969 }
17970 else
17971 {
17972 SgExpression* root = getRootOfExpression(from);
17973 ROSE_ASSERT (root);
17974 // printf ("root = %p \n",root);
17975 {
17976 if (forStatement && forStatement->get_increment() == root)
17977 {
17978 // printf ("Convert step of for statement \n");
17979 // Convert step of for statement
17980 // for (init; test; e) body; (where e contains from) becomes
17981 // for (init; test; ) {
17982 // body (with "continue" changed to "goto label");
17983 // label: e;
17984 // }
17985 // std::cout << "Converting for step" << std::endl;
17986 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(forStatement->get_increment());
17987 forStatement->get_increment()->set_parent(incrStmt);
17988
17989 SageInterface::addStepToLoopBody(forStatement, incrStmt);
17991 forStatement->set_increment(ne);
17992 ne->set_parent(forStatement);
17994 }
17995 else
17996 {
17997 SgStatement* enclosingStmtParent = isSgStatement(enclosingStatement->get_parent());
17998 assert (enclosingStmtParent);
17999 SgWhileStmt* whileStatement = isSgWhileStmt(enclosingStmtParent);
18000 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(enclosingStmtParent);
18001 SgIfStmt* ifStatement = isSgIfStmt(enclosingStmtParent);
18002 SgSwitchStatement* switchStatement = isSgSwitchStatement(enclosingStmtParent);
18003 SgForStatement* enclosingForStatement = isSgForStatement(enclosingStmtParent);
18004 if (enclosingForStatement && enclosingForStatement->get_test() == exprStatement)
18005 {
18006 // Convert test of for statement:
18007 // for (init; e; step) body; (where e contains from) becomes
18008 // for (init; true; step) {
18009 // bool temp;
18010 // temp = e;
18011 // if (!temp) break;
18012 // body;
18013 // }
18014 // in which "temp = e;" is rewritten further
18015 // std::cout << "Converting for test" << std::endl;
18016 pushTestIntoBody(enclosingForStatement);
18018 }
18019 else if (whileStatement && whileStatement->get_condition() == exprStatement)
18020 {
18021 // printf ("Convert while statements \n");
18022 // Convert while statement:
18023 // while (e) body; (where e contains from) becomes
18024 // while (true) {
18025 // bool temp;
18026 // temp = e;
18027 // if (!temp) break;
18028 // body;
18029 // }
18030 // in which "temp = e;" is rewritten further
18031 // std::cout << "Converting while test" << std::endl;
18032 pushTestIntoBody(whileStatement);
18033 // FixSgTree(whileStatement);
18035 }
18036 else if (doWhileStatement && doWhileStatement->get_condition() == exprStatement)
18037 {
18038 // printf ("Convert do-while statements \n");
18039 // Convert do-while statement:
18040 // do body; while (e); (where e contains from) becomes
18041 // {bool temp = true;
18042 // do {
18043 // body (with "continue" changed to "goto label";
18044 // label:
18045 // temp = e;} while (temp);}
18046 // in which "temp = e;" is rewritten further
18047 // std::cout << "Converting do-while test" << std::endl;
18048 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18049 // printf ("Building IR node #14: new SgBasicBlock = %p \n",new_statement);
18050 assert (doWhileStatement->get_parent());
18051 new_statement->set_parent(doWhileStatement->get_parent());
18052 myStatementInsert(doWhileStatement, new_statement, false);
18053 SageInterface::myRemoveStatement(doWhileStatement);
18054 SgName varname = "rose__temp1"; // Does not need to be unique, but must not be used in user code anywhere
18055 SgAssignInitializer* assignInitializer = buildAssignInitializer(
18056 buildBoolValExp(true));
18057 //SageInterface::getBoolType(doWhileStatement));
18059 varname, buildBoolType(), assignInitializer, new_statement);
18060
18061 SgInitializedName* initname = new_decl->get_variables().back();
18062 initname->set_scope(new_statement);
18063
18064 // DQ (12/14/2006): set the parent of the SgAssignInitializer to the variable (SgInitializedName).
18065 assignInitializer->set_parent(initname);
18066
18067#if 1
18068 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18070#else
18071 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18072 new_statement->insert_symbol(varname, varsym);
18073 varsym->set_parent(new_statement->get_symbol_table());
18074#endif
18075
18076 SageInterface::appendStatement(new_decl, new_statement);
18077 SageInterface::appendStatement(doWhileStatement, new_statement);
18078 assert (varsym);
18079 SgCastExp* castExp1 = buildCastExp(root,buildBoolType());
18080 SgVarRefExp* vr = buildVarRefExp(varsym);
18081 vr->set_lvalue(true);
18082
18083 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp1);
18084
18085 SageInterface::addStepToLoopBody(doWhileStatement, temp_setup);
18086 SgVarRefExp* varsymVr = buildVarRefExp(varsym);
18087
18089 varsymVr->set_parent(condStmt);
18090 doWhileStatement->set_condition(condStmt);
18091 condStmt->set_parent(doWhileStatement);
18093 }
18094 else if (ifStatement && ifStatement->get_conditional() == exprStatement)
18095 {
18096 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18097 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18098 assert (ifStatement->get_parent());
18099 new_statement->set_parent(ifStatement->get_parent());
18100 myStatementInsert(ifStatement, new_statement, false);
18102 SgName varname = "rose__temp2"; // Does not need to be unique, but must not be used in user code anywhere
18103 SgBoolValExp* trueVal = buildBoolValExp(true);
18104
18106
18108 buildBoolType(), ai,new_statement);
18109 SgInitializedName* initname = new_decl->get_variables().back();
18110 ai->set_parent(initname);
18111 initname->set_scope(new_statement);
18112#if 1
18113 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18115#else
18116 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18117 new_statement->insert_symbol(varname, varsym);
18118 varsym->set_parent(new_statement->get_symbol_table());
18119#endif
18120 SageInterface::appendStatement(new_decl, new_statement);
18121 ifStatement->set_parent(new_statement);
18122 assert (varsym);
18123
18124 SgCastExp* castExp2 = SageBuilder::buildCastExp(root, SageInterface::getBoolType(ifStatement));
18125 SgVarRefExp* vr = buildVarRefExp(varsym);
18126 vr->set_lvalue(true);
18127 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp2 );
18128 SageInterface::appendStatement(temp_setup, new_statement);
18129 SageInterface::appendStatement(ifStatement, new_statement);
18132 ifStatement->set_conditional(es);
18133 es->set_parent(ifStatement);
18135 }
18136 else if (switchStatement && switchStatement->get_item_selector() == exprStatement)
18137 {
18138 SgExpression* switchCond = exprStatement->get_expression();
18139 ROSE_ASSERT (switchCond);
18140 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18141 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18142 assert (switchStatement->get_parent());
18143 new_statement->set_parent(switchStatement->get_parent());
18144 myStatementInsert(switchStatement, new_statement, false);
18145 SageInterface::myRemoveStatement(switchStatement);
18146 SgName varname = "rose__temp3"; // Does not need to be unique, but must not be used in user code anywhere
18147 switchCond->set_parent(NULL);
18148 SgVariableDeclaration* new_decl = SageBuilder::buildVariableDeclaration(varname, switchCond->get_type(), SageBuilder::buildAssignInitializer(switchCond), new_statement);
18150 SageInterface::appendStatement(new_decl, new_statement);
18151 switchStatement->set_parent(new_statement);
18152 assert (varsym);
18153
18154
18155 SageInterface::appendStatement(switchStatement, new_statement);
18158 switchStatement->set_item_selector(es);
18159 es->set_parent(switchStatement);
18161 }
18162 else
18163 {
18164 // printf ("Handles expression and return statements \n");
18165 // Handles expression and return statements
18166 // std::cout << "Converting other statement" << std::endl;
18168 }
18169 }
18170 }
18171 }
18172
18173#endif
18174
18175 // printf ("Leaving replaceExpressionWithStatement(from,to) \n");
18176 }
18177
18186
18187// Similar to replaceExpressionWithStatement, but with more restrictions.
18188// Assumptions: from is not within the test of a loop or if
18189// not currently traversing from or the statement it is in
18191 {
18192
18193#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18194 SgStatement* stmt = getStatementOfExpression(from);
18195
18196 if (isSgExprStatement(stmt))
18197 {
18198 SgExpression* top = getRootOfExpression(from);
18199
18200
18201 if (top == from)
18202 {
18203 SgStatement* generated = to->generate(0);
18204 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18205 generated->set_parent(stmt->get_parent());
18206 return;
18207 }
18208 else
18209 {
18210 if (isSgAssignOp(top) && isSgAssignOp(top)->get_rhs_operand() == from)
18211 {
18212 SgAssignOp* t = isSgAssignOp(top);
18213 SgStatement* generated = to->generate(t->get_lhs_operand());
18214 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18215 generated->set_parent(stmt->get_parent());
18216 return;
18217 }
18218 else
18219 {
18220 // printf ("In replaceSubexpressionWithStatement(): Statement not generated \n");
18221 }
18222 }
18223 }
18224
18225 // cout << "1: " << getStatementOfExpression(from)->unparseToString() << endl;
18227 // cout << "2: " << getStatementOfExpression(from)->unparseToString() << endl;
18228 convertInitializerIntoAssignment(init);
18229 // cout << "3: " << getStatementOfExpression(from)->unparseToString() << endl;
18230 // cout << "3a: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18231 SgExprStatement* new_stmt = isSgExprStatement(getStatementOfExpression(from));
18232 assert (new_stmt != NULL); // Should now have this form because of conversion
18233 replaceAssignmentStmtWithStatement(new_stmt, to);
18234
18235 // printf ("In replaceSubexpressionWithStatement: new_stmt = %p = %s \n",new_stmt,new_stmt->class_name().c_str());
18236 // cout << "4: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18237
18238#endif
18239 }
18240
18241
18242 // Liao, 6/27/2008
18243 //Tasks
18244 // find all return statements
18245 // rewrite it to temp = expression; return temp; if expression is not a single value.
18246 // insert s right before 'return xxx;'
18248 {
18249 int result = 0;
18250 ROSE_ASSERT(func&&s);
18251 // vector<SgReturnStmt* > stmts = findReturnStmts(func);
18252 Rose_STL_Container <SgNode* > stmts = NodeQuery::querySubTree(func, V_SgReturnStmt);
18253 //vector<SgReturnStmt*>::iterator i;
18254 Rose_STL_Container<SgNode*>::iterator i;
18255 for (i=stmts.begin();i!=stmts.end();i++)
18256 {
18257 SgReturnStmt* cur_stmt = isSgReturnStmt(*i);
18258 ROSE_ASSERT(cur_stmt);
18259 SgExpression * exp = cur_stmt->get_expression();
18260 // TV (05/03/2011) Catch the case "return ;" where exp is NULL
18261 bool needRewrite = (exp != NULL) && !(isSgValueExp(exp));
18262 if (needRewrite)
18263 {
18264 splitExpression(exp);
18265 }
18266 // avoid reusing the statement
18267 if (result>=1 )
18268 s = copyStatement(s);
18269 insertStatementBefore(cur_stmt,s);
18270 result ++;
18271 } // for
18272 if (stmts.size()==0 ) // a function without any return at all,
18273 {
18274 SgBasicBlock * body = func->get_definition()->get_body();
18275 if (body== NULL)
18276 {
18277 cout<<"In instrumentEndOfFunction(), found an empty function body.! "<<endl;
18278 ROSE_ABORT();
18279 }
18280 appendStatement(s,body);
18281 result ++;
18282 }
18283 return result;
18284 } // instrumentEndOfFunction
18285
18287 {
18288 ROSE_ASSERT(stmt);
18289 return ((stmt->get_declarationModifier()).get_storageModifier()).isStatic();
18290 } // isStatic()
18291
18294 {
18295 ROSE_ASSERT(stmt);
18296 return ((stmt->get_declarationModifier()).get_storageModifier()).setStatic();
18297 }
18298
18300 {
18301 ROSE_ASSERT(stmt);
18302 return ((stmt->get_declarationModifier()).get_storageModifier()).isExtern();
18303 } // isExtern()
18304
18305
18308 {
18309 ROSE_ASSERT(stmt);
18310 return ((stmt->get_declarationModifier()).get_storageModifier()).setExtern();
18311 }
18312
18313 // Check if an SgInitializedName is "mutable' (has storage modifier set)
18315 {
18316 ROSE_ASSERT(name);
18317 return name->get_storageModifier().isMutable();
18318 }
18319
18320 // True if a parameter name is a Jovial output parameter
18322 {
18323 return isMutable(name);
18324 }
18325
18326 // Get a vector of Jovial input parameters from the function parameter list
18327 // TODO: Look into making this work for Fortran
18328 std::vector<SgInitializedName*> SageInterface::getInParameters(const SgInitializedNamePtrList &params)
18329 {
18330 std::vector<SgInitializedName*> in_params;
18331 BOOST_FOREACH (SgInitializedName* name, params)
18332 {
18333 if (!isJovialOutParam(name)) in_params.push_back(name);
18334 }
18335 return in_params;
18336 }
18337
18338 // Get a list of Jovial output parameters from the function parameter list
18339 // TODO: Look into making this work for Fortran
18340 std::vector<SgInitializedName*> SageInterface::getOutParameters(const SgInitializedNamePtrList &params)
18341 {
18342 std::vector<SgInitializedName*> out_params;
18343 BOOST_FOREACH (SgInitializedName* name, params)
18344 {
18345 if (isJovialOutParam(name)) out_params.push_back(name);
18346 }
18347 return out_params;
18348 }
18349
18351 switch (expr->variantT()) {
18352 case V_SgCharVal: return (long long)(isSgCharVal(expr)->get_value());
18353 case V_SgSignedCharVal: return (long long)(isSgSignedCharVal(expr)->get_value());
18354 case V_SgUnsignedCharVal: return isSgUnsignedCharVal(expr)->get_value();
18355 case V_SgShortVal: return (long long)(isSgShortVal(expr)->get_value());
18356 case V_SgUnsignedShortVal: return isSgUnsignedShortVal(expr)->get_value();
18357 case V_SgIntVal: return (long long)(isSgIntVal(expr)->get_value());
18358 case V_SgUnsignedIntVal: return isSgUnsignedIntVal(expr)->get_value();
18359 case V_SgLongIntVal: return (long long)(isSgLongIntVal(expr)->get_value());
18360 case V_SgUnsignedLongVal: return isSgUnsignedLongVal(expr)->get_value();
18361 case V_SgLongLongIntVal: return isSgLongLongIntVal(expr)->get_value();
18362 case V_SgUnsignedLongLongIntVal: return isSgUnsignedLongLongIntVal(expr)->get_value();
18363 case V_SgBoolValExp: return (long long )(isSgBoolValExp(expr)->get_value());
18364
18365 // DQ (2/18/2015): Make this a better error message.
18366 // default: ROSE_ASSERT (!"Bad kind in getIntegerConstantValue");
18367 default:
18368 {
18369 printf ("ERROR: In SageInterface::getIntegerConstantValue(): default reached: expr = %p = %s \n",expr,expr->class_name().c_str());
18370 ROSE_ASSERT (false);
18371 }
18372
18373 }
18374
18375 ROSE_ASSERT (!"Bad kind return in getIntegerConstantValue");
18376 return 0;
18377 }
18378
18379
18380#ifdef ROSE_ENABLE_BINARY_ANALYSIS
18381// tps : 28 Oct 2008 - support for finding the main interpretation
18382// rpm : 18 Sep 2009 - rewritten to support multiple files per interpretation
18386SageInterface::getMainInterpretation(SgAsmGenericFile *file)
18387{
18388 SgBinaryComposite *binary = getEnclosingNode<SgBinaryComposite>(file);
18389 ROSE_ASSERT(binary!=NULL);
18390
18391 /* Find the only header or the PE header of this file */
18392 SgAsmGenericHeader *requisite_header = NULL; /*the returned interpretation must point to this header*/
18393 const SgAsmGenericHeaderPtrList &headers = file->get_headers()->get_headers();
18394 if (1==headers.size()) {
18395 requisite_header = headers[0];
18396 } else {
18397 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18398 if (isSgAsmPEFileHeader(*hi)) {
18399 requisite_header = isSgAsmPEFileHeader(*hi);
18400 break;
18401 }
18402 }
18403 }
18404 ROSE_ASSERT(requisite_header!=NULL);
18405
18406 /* Find an interpretation that points to this header */
18407 const SgAsmInterpretationPtrList &interps = binary->get_interpretations()->get_interpretations();
18408 for (SgAsmInterpretationPtrList::const_iterator ii=interps.begin(); ii!=interps.end(); ++ii) {
18409 const SgAsmGenericHeaderPtrList &headers = (*ii)->get_headers()->get_headers();
18410 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18411 if ((*hi)==requisite_header)
18412 return *ii;
18413 }
18414 }
18415
18416 ROSE_ASSERT(!"no appropriate interpretation");
18417 return NULL;
18418}
18419#endif
18420
18422 {
18423 public:
18424 // This is the simpliest possible version of a deep copy SgCopyHelp::copyAst() member function.
18425 // Note that the root of the does not have its file info set like its children.
18426 virtual SgNode *copyAst(const SgNode *n)
18427 {
18428 // DQ (2/26/2009): This defines a simple concept of "deep" copy. It forms a more testable building block, I hope.
18429 SgNode* copy = n->copy(*this);
18430
18431 // Also mark this as a transformation and to be output in unparsing (so it will be output by the code generator).
18432 Sg_File_Info* fileInfo = copy->get_file_info();
18433 if (fileInfo != NULL)
18434 {
18435 // Must make this for output (checked in unparser), marking as a transformation is not checked
18436 fileInfo->setOutputInCodeGeneration();
18437 fileInfo->setTransformation();
18438 }
18439
18440 return copy;
18441 }
18442 } collectDependentDeclarationsCopyType;
18443
18444
18446 {
18447 // This traversal collects the includes at the top of a file.
18448
18449 public:
18450 vector<PreprocessingInfo*> cppDirectiveList;
18451
18452 void visit(SgNode *astNode);
18453 };
18454
18455
18456void
18458 {
18459 SgLocatedNode* locatedNode = isSgLocatedNode(astNode);
18460 if (locatedNode != NULL)
18461 {
18462 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
18463
18464 if (comments != NULL)
18465 {
18466#if 0
18467 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18468#endif
18469 AttachedPreprocessingInfoType::iterator i;
18470 for (i = comments->begin(); i != comments->end(); i++)
18471 {
18472 ROSE_ASSERT ( (*i) != NULL );
18473#if 0
18474 printf (" Attached Comment (relativePosition=%s): %s\n",
18475 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18476 (*i)->getString().c_str());
18477 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
18478 (*i)->get_file_info()->display("comment/directive location");
18479#endif
18480
18481 // We only save the #include directives, but likely we should be collecting ALL directives to
18482 // avoid the collection of #include that is meant to be hidden in an #if 0 ... #endif pairing.
18483 // if ((*i)->getTypeOfDirective() == PreprocessingInfo::CpreprocessorIncludeDeclaration)
18484 {
18485 // This is an include directive.
18486 cppDirectiveList.push_back(*i);
18487#if 0
18488 printf (" Attached include directive (relativePosition=%s): %s\n",
18489 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18490 (*i)->getString().c_str());
18491#endif
18492 }
18493 }
18494 }
18495 else
18496 {
18497#if 0
18498 printf ("No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18499#endif
18500 }
18501 }
18502 }
18503
18504
18505// This is part of a mechanism to collect directives from code that is to be outlined.
18506// However if we collect include directives we likely should really be collecting ALL
18507// directives (since the #include could be inside of an #if 0 ... #endif pairing.
18508// This level of detail will be addressed later (in an iterative approach).
18509vector<PreprocessingInfo*>
18510collectCppDirectives ( SgSourceFile* file )
18511 {
18512 // This function is used to collect include directives from the whole file.
18514 t.traverse(file,preorder);
18515
18516 return t.cppDirectiveList;
18517 }
18518
18519
18520vector<PreprocessingInfo*>
18521collectCppDirectives ( SgLocatedNode* n )
18522 {
18523 // This function is used to collect include directives from specific dependent declarations.
18525 t.traverse(n,preorder);
18526
18527 return t.cppDirectiveList;
18528 }
18529
18530// Debugging support.
18531void
18532outputPreprocessingInfoList ( const vector<PreprocessingInfo*> & l )
18533 {
18534 // This function support debugging the generated directive lists.
18535
18536 vector<PreprocessingInfo*>::const_iterator i = l.begin();
18537 while ( i != l.end() )
18538 {
18539 printf (" Attached include directive (relativePosition=%s): %s\n",
18540 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18541 (*i)->getString().c_str());
18542 i++;
18543 }
18544 }
18545
18546
18547
18549getAssociatedDeclaration( SgScopeStatement* scope )
18550 {
18551 //TODO This should become a member of SgScopeStatement
18552
18553 SgDeclarationStatement* declaration = NULL;
18554 switch(scope->variantT())
18555 {
18556 case V_SgNamespaceDefinitionStatement:
18557 {
18558 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
18559 declaration = namespaceDefinition->get_namespaceDeclaration();
18560 break;
18561 }
18562
18563 case V_SgClassDefinition:
18564 case V_SgTemplateInstantiationDefn: // Liao, 5/12/2009
18565 {
18566 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
18567 declaration = classDefinition->get_declaration();
18568 break;
18569 }
18570
18571 default:
18572 {
18573 printf ("Error: default reached in getAssociatedDeclaration(): scope = %p = %s \n",scope,scope->class_name().c_str());
18574 ROSE_ABORT();
18575 }
18576 }
18577
18578 // There may be some scopes that don't have an associated declaration.
18579 ROSE_ASSERT(declaration != NULL);
18580
18581 return declaration;
18582 }
18583
18584
18586 {
18587 public:
18588 // Accumulate a list of copies of associated declarations referenced in the AST subtree
18589 // (usually of the outlined functions) to insert in the separate file to support outlining.
18590 vector<SgDeclarationStatement*> declarationList;
18591
18592 // Save the list of associated symbols of dependent declarations identified so that we can
18593 // support their replacement in the new AST.
18594 vector<SgSymbol*> symbolList;
18595
18596 // Keep track of declarations already copied so that we don't copy them more than once and try to insert them.
18597 set<SgDeclarationStatement*> alreadySavedDeclarations;
18598
18599 // Required visit function for the AST traversal
18600 void visit(SgNode *astNode);
18601 private:
18602 void addDeclaration(SgDeclarationStatement* decl);
18603 };
18604
18606getGlobalScopeDeclaration( SgDeclarationStatement* inputDeclaration )
18607 {
18608 // DQ (2/16/2009): Basically if a class is used from a namespace (or any outer scope) and we
18609 // outline the reference to the class, we have to declare not the class but the outer scope
18610 // (which will have the class included).
18611
18612 SgDeclarationStatement* returnDeclaration = inputDeclaration;
18613
18614 // I think that we have to copy the outer scope if the declaration's scope is not SgGlobal.
18615 SgScopeStatement* scope = inputDeclaration->get_scope();
18616 ROSE_ASSERT(scope != NULL);
18617
18618 // printf ("inputDeclaration->get_scope() = %p = %s \n",scope,scope->class_name().c_str());
18619
18620 // If the input declaration is not in global scope then find the parent declaration that is in global scope!
18621 SgGlobal* globalScope = isSgGlobal(scope);
18622 if (globalScope == NULL)
18623 {
18624 // Traverse back to the global scope to include outer declarations which contain the "declaration"
18625 // printf ("Traverse back to the global scope to include outer declarations \n");
18626
18627 SgScopeStatement* parentScope = scope;
18628 SgDeclarationStatement* associatedDeclaration = returnDeclaration;
18629 ROSE_ASSERT(parentScope != NULL);
18630 while (globalScope == NULL)
18631 {
18632 associatedDeclaration = getAssociatedDeclaration(parentScope);
18633 ROSE_ASSERT(associatedDeclaration != NULL);
18634
18635 parentScope = parentScope->get_scope();
18636 globalScope = isSgGlobal(parentScope);
18637 }
18638
18639 returnDeclaration = associatedDeclaration;
18640 }
18641
18642 return returnDeclaration;
18643 }
18644
18645
18646// Debugging support.
18647void
18648outputDeclarationList ( const vector<SgDeclarationStatement*> & l )
18649 {
18650 // This function support debugging the generated declarations.
18651
18652 int counter = 0;
18653 vector<SgDeclarationStatement*>::const_iterator i = l.begin();
18654 while ( i != l.end() )
18655 {
18656 printf ("In outputDeclarationList(): list[%d] = %p = %s = %s \n",counter++,*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
18657 i++;
18658 }
18659 }
18660
18661void CollectDependentDeclarationsTraversal::addDeclaration(SgDeclarationStatement* declaration)
18662{
18663 // If there was a declaration found then handle it.
18664 if (declaration != NULL)
18665 {
18666 // Reset the defining declaration in case there is an outer declaration that is more important
18667 // to consider the dependent declaration (e.g. a class in a namespace). In general this will
18668 // find the associated outer declaration in the global scope.
18669 SgDeclarationStatement* dependentDeclaration = getGlobalScopeDeclaration(declaration);
18670
18671 // This declaration is in global scope so we just copy the declaration
18672 // For namespace declarations: they may have the save name but they have to be saved separated.
18673 if (alreadySavedDeclarations.find(dependentDeclaration) == alreadySavedDeclarations.end())
18674 {
18675#if 0
18676 printf ("In CollectDependentDeclarationsTraversal::visit(): selected dependentDeclaration = %p = %s = %s \n",
18677 dependentDeclaration,dependentDeclaration->class_name().c_str(),SageInterface::get_name(dependentDeclaration).c_str());
18678#endif
18679 // DQ (2/22/2009): Semantics change for this function, just save the original declaration, not a copy of it.
18680 declarationList.push_back(dependentDeclaration);
18681
18682 // Record this as a copied declaration
18683 alreadySavedDeclarations.insert(dependentDeclaration);
18684#if 0
18685 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18686 printf ("############### ADDING dependentDeclaration = %p = %s to alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18687 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18688#endif
18689 // DQ (2/21/2009): Added assertions (will be inforced in SageInterface::appendStatementWithDependentDeclaration()).
18690 // ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
18691 }
18692 else
18693 {
18694#if 0
18695 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18696 printf ("############### EXISTING dependentDeclaration = %p = %s found in alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18697 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18698#endif
18699 }
18700 }
18701}
18702
18704static std::vector<SgTypedefDeclaration*> collectTypedefDeclarations(SgType* type)
18705{
18706 ROSE_ASSERT(type != NULL);
18707 std::vector<SgTypedefDeclaration*> result;
18708 SgType* currentType = type;
18709
18710 SgModifierType* modType = NULL;
18711 SgPointerType* pointType = NULL;
18712 SgReferenceType* refType = NULL;
18713 SgArrayType* arrayType = NULL;
18714 SgTypedefType* typedefType = NULL;
18715
18716 while (true)
18717 {
18718 modType = isSgModifierType(currentType);
18719 if(modType)
18720 {
18721 currentType = modType->get_base_type();
18722 }
18723 else
18724 {
18725 refType = isSgReferenceType(currentType);
18726 if(refType)
18727 {
18728 currentType = refType->get_base_type();
18729 }
18730 else
18731 {
18732 pointType = isSgPointerType(currentType);
18733 if ( pointType)
18734 {
18735 currentType = pointType->get_base_type();
18736 }
18737 else
18738 {
18739 arrayType = isSgArrayType(currentType);
18740 if (arrayType)
18741 {
18742 currentType = arrayType->get_base_type();
18743 }
18744 else
18745 {
18746 typedefType = isSgTypedefType(currentType);
18747 if (typedefType)
18748 {
18749 currentType = typedefType->get_base_type();
18750 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(typedefType->get_declaration());
18751 // have to try to get the defining declaration for a defining typedef declaration
18752 // otherwise AST traversal will not visit the non-defining one for a defining typedef declaration
18753 // sortSgNodeListBasedOnAppearanceOrderInSource() won't work properly
18754 SgTypedefDeclaration* decl = isSgTypedefDeclaration(tdecl->get_definingDeclaration());
18755 if (decl ==NULL)
18756 decl = tdecl;
18757 result.push_back(decl);
18758 }
18759 else
18760 {
18761 // Exit the while(true){} loop!
18762 break;
18763 }
18764 }
18765 }
18766 }
18767 }
18768 }
18769#if 0
18770 // debug here
18771 if (result.size()>0)
18772 {
18773 cout<<"------------Found a chain of typedef decls: count="<<result.size()<<endl;
18774 for (vector <SgTypedefDeclaration*>::const_iterator iter = result.begin();
18775 iter!=result.end(); iter ++)
18776 cout<<(*iter)->unparseToString()<<endl;
18777 }
18778#endif
18779 return result;
18780}
18781
18783void
18785 {
18786 // Statements that can cause us to have declaration dependences:
18787 // 1) variable declarations (through their types)
18788 // 2) function calls
18789 // 3) typedefs (through their base types)
18790 // Not implemented:
18791 // 4) static member functions (through their class)
18792 // 5) static data members (through their class)
18793 // 6) namespaces
18794 // 7) #include<> CPP directives.
18795
18796 // DQ (2/22/2009): Changing the semantics for this function,
18797 // just save the original declaration, not a copy of it.
18798
18799#if 0
18800 // Debugging support.
18801 Sg_File_Info* fileInfo = astNode->get_file_info();
18802 if (fileInfo != NULL && fileInfo->isFrontendSpecific() == false && (isSgStatement(astNode) != NULL) )
18803 {
18804 printf ("\n\nIn CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18805 // fileInfo->display("In CollectDependentDeclarationsTraversal::visit()");
18806 int counter = 0;
18807 printf ("alreadySavedDeclarations.size() = %" PRIuPTR " \n",alreadySavedDeclarations.size());
18808 for (set<SgDeclarationStatement*>::iterator i = alreadySavedDeclarations.begin(); i != alreadySavedDeclarations.end(); i++)
18809 {
18810 printf ("alreadySavedDeclarations %d: %p = %s \n",counter++,*i,(*i)->class_name().c_str());
18811 }
18812 }
18813#endif
18814
18815 // The following conditionals set this variable
18816 SgDeclarationStatement* declaration = NULL;
18817
18818 // 1) ------------------------------------------------------------------
18819 // Collect the declarations associated with referenced types in variable declarations (or any types associated with SgInitializedName IR nodes)
18820 SgInitializedName* initializedname = isSgInitializedName(astNode);
18821 if (initializedname != NULL)
18822 {
18823 SgType* type = initializedname->get_type();
18824
18825 // handle all dependent typedef declarations, if any
18826 std::vector <SgTypedefDeclaration*> typedefVec = collectTypedefDeclarations(type);
18827 for (std::vector <SgTypedefDeclaration*>::const_iterator iter =typedefVec.begin();
18828 iter != typedefVec.end(); iter++)
18829 {
18830 SgTypedefDeclaration* typedef_decl = *iter;
18831 addDeclaration(typedef_decl);
18832 symbolList.push_back(typedef_decl->get_symbol_from_symbol_table());
18833 }
18834
18835 // handle base type:
18836
18837 // We now can to strip typedefs since they are already handled by collectTypedefDeclarations()
18838 // this also reach to the defining body of a defining typedef declaration
18839 // and treat it as an independent declarations,
18840 // the assumption here is that a defining typedef declaration will only has its
18841 // nondefining declaration copied to avoid redefining of the struct.
18842 // This is also a workaround for an AST copy bug: defining body gets lost after copying
18843 // a defining typedef declaration.
18844 // Liao, 5/8/2009
18845 //
18846 // e.g. typedef struct hypre_BoxArray_struct
18847 // {
18848 // int alloc_size;
18849 // } hypre_BoxArray;
18850 //
18851 // struct hypre_BoxArray_struct will be treated as a strippedType and its declaration
18852 // will be inserted.
18853 //
18854 SgType* strippedType = type->stripType();
18855 SgNamedType* namedType = isSgNamedType(strippedType);
18856 if (namedType != NULL)
18857 {
18858 // Note that since this was obtained via the types and types are shared, this is the non-defining
18859 // declaration in original program (not the separate file is this is to support outlining into a
18860 // separate file.
18861 SgDeclarationStatement* named_decl = namedType->get_declaration();
18862 // the case of class declaration, including struct, union
18863 SgClassDeclaration* classDeclaration = isSgClassDeclaration(named_decl);
18864 if (classDeclaration != NULL)
18865 {
18866 // printf ("Found class declaration: classDeclaration = %p \n",classDeclaration);
18867 declaration = classDeclaration->get_definingDeclaration();
18868 // Liao, 12/09/2016.
18869 // In some cases, forward declaration of class types are used and sufficient, without providing defining declaration.
18870 // We should allow this.
18871 if (declaration != NULL)
18872 {
18873 // ROSE_ASSERT(declaration != NULL);
18874 addDeclaration(declaration);
18875 }
18876 else
18877 addDeclaration (classDeclaration); // we use the original forward declaration.
18878
18879 // Note that since types are shared in the AST, the declaration for a named type may be (is)
18880 // associated with the class declaration in the original file. However, we want to associated
18881 // class declaration in the current file, but since the AST copy mechanism work top-down, this
18882 // mapping form the declaration in the original file to the new declaration in the copied AST
18883 // is available in the SgCopyHelp map of copied IR nodes.
18884 // DQ (3/3/2009): Added support for symbol references to be saved (symbols in the original file).
18885 // these symbols will be mapped to their new symbols.
18886 ROSE_ASSERT(classDeclaration->hasAssociatedSymbol() == true);
18887 SgSymbol* classSymbol = classDeclaration->get_symbol_from_symbol_table();
18888 ROSE_ASSERT(classSymbol != NULL);
18889
18890 // printf ("Saving classSymbol = %p \n",classSymbol);
18891 symbolList.push_back(classSymbol);
18892 }
18893
18894 // handle Enum types
18895 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(named_decl);
18896 if (enum_decl != NULL)
18897 {
18898 declaration = enum_decl->get_definingDeclaration();
18899 ROSE_ASSERT(declaration != NULL);
18900 addDeclaration(declaration);
18901 ROSE_ASSERT(enum_decl->hasAssociatedSymbol() == true);
18902 // Liao 12/14/2012. use search_for_symbol_from_symbol_table() instead to avoid the defining/nondefing decl issue
18903 //SgSymbol* esymbol = enum_decl->get_symbol_from_symbol_table();
18904 SgSymbol* esymbol = enum_decl->search_for_symbol_from_symbol_table();
18905 ROSE_ASSERT(esymbol!= NULL);
18906 symbolList.push_back(esymbol);
18907 }
18908 } // end if namedType
18909#if 0
18910 printf ("Found reference to type = %p = %s strippedType = %p = %s \n",type,type->class_name().c_str(),strippedType,strippedType->class_name().c_str());
18911#endif
18912 }// end if (initializedname)
18913
18914 // 2) ------------------------------------------------------------------
18915 // Collect declarations associated with function calls.
18916 SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
18917 if (functionCallExp != NULL)
18918 {
18919 declaration = functionCallExp->getAssociatedFunctionDeclaration();
18920 //ROSE_ASSERT(declaration != NULL);
18921 // We allow a function pointer to have no specific declaration associated.
18922 if (declaration != NULL)
18923 addDeclaration(declaration);
18924
18925 // DQ (3/2/2009): Added support for symbol references to be saved (this can be a SgFunctionSymbol or a SgMemberFunctionSymbol).
18926 SgSymbol* functionSymbol = functionCallExp->getAssociatedFunctionSymbol();
18927 //ROSE_ASSERT(functionSymbol != NULL);
18928
18929 // printf ("Saving functionSymbol = %p \n",functionSymbol);
18930 if (functionSymbol)
18931 symbolList.push_back(functionSymbol);
18932 }
18933
18934 // 3) ------------------------------------------------------------------
18935 // Collect enumerate declarations associated with SgEnumVal
18936 SgEnumVal * eval = isSgEnumVal(astNode);
18937 if (eval != NULL)
18938 {
18939 declaration = eval->get_declaration();
18940 ROSE_ASSERT(declaration != NULL);
18941 addDeclaration(declaration);
18943 ROSE_ASSERT(symbol != NULL);
18944 symbolList.push_back(symbol);
18945 }
18946// addDeclaration(declaration); // do it in different cases individually
18947 }
18948
18949static std::map<const SgStatement*, bool> visitedDeclMap; // avoid infinite recursion
18950
18951
18953// Used to separate a function to a new source file and add necessary type declarations into the new file.
18954// NOTICE: each call to this function has to have call visitedDeclMap.clear() first!!
18955static void
18956getDependentDeclarations (SgStatement* stmt, vector<SgDeclarationStatement*> & declarationList, vector<SgSymbol*> & symbolList )
18957{
18958 // This function returns a list of the dependent declaration for any input statement.
18959 // Dependent declaration are functions called, types referenced in variable declarations, etc.
18960#if 0
18961 printf ("\n\n********************************************************** \n");
18962 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
18963 printf ("********************************************************** \n");
18964#endif
18965 visitedDeclMap[stmt]= true;
18967 t.traverse(stmt,preorder);
18968#if 0
18969 declarationList = t.declarationList;
18970 symbolList = t.symbolList;
18971#else
18972 // Merge to the parent level list
18973 copy(t.declarationList.begin(),t.declarationList.end(), back_inserter(declarationList));
18974 copy(t.symbolList.begin(),t.symbolList.end(), back_inserter(symbolList));
18975 // make their elements unique
18976 sort (declarationList.begin(), declarationList.end());
18977 vector<SgDeclarationStatement*>::iterator new_end = unique(declarationList.begin(), declarationList.end());
18978 declarationList.erase(new_end, declarationList.end());
18979
18980 sort (symbolList.begin(), symbolList.end());
18981 vector<SgSymbol*>::iterator end2 = unique(symbolList.begin(), symbolList.end());
18982 symbolList.erase(end2, symbolList.end());
18983
18984
18985 // Liao, 5/7/2009 recursively call itself to get dependent declarations' dependent declarations
18986 for (vector<SgDeclarationStatement*>::const_iterator iter = t.declarationList.begin();
18987 iter !=t.declarationList.end(); iter++)
18988 {
18989 SgDeclarationStatement* decl = *iter;
18990 SgType* base_type = NULL;
18991 SgStatement* body_stmt= NULL;
18992
18993 // grab base type for a declaration
18994 // For class declaration: grab their
18995 if (isSgClassDeclaration(decl))
18996 {
18997 base_type = isSgClassDeclaration(decl)->get_type();
18998 } else
18999 if (isSgTypedefDeclaration(decl))
19000 {
19001
19002 // we don't want to strip of nested typedef declarations
19003 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);
19004 }
19005
19006 //TODO variable declaration, function declaration: parameter list types,
19007 // multiple base_type then
19008
19009 // is the base type associated with a defining body?
19010 // TODO enum type
19011 if (isSgClassType(base_type))
19012 {
19013 SgClassDeclaration* class_decl = isSgClassDeclaration(isSgClassType(base_type)->get_declaration()->get_definingDeclaration());
19014 if (class_decl!=NULL)
19015 {
19016 body_stmt = class_decl->get_definition();
19017 }
19018 }
19019 // recursively collect dependent declarations for the body stmt
19020 if ((body_stmt!=NULL) &&(!visitedDeclMap[body_stmt]))
19021 { // avoid infinite recursion
19022 getDependentDeclarations(body_stmt, declarationList, symbolList);
19023 }
19024 }
19025#endif
19026} // end void getDependentDeclarations()
19027
19028
19029// Reorder a list of declaration statements based on their appearance order in source files
19030// This is essential to insert their copies into a new file in a right order
19031// Liao, 5/7/2009
19032vector<SgDeclarationStatement*>
19033SageInterface::sortSgNodeListBasedOnAppearanceOrderInSource(const vector<SgDeclarationStatement*>& nodevec)
19034{
19035 vector<SgDeclarationStatement*> sortedNode;
19036
19037 if (nodevec.size()==0 )
19038 return sortedNode;
19039 // no need to sort if there is only 1 element
19040 if (nodevec.size() ==1)
19041 return nodevec;
19042
19044 Rose_STL_Container<SgNode*> queryResult = NodeQuery::querySubTree(project,V_SgDeclarationStatement);
19045 for (Rose_STL_Container<SgNode*>::const_iterator iter = queryResult.begin();
19046 iter!= queryResult.end(); iter++)
19047 {
19048 // cerr<<"Trying to match:"<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19049 SgNode* cur_node = *iter;
19050 SgDeclarationStatement* cur_stmt = isSgDeclarationStatement(cur_node);
19051 ROSE_ASSERT(cur_stmt!=NULL);
19052 // Liao 12/14/2012. It is possible nodevec contains a first non-defining function declaration since the function is called in the outlined function
19053 // This is true even if the AST only has a defining function declaration.
19054 //
19055 // But that first non-defining function declaration is not traversable in AST due to it is hidden.
19056 // The solution here is to for each defining function decl traversed, convert it to the first nondefining one to do the match.
19057 SgFunctionDeclaration * func_decl = isSgFunctionDeclaration (cur_stmt);
19058 if (func_decl)
19059 {
19060 if (func_decl->get_definingDeclaration() == func_decl )
19061 {
19062 cur_stmt = func_decl->get_firstNondefiningDeclaration();
19063 ROSE_ASSERT (cur_stmt != func_decl);
19064 }
19065 }
19066 vector<SgDeclarationStatement*>::const_iterator i = find (nodevec.begin(), nodevec.end(), cur_stmt);
19067 if (i!=nodevec.end())
19068 {
19069 // It is possible we already visited a real prototype func decl before, now we see a prototype converted from a defining declaration.
19070 // We have to make sure only one copy is inserted.
19071 vector<SgDeclarationStatement*>::const_iterator j = find (sortedNode.begin(), sortedNode.end(), *i);
19072 if (j == sortedNode.end())
19073 sortedNode.push_back(*i);
19074 }
19075 }
19076
19077 if (nodevec.size() != sortedNode.size())
19078 {
19079 cerr<<"Fatal error in sortSgNodeListBasedOnAppearanceOrderInSource(): nodevec.size() != sortedNode.size()"<<endl;
19080 cerr<<"nodevec() have "<< nodevec.size()<<" elements. They are:"<<endl;
19081 for (vector<SgDeclarationStatement*>::const_iterator iter = nodevec.begin(); iter != nodevec.end(); iter++)
19082 {
19083 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19084 }
19085 cerr<<"sortedNode() have " << sortedNode.size() <<" elements. They are:"<<endl;
19086 for (vector<SgDeclarationStatement*>::const_iterator iter = sortedNode.begin(); iter != sortedNode.end(); iter++)
19087 {
19088 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19089 }
19090
19091 ROSE_ASSERT(nodevec.size() == sortedNode.size());
19092 }
19093 return sortedNode;
19094}
19095
19097// This function clears a history map transparently and return a sorted list of dependent declarations
19098std::vector<SgDeclarationStatement*>
19100 {
19101 // This function returns a list of the dependent declaration for any input statement.
19102 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19103#if 0
19104 printf ("\n\n********************************************************** \n");
19105 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19106 printf ("********************************************************** \n");
19107
19109 t.traverse(stmt,preorder);
19110
19111 return t.declarationList;
19112#else
19113 // share a single implementation for recursive lookup for dependent declaration
19114 visitedDeclMap.clear();
19115 vector<SgDeclarationStatement*> declarationList;
19116 vector<SgSymbol*> symbolList;
19117 getDependentDeclarations(stmt, declarationList, symbolList);
19118 declarationList = sortSgNodeListBasedOnAppearanceOrderInSource(declarationList);
19119#if 0
19120 printf ("\n\n ********************************************************** \n");
19121 cout<<"Found dependent decl: count="<<declarationList.size()<<endl;
19122 for ( vector<SgDeclarationStatement*>::const_iterator iter = declarationList.begin();
19123 iter != declarationList.end(); iter++)
19124 {
19125 cout<<"\t"<<(*iter)->class_name()<<" at line "<<(*iter)->get_file_info()->get_line()<<endl;
19126 if ((*iter)->variantT()== V_SgFunctionDeclaration)
19127 cout<<"func name is:"<<isSgFunctionDeclaration(*iter)->get_name().getString()<<endl;
19128 //<<(*iter)->unparseToString()<<endl; // unparseToString() won't work on outlined function
19129 }
19130 printf ("\n ********************************************************** \n");
19131#endif
19132
19133 return declarationList;
19134
19135#endif
19136 }
19137
19138
19139bool
19141 {
19142 bool returnValue = false;
19143
19144#if 0
19145 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());
19146#endif
19147
19148 if (functionName.is_null() == false)
19149 {
19150 // DQ (1/20/2019): Add operator~() to this list (see test2019_10.C).
19151 if ( functionName == "operator++" || functionName == "operator--" || functionName == "operator&" ||
19152 functionName == "operator!" || functionName == "operator*" || functionName == "operator+" ||
19153 functionName == "operator-" || functionName == "operator+" || functionName == "operator~")
19154 {
19155 returnValue = true;
19156 }
19157 }
19158
19159 return returnValue;
19160 }
19161
19162
19163// DQ (4/13/2013): We need these to support the unparing of operators defined by operator syntax or member function names.
19165bool
19167 {
19168 // DQ (4/21/2013): Reimplemented this function to support more of the prefix operators.
19169 // Also we now support when they are defined as member functions and non-member functions.
19170
19171 bool returnValue = false;
19172
19173 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(exp);
19174 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19175 // ROSE_ASSERT(memberFunctionRefExp != NULL);
19176
19177 SgName functionName;
19178 size_t numberOfOperands = 0;
19179
19180 if (memberFunctionRefExp != NULL)
19181 {
19182 ROSE_ASSERT(functionRefExp == NULL);
19183 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19184 if (memberFunctionDeclaration != NULL)
19185 {
19186 functionName = memberFunctionDeclaration->get_name();
19187 numberOfOperands = memberFunctionDeclaration->get_args().size();
19188 }
19189 }
19190 else
19191 {
19192 // This could be "friend bool operator!(const X & x);"
19193 if (functionRefExp != NULL)
19194 {
19195 SgFunctionDeclaration* functionDeclaration = functionRefExp->getAssociatedFunctionDeclaration();
19196 if (functionDeclaration != NULL)
19197 {
19198 functionName = functionDeclaration->get_name();
19199 numberOfOperands = functionDeclaration->get_args().size();
19200 }
19201 }
19202 else
19203 {
19204 // Note clear if this should be an error.
19205 printf ("In SageInterface::isPrefixOperator(): unknown case of exp = %p = %s \n",exp,exp->class_name().c_str());
19206 }
19207 }
19208
19209#if 0
19210 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);
19211#endif
19212
19213 if (isPrefixOperatorName(functionName) == true)
19214 {
19215 if (memberFunctionRefExp != NULL)
19216 {
19217 // This case is for member functions.
19218 ROSE_ASSERT(functionRefExp == NULL);
19219 if (numberOfOperands == 0)
19220 {
19221 // This is the C++ signature for the operator++() prefix operator.
19222 returnValue = true;
19223 }
19224 else
19225 {
19226 // This is the C++ signature for the operator++() postfix operator.
19227 returnValue = false;
19228 }
19229 }
19230 else
19231 {
19232 // This case is for non-member functions.
19233 ROSE_ASSERT(functionRefExp != NULL);
19234 ROSE_ASSERT(memberFunctionRefExp == NULL);
19235 if (numberOfOperands == 1)
19236 {
19237 // This is the C++ signature for the operator++() prefix operator.
19238 returnValue = true;
19239 }
19240 else
19241 {
19242 // This is the C++ signature for the operator++() postfix operator.
19243 ROSE_ASSERT(numberOfOperands == 2);
19244 returnValue = false;
19245 }
19246 }
19247 }
19248
19249#if 0
19250 printf ("Leaving SageInterface::isPrefixOperator(): returnValue = %s \n",returnValue ? "true" : "false");
19251#endif
19252
19253 return returnValue;
19254 }
19255
19256
19258bool
19260 {
19261 return ( (isPrefixOperator(exp) == false) && (isIndexOperator(exp) == false) );
19262 }
19263
19264
19266bool
19268 {
19269 bool returnValue = false;
19270 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19271 if (memberFunctionRefExp == NULL)
19272 return false;
19273
19274 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19275 if (memberFunctionDeclaration != NULL)
19276 {
19277 SgName functionName = memberFunctionDeclaration->get_name();
19278 if ( (functionName == "operator[]") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19279 {
19280 returnValue = true;
19281 }
19282 else
19283 {
19284 if ( (functionName == "operator()") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19285 {
19286 returnValue = true;
19287 }
19288 else
19289 {
19290 returnValue = false;
19291 }
19292 }
19293 }
19294
19295 return returnValue;
19296 }
19297
19298
19299// DQ (1/10/2014): Adding more general support for token based unparsing.
19301SageInterface::lastStatementOfScopeWithTokenInfo (SgScopeStatement* scope, std::map<SgNode*,TokenStreamSequenceToNodeMapping*> & tokenStreamSequenceMap)
19302 {
19303 // Return the last statement in the associated scope that has token information.
19304 SgStatement* lastStatement = NULL;
19305
19306 ROSE_ASSERT(scope != NULL);
19307
19308#if 0
19309 printf ("In SageInterface::lastStatementOfScopeWithTokenInfo(): scope = %p = %s \n",scope,scope->class_name().c_str());
19310#endif
19311
19312 SgIfStmt* ifStatement = isSgIfStmt(scope);
19313 if (ifStatement != NULL)
19314 {
19315 lastStatement = ifStatement->get_false_body();
19316 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19317 {
19318 lastStatement = ifStatement->get_true_body();
19319 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19320 {
19321 lastStatement = NULL;
19322 }
19323 }
19324
19325 printf ("Note: SgIfStmt scope in SageInterface::lastStatementOfScopeWithTokenInfo(): returning lastStatement = %p \n",lastStatement);
19326 if (lastStatement != NULL)
19327 {
19328 printf (" --- lastStatement = %p = %s \n",lastStatement,lastStatement->class_name().c_str());
19329 }
19330
19331 return lastStatement;
19332 }
19333
19334 SgStatementPtrList statementList = scope->generateStatementList();
19335 if (statementList.rbegin() != statementList.rend())
19336 {
19337 // Find the last statement with token stream information.
19338 SgStatementPtrList::reverse_iterator i = statementList.rbegin();
19339
19340 while (i != statementList.rend() && (tokenStreamSequenceMap.find(*i) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[*i] == NULL) )
19341 {
19342 i++;
19343 }
19344
19345 if (i == statementList.rend())
19346 {
19347 lastStatement = NULL;
19348 }
19349 else
19350 {
19351 lastStatement = *i;
19352 }
19353 }
19354
19355 return lastStatement;
19356 }
19357
19358
19359void
19361 {
19362 // DQ (8/12/2020): Check the access permissions of all defining and nodefining declarations (debugging support for Cxx_tests/test2020_28.C).
19363
19364 class DeclarationTraversal : public AstSimpleProcessing
19365 {
19366 public:
19367 // DeclarationTraversal() {}
19368
19369 void visit (SgNode* node)
19370 {
19371 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
19372 if (decl != NULL)
19373 {
19374 SgDeclarationStatement* definingDeclaration = isSgDeclarationStatement(decl->get_definingDeclaration());
19375 SgDeclarationStatement* firstNondefiningDeclaration = isSgDeclarationStatement(decl->get_firstNondefiningDeclaration());
19376 SgDeclarationStatement* otherDeclaration = NULL;
19377
19378 // Output access modifier information for each declaration.
19379 printf ("Found declaration = %p = %s name = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
19380 if (decl != definingDeclaration && decl != firstNondefiningDeclaration)
19381 {
19382 otherDeclaration = decl;
19383 }
19384
19385 if (definingDeclaration != NULL)
19386 {
19387 definingDeclaration->get_declarationModifier().get_accessModifier().display("definingDeclaration: accessModifier");
19388 }
19389
19390 if (firstNondefiningDeclaration != NULL)
19391 {
19392 firstNondefiningDeclaration->get_declarationModifier().get_accessModifier().display("firstNondefiningDeclaration: accessModifier");
19393 }
19394
19395 if (otherDeclaration != NULL)
19396 {
19397 otherDeclaration->get_declarationModifier().get_accessModifier().display("otherDeclaration: accessModifier");
19398 }
19399
19400 // Adding space for formatting.
19401 printf ("\n");
19402 }
19403 }
19404 };
19405
19406 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19407 DeclarationTraversal traversal;
19408 traversal.traverse(astNode, preorder);
19409 }
19410
19411
19412void
19414 {
19415 // DQ (8/14/2020): Check the symbol tables for specific scopes (debugging support).
19416
19417 class ScopeTraversal : public AstSimpleProcessing
19418 {
19419 public:
19420 void visit (SgNode* node)
19421 {
19422 SgScopeStatement* scope = isSgScopeStatement(node);
19423 if (scope != NULL)
19424 {
19425 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
19426 if (functionDefinition != NULL)
19427 {
19428 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
19429 ROSE_ASSERT(functionDeclaration != NULL);
19430
19431 string functionName = functionDeclaration->get_name();
19432
19433 printf ("functionName = %s \n",functionName.c_str());
19434
19435 if (functionName == "main")
19436 {
19437
19438 SgBasicBlock* functionBody = functionDefinition->get_body();
19439 ROSE_ASSERT(functionBody != NULL);
19440 SgSymbolTable* symbolTable = functionBody->get_symbol_table();
19441 ROSE_ASSERT(symbolTable != NULL);
19442
19443 // Print out the symbol table.
19444 symbolTable->print();
19445 }
19446 }
19447
19448 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
19449 if (namespaceDefinition != NULL)
19450 {
19451 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
19452 ROSE_ASSERT(namespaceDeclaration != NULL);
19453
19454 string namespaceName = namespaceDeclaration->get_name();
19455
19456 printf ("namespaceName = %s \n",namespaceName.c_str());
19457
19458 if (namespaceName == "B")
19459 {
19460 SgSymbolTable* symbolTable = namespaceDefinition->get_symbol_table();
19461 ROSE_ASSERT(symbolTable != NULL);
19462
19463 // Print out the symbol table.
19464 symbolTable->print();
19465 }
19466 }
19467 }
19468 }
19469 };
19470
19471 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19472 ScopeTraversal traversal;
19473 traversal.traverse(astNode, preorder);
19474 }
19475
19476//Jim Leek TODO (07/25/2023): After Dan merges his branch, please clean up all the #1f 0 stuff
19477void SageInterface::markNodeToBeUnparsed(SgNode* node, int physical_file_id)
19478 {
19479#if 0
19480 Sg_File_Info* fileInfo=node->get_file_info();
19481 if (fileInfo != NULL)
19482 {
19483 fileInfo->setTransformation();
19484 fileInfo->setOutputInCodeGeneration();
19485
19486 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19487 if (locatedNode != NULL)
19488 {
19489 // DQ (7/7/2015): Make the subtree as transformed.
19490 locatedNode->setTransformation();
19491 locatedNode->setOutputInCodeGeneration();
19492
19493 // DQ (7/8/2021): Added assertion.
19494 ROSE_ASSERT(locatedNode->get_file_info() != NULL);
19495#if 0
19496 printf ("In markNodeToBeUnparsed(): physical_file_id = %d \n",physical_file_id);
19497#endif
19498 // DQ (10/26/2020): Set the physical_file_id, required for ueader file unparsing (is it?).
19499 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19500#if 1
19501 printf ("Note: calling node markTransformationsForOutput(): node = %p = %s \n",node,node->class_name().c_str());
19502#endif
19503 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19504 // to call setTransformation() and setOutputInCodeGeneration().
19505 markTransformationsForOutput(node);
19506 }
19507 else
19508 {
19509#if 0
19510 printf ("Note: node is not a SgLocatedNode: node = %p = %s \n",node,node->class_name().c_str());
19511#endif
19512 }
19513 }
19514 else
19515 {
19516#if 0
19517 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19518#endif
19519 }
19520#else
19521 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19522 if (locatedNode != NULL)
19523 {
19524 locatedNode->setTransformation();
19525 locatedNode->setOutputInCodeGeneration();
19526
19527 // DQ (10/26/2020): Set the physical_file_id, required for header file unparsing (is it?).
19528 if (locatedNode->get_file_info() != NULL)
19529 {
19530#if 0
19531 printf ("In SageInterface::markNodeToBeUnparsed(): locatedNode = %p = %s calling set_physical_file_id(%d) \n",locatedNode,locatedNode->class_name().c_str(),physical_file_id);
19532#endif
19533 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19534 }
19535 else
19536 {
19537#if 1
19538 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19539#endif
19540 }
19541
19542 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19543 // to call setTransformation() and setOutputInCodeGeneration().
19544 // Jim Leek (07/25/2023) This doesn't seem to be redundant, it definately marks a bunch of the subtree as transformed
19545 // That otherwise isn't, but Reverse Type Dependence often fails to compile because too much gets unparsed.
19546 // markTransformationsForOutput(node);
19547 }
19548#endif
19549 }
19550
19551
19552
19553void SageInterface::markSubtreeToBeUnparsed(SgNode* root, int physical_file_id)
19554 {
19555 RoseAst ast(root);
19556 for (RoseAst::iterator i=ast.begin();i!=ast.end();++i)
19557 {
19558 markNodeToBeUnparsed(*i,physical_file_id);
19559 }
19560 }
19561
19562
19563
19565 {
19566 // DQ (7/13/2021): This function marks nodes in a subtree to be a transformation, but avoids marking subtrees of the SgCastExp.
19567 // This is important because currently the marking of an implicit cast will cause it to be unparsed, even though it is marked
19568 // as implicit. This detail of precedence of implicit flags over transformation flags needs to be fixed seperated.
19569 // This function has been implemented as part of debugging this issue.
19570
19571 class InheritedAttribute
19572 {
19573 public:
19574 int physical_file_id;
19575 bool isCastSubtree;
19576 InheritedAttribute(int file_id): physical_file_id(file_id), isCastSubtree(false) {}
19577 InheritedAttribute(const InheritedAttribute & X)
19578 {
19579 isCastSubtree = X.isCastSubtree;
19580 physical_file_id = X.physical_file_id;
19581 }
19582 };
19583
19584// DQ (7/21/21): This code construction does not work with the GNU 4.9.x compilers.
19585// #if !( ( (__GNUC__ == 4) && (__GNUC_MINOR__ <= 9) ) || (__GNUC__ < 4))
19586#if (__GNUC__ > 4)
19587
19588 class SubtreeTraversal : public SgTopDownProcessing<InheritedAttribute>
19589 {
19590 public:
19591 InheritedAttribute evaluateInheritedAttribute ( SgNode* node, InheritedAttribute inheritedAttribute)
19592 {
19593 InheritedAttribute returnAttribute(inheritedAttribute);
19594
19595 SgCastExp* castExpression = isSgCastExp(node);
19596 if (castExpression != NULL)
19597 {
19598 returnAttribute.isCastSubtree = true;
19599 }
19600
19601 if (returnAttribute.isCastSubtree == true)
19602 {
19603 // Nothing to do, unless we want to fixup the physical node id.
19604#if 0
19605 printf ("In markSubtreeToBeUnparsedTreeTraversal(): subtree of a SgCastExp: node = %p = %s physical_file_id = %d \n",
19606 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19607#endif
19608 }
19609 else
19610 {
19611#if 0
19612 printf ("In markSubtreeToBeUnparsedTreeTraversal(): Calling markNodeToBeUnparsed(): node = %p = %s physical_file_id = %d \n",
19613 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19614#endif
19615 // This logic will cause the SgCastExp node to NOT be marked as a transformation (not just its children).
19616 markNodeToBeUnparsed(node,inheritedAttribute.physical_file_id);
19617 }
19618
19619 return returnAttribute;
19620 }
19621 };
19622
19623 InheritedAttribute inheritedAttribute(physical_file_id);
19624
19625 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19626 SubtreeTraversal traversal;
19627
19628#if 0
19629 printf ("\nIn markSubtreeToBeUnparsedTreeTraversal(): calling traverse \n");
19630#endif
19631
19632 traversal.traverse(root, inheritedAttribute);
19633#else
19634 printf ("This function does not compile with GNU 4.9 or older compilers (part of ROSE used only with more modern compilers) \n");
19635#endif
19636
19637 }
19638
19639
19640
19641
19643vector<SgDeclarationStatement*>
19644generateCopiesOfDependentDeclarations (const vector<SgDeclarationStatement*>& dependentDeclarations, SgScopeStatement* targetScope)
19645//generateCopiesOfDependentDeclarations ( SgStatement* stmt, SgScopeStatement* targetScope )
19646 {
19647 // Liao suggests adding the target scope to the parameter list so that the constructed function
19648 // built using SageBuilder::buildNondefiningFunctionDeclaration() can be built to be in the
19649 // correct scope as soon as possible.
19650
19651 // This function uses the getDependentDeclarations() function to get the dependent declarations
19652 // and then returns a list of copies of each of them.
19653
19654#if 0
19655 printf ("\n\n********************************************************** \n");
19656 printf (" Inside of generateCopiesOfDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19657 printf ("********************************************************** \n");
19658#endif
19659
19660 vector<SgDeclarationStatement*> copiesOfDependentDeclarations;
19661 // avoiding call getDependentDeclarations() twice
19662// vector<SgDeclarationStatement*> dependentDeclarations = getDependentDeclarations(stmt);
19663
19664#if 0
19665 printf ("Output the dependentDeclarations: dependentDeclarations.size() = %" PRIuPTR " \n",dependentDeclarations.size());
19666 outputDeclarationList(dependentDeclarations);
19667#endif
19668#if 0
19669 printf ("************************************************ \n");
19670 printf ("*** Make all copies of dependentDeclarations *** \n");
19671 printf ("************************************************ \n");
19672#endif
19673
19674 // Should have a valid scope, so that symbol tables can be expected to be setup.
19675 ROSE_ASSERT(targetScope != NULL);
19676
19677 // DQ (2/25/2009): Initially this is always global scope so test this for now, at least.
19678 ROSE_ASSERT(isSgGlobal(targetScope) != NULL);
19679
19680 for (vector<SgDeclarationStatement*>::const_iterator i = dependentDeclarations.begin(); i != dependentDeclarations.end(); i++)
19681 {
19682#if 0
19683 printf ("Copying declaration = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
19684#endif
19685 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19686
19687 SgNode* copy_node = NULL;
19688 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
19689
19690 // For function declarations we don't want to do deep copies on defining declarations
19691 // since that would violate the One-time Definition Rule (ODR).
19692 if (functionDeclaration != NULL)
19693 {
19694 // the target scope may already have a declaration for this function.
19695 // This happens since SageInterface::appendStatementWithDependentDeclaration() is called in the end of outlining
19696 // and the original enclosing class of the outlined target has been changed already (replaced target with a call to OUT_xxx())
19697 // Also, getDependentDeclarations() recursively searches for declarations within the dependent class and hits OUT_xxx()
19698 // Liao, 5/8/2009
19699
19700 if ( SgProject::get_verbose() >= 1 )
19701 printf ("WARNING: In SageInterface -- generateCopiesOfDependentDeclarations(): I think this is the wrong lookup symbol function that is being used here! \n");
19702
19703 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
19704 // TV (2/4/2014): can be found in the project wide global scope...
19705 // So I removed it as we only build a nondef decl and it will only happen for function declared in global scope.`
19706#endif
19707#if 0
19708 printf ("In generateCopiesOfDependentDeclarations(): Copy mechanism appied to SgFunctionDeclaration functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19709
19710 printf ("functionDeclaration = %p \n",functionDeclaration);
19711 printf ("functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
19712 printf ("functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19713 printf ("functionDeclaration->get_scope() = %p \n",functionDeclaration->get_scope());
19714 printf ("targetScope = %p \n",targetScope);
19715#endif
19716 SgFunctionDeclaration* copy_functionDeclaration = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,targetScope);
19717 assert(copy_functionDeclaration != NULL);
19718
19719 copy_functionDeclaration->set_parent(targetScope);
19720
19721 assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != NULL);
19722
19723 // DQ (11/8/2020): This can not be asserted now that the buildSourceFile() has the
19724 // feature of clearing the symbol table used across multiple files.
19725 // assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != copy_functionDeclaration);
19726
19727 assert(copy_functionDeclaration->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table() != NULL);
19728
19729 assert(copy_functionDeclaration->get_scope() != NULL);
19730 assert(copy_functionDeclaration->get_scope() == targetScope);
19731 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19732 copy_functionDeclaration->get_type()) != NULL);
19733 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19734 copy_functionDeclaration->get_type())->get_symbol_basis() == copy_functionDeclaration->get_firstNondefiningDeclaration());
19735
19736 copy_node = copy_functionDeclaration;
19737#if 0
19738 printf ("In generateCopiesOfDependentDeclarations(): DONE: Copy mechanism appied to SgFunctionDeclaration \n");
19739 ROSE_ABORT();
19740#endif
19741 }
19742 else
19743 {
19744 // We only copy the non-defining declaration of a defining typedef declaration
19745 // since its defining body will be treated as a separate declaration and inserted to the new file.
19746 // This is also a workaround for an AST copy bug: losing defining body of a defining typedef declaration after copying.
19747 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(*i);
19748 if (tdecl)
19749 {
19750#if 0
19751 if (tdecl->get_definingDeclaration() == tdecl)
19752 cout<<"Copying a defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19753 else
19754 cout<<"Copying a non-defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19755#endif
19757 SgTypedefDeclaration* tdecl_copy = isSgTypedefDeclaration(copy_node);
19758 tdecl_copy->set_typedefBaseTypeContainsDefiningDeclaration (false); // explicit indicate this does not contain defining base type, Liao 12/14/2012
19759 }
19760 else
19761 copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19762
19763 // 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).
19764 SgDeclarationStatement* copy_declaration = isSgDeclarationStatement(copy_node);
19765 ROSE_ASSERT(copy_declaration != NULL);
19766
19767 // DQ (3/2/2009): This will be done later, but it is set above, so set it in this branch to be consistant.
19768 if (copy_declaration->hasExplicitScope() == true)
19769 copy_declaration->set_scope(targetScope);
19770 }
19771
19772 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19773 // Build a function prototype, but what scope should be used?
19774 // ROSE_ASSERT(functionDeclaration->get_scope() != NULL);
19775 // copy = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,functionDeclaration->get_scope());
19776
19777#if 0
19778 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());
19779#endif
19780
19781 ROSE_ASSERT(copy_node != NULL);
19782 ROSE_ASSERT(copy_node->get_file_info() != NULL);
19783
19784 // Note that the root of the does not have its file info set like its children.
19785 copy_node->get_file_info()->setTransformation();
19787 // copy_node->get_file_info()->display("CollectDependentDeclarationsTraversal::visit()");
19788
19789 SgDeclarationStatement* copy_definingDeclaration = isSgDeclarationStatement(copy_node);
19790 ROSE_ASSERT(copy_definingDeclaration != NULL);
19791
19792 ROSE_ASSERT( *i != NULL );
19793 ROSE_ASSERT(copy_definingDeclaration != NULL);
19794
19795 // DQ (2/26/2009): get_scope() will require a valid parent for some cases (see moreTest4.cpp).
19796 if (copy_definingDeclaration->get_parent() == NULL)
19797 {
19798 copy_definingDeclaration->set_parent(targetScope);
19799 }
19800 ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19801
19802#if 0
19803 printf ("DONE: Copying declaration: original scope = %p copied to scope = %p \n",(*i)->get_scope(),copy_definingDeclaration->get_scope());
19804#endif
19805
19806 // DQ (2/22/2009): I think we need to set these explicitly (it will be reset later).
19807 copy_definingDeclaration->set_parent(NULL);
19808
19809 // Now that we pass in the scope explicitly we can set the scope (above), so don't reset to NULL!
19810 // copy_definingDeclaration->set_scope(NULL);
19811
19812 // DQ (2/20/2009): Added assertion.
19813 ROSE_ASSERT(copy_definingDeclaration->get_parent() == NULL);
19814
19815#if 0
19816 // DQ (2/20/2009): Added assertion.
19817 // ROSE_ASSERT(copy_definingDeclaration->get_definingDeclaration() != NULL);
19818 if (copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL)
19819 {
19820 printf ("copy_definingDeclaration = %p \n",copy_definingDeclaration);
19821 printf ("copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL \n");
19822 printf ("copy_definingDeclaration->get_definingDeclaration() = %p \n",copy_definingDeclaration->get_definingDeclaration());
19823 }
19824#endif
19825
19826 // DQ (2/21/2009): Commented out as a test.
19827 if ((*i)->get_firstNondefiningDeclaration() != NULL)
19828 {
19829 ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
19830 }
19831
19832 // DQ (2/20/2009): Added asertion.
19833 // ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19834
19835 copiesOfDependentDeclarations.push_back(copy_definingDeclaration);
19836 }
19837
19838#if 0
19839 printf ("****************************************************** \n");
19840 printf ("*** DONE: Make all copies of dependentDeclarations *** \n");
19841 printf ("****************************************************** \n");
19842 printf ("copiesOfDependentDeclarations.size() = %" PRIuPTR " \n",copiesOfDependentDeclarations.size());
19843#endif
19844
19845 // The mapping of copies to original declarations should be 1-to-1.
19846 // Liao, not true anymore for getDependentDeclarations() using recursion: a depending class's body is searched for dependents also.
19847 // 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
19848 ROSE_ASSERT(copiesOfDependentDeclarations.size() <= dependentDeclarations.size());
19849
19850 return copiesOfDependentDeclarations;
19851 }
19852
19853
19854bool
19855declarationContainsDependentDeclarations( SgDeclarationStatement* decl, vector<SgDeclarationStatement*> & dependentDeclarationList )
19856 {
19857 // DQ (2/16/2009): This function finds the declarations in "decl" and checks if they match against those in dependentDeclarationList
19858 bool returnValue = false;
19859
19860#if 0
19861 printf ("\n\n********************************************************** \n");
19862 printf (" Inside of declarationContainsDependentDeclarations(decl = %p = %s) \n",decl,decl->class_name().c_str());
19863 printf ("********************************************************** \n");
19864#endif
19865
19866 vector<SgDeclarationStatement*> locallyDependentDeclarationList = SageInterface::getDependentDeclarations(decl);
19867
19868 // printf ("In declarationContainsDependentDeclarations(): locallyDependentDeclarationList: \n");
19869 // outputPreprocessingInfoList(locallyDependentDeclarationList);
19870
19871 for (size_t i = 0; i < locallyDependentDeclarationList.size(); i++)
19872 {
19873 SgDeclarationStatement* d = locallyDependentDeclarationList[i];
19874#if 0
19875 printf ("locallyDependentDeclarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
19876#endif
19877 vector<SgDeclarationStatement*>::iterator j = find(dependentDeclarationList.begin(),dependentDeclarationList.end(),d);
19878 if (j != dependentDeclarationList.end())
19879 {
19880 // These identified declaration must be output as members of the class when it is output in the separate header file.
19881 // infact ODR may require that the whole class be output! Actually I think we don't have any chioce here!
19882#if 0
19883 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());
19884#endif
19885 returnValue = true;
19886 }
19887 }
19888
19889#if 0
19890 printf ("**************************************************************************** \n");
19891 printf (" LEAVING: Inside of declarationContainsDependentDeclarations(decl = %p = %s) returnValue = %s \n",decl,decl->class_name().c_str(),returnValue ? "true" : "false");
19892 printf ("**************************************************************************** \n");
19893#endif
19894
19895 return returnValue;
19896 }
19899{
19900 ROSE_ASSERT (new_exp != NULL);
19901 ROSE_ASSERT (anchor_exp != NULL);
19902 ROSE_ASSERT (new_exp != anchor_exp);
19903
19904 SgNode* parent = anchor_exp->get_parent();
19905 ROSE_ASSERT (parent != NULL);
19906
19907 //TODO use deep copy may be a better way, avoid reusing the original anchor_exp
19908 SgCommaOpExp * result = buildCommaOpExp(new_exp, NULL);
19909 ROSE_ASSERT (result != NULL);
19910 replaceExpression (anchor_exp, result, true);
19911
19912 result->set_rhs_operand(anchor_exp);
19913 anchor_exp->set_parent(result);
19914 return result ;
19915}
19916
19917
19919SgCommaOpExp * SageInterface::insertAfterUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp, SgStatement** temp_decl /* = NULL */, SgVarRefExp** temp_ref /* = NULL */)
19920{
19921 ROSE_ASSERT (new_exp != NULL);
19922 ROSE_ASSERT (anchor_exp != NULL);
19923 ROSE_ASSERT (new_exp != anchor_exp);
19924
19925 SgNode* parent = anchor_exp->get_parent();
19926 ROSE_ASSERT (parent != NULL);
19927
19928 // insert TYPE T1; right before the enclosing statement of anchor_exp
19929 SgType * t = anchor_exp ->get_type();
19930 ROSE_ASSERT (t != NULL);
19931 SgStatement * enclosing_stmt = getEnclosingStatement(anchor_exp);
19932 ROSE_ASSERT (enclosing_stmt != NULL);
19933
19934 gensym_counter ++;
19935 string temp_name = "_t_"+ StringUtility::numberToString(gensym_counter);
19936 SgVariableDeclaration* t_decl = buildVariableDeclaration(temp_name, t, NULL, enclosing_stmt->get_scope());
19937 insertStatementBefore (enclosing_stmt, t_decl);
19938 SgVariableSymbol * temp_sym = getFirstVarSym (t_decl);
19939 ROSE_ASSERT (temp_sym != NULL);
19940 if (temp_decl)
19941 *temp_decl = t_decl;
19942
19943 // build ((T1 = anchor_exp, new_exp),T1) )
19944 SgVarRefExp * first_ref = buildVarRefExp(temp_sym);
19945 if (temp_ref)
19946 * temp_ref = first_ref;
19947 SgCommaOpExp * result = buildCommaOpExp ( buildCommaOpExp (buildAssignOp ( first_ref, deepCopy(anchor_exp)), new_exp) , buildVarRefExp(temp_sym));
19948 replaceExpression (anchor_exp, result, false);
19949
19950 return result;
19951}
19952
19953void
19955 {
19956 // Put out a message in the separate file to lable the dependent CPP directives.
19957 // --- PreprocessingInfo(DirectiveType, const std::string & inputString, const std::string & filenameString, int line_no, int col_no, int nol, RelativePositionType relPos );
19958 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
19959 string fileName = "separate-outlined-file";
19960 PreprocessingInfo* messageToUser = new PreprocessingInfo(PreprocessingInfo::C_StyleComment,message,fileName,0,0,1,PreprocessingInfo::before);
19961 // requiredDirectivesList.push_back(messageToUser);
19962 stmt->addToAttachedPreprocessingInfo(messageToUser,PreprocessingInfo::before);
19963
19964 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
19965 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
19966 // when multiple files are used on the command line.
19967 messageToUser->get_file_info()->setTransformation();
19968 }
19969
19970
19971// DQ (2/6/2009): Added function to support outlining into separate file.
19972// 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)
19973void
19975 {
19976 // New function to support outlining of functions into separate files (with their required declarations).
19977
19978#if 0
19979 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl = %p \n",decl);
19980 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_parent() = %p \n",decl->get_parent());
19981 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_scope() = %p \n",decl->get_scope());
19982 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): original_statement = %p \n",original_statement);
19983 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (decl) = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
19984 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_firstNondefiningDeclaration() = %p \n",decl->get_firstNondefiningDeclaration());
19985 if (decl->get_firstNondefiningDeclaration() != NULL)
19986 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
19987 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_definingDeclaration() = %p \n",decl->get_definingDeclaration());
19988 if (decl->get_definingDeclaration() != NULL)
19989 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_definingDeclaration())->getFileName().c_str());
19990#endif
19991
19992#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
19993 // Make sure that the input declaration (decl" is consistent in it's representation across more
19994 // than one file (only a significant test when outlining to a separate file; which is what this
19995 // function supports).
19996 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
19997 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
19998 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
19999
20000 // DQ (2/6/2009): I need to write this function to support the
20001 // insertion of the function into the specified scope. If the
20002 // file associated with the scope is marked as compiler generated
20003 // (or as a transformation) then the declarations referenced in the
20004 // function must be copied as well (those not in include files)
20005 // and the include files must be copies also. If the SgFile
20006 // is not compiler generated (or a transformation) then we just
20007 // append the function to the scope (trivial case).
20008
20009 // This code will be based on the work in:
20010 // developersScratchSpace/Dan/translator_tests/reverseTraversal.C
20011
20012 // To test this run: "rm moreTest2.o ; make moreTest2.o"
20013 // in directory: tests/nonsmoke/functional/roseTests/astOutliningTests
20014
20015 // ***** Also move different loop IR nodes into a common base class *****
20016
20017 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20018
20019 // DQ (3/2/2009): This now calls a newer function which returns a list of declarations and a list of symbols.
20020 // The declarations are sometimes outer declarations of nested references to dependent declaration in inner
20021 // scopes (see moreTest3.cpp). The Symbol list are the symbols in the old AST that will be mapped to newer
20022 // symbols generated in the copied AST.
20023 // Collect the declaration that the input declaration depends upon.
20024 vector<SgDeclarationStatement*> dependentDeclarationList_inOriginalFile;
20025
20026 dependentDeclarationList_inOriginalFile = getDependentDeclarations(decl);
20027
20028 // Generate the copies of all the dependent statements
20029// printf ("Fixme: this currently causes the getDependentDeclarations(decl) function to be called twice \n");
20030// vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(decl,scope);
20031 vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(dependentDeclarationList_inOriginalFile,scope);
20032 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20033
20034 // Make sure that the input declaration (decl" is consistent in it's representation across more
20035 // than one file (only a significant test when outlining to a separate file; which is what this
20036 // function supports).
20037 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20038 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20039 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20040
20041 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
20042 std::map<SgNode*, SgNode*> replacementMap;
20043
20044 // DQ (3/2/2009): Now use the collectDependentDeclarationsCopyType object to generate the mapping
20045 // from the symbols in the old AST to the new symbols in the new AST (generated as part of the AST
20046 // copy mechanism).
20047 SgCopyHelp::copiedNodeMapType copyNodeMap = collectDependentDeclarationsCopyType.get_copiedNodeMap();
20048 SgCopyHelp::copiedNodeMapType::iterator copyNodeMapItrator = copyNodeMap.begin();
20049 while (copyNodeMapItrator != copyNodeMap.end())
20050 {
20051 // Loop over all the nodes generated in the AST copy mechanism (accumulated result over multiple copies).
20052 // const SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20053 // SgNode* first = copyNodeMapItrator->first;
20054 SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20055 SgNode* second = copyNodeMapItrator->second;
20056#if 0
20057 printf ("copyNodeMapItrator.first = %p = %s second = %p = %s \n",first,first->class_name().c_str(),second,second->class_name().c_str());
20058#endif
20059 // Add the SgGlobal referenece to the replacementMap
20060 if (isSgSymbol(first) != NULL)
20061 {
20062#if 0
20063 printf ("Adding to replacementMap (first = %p = %s = %s , second = %p \n",first,first->class_name().c_str(),SageInterface::get_name(first).c_str(),second);
20064#endif
20065 replacementMap.insert(pair<SgNode*,SgNode*>(first,second));
20066 }
20067
20068 copyNodeMapItrator++;
20069 }
20070
20071#if 0
20072 printf ("Exiting after test of new functionality \n");
20073 ROSE_ABORT();
20074#endif
20075
20076 // DQ (2/22/2009): We need all the declarations! (moreTest3.cpp demonstrates this, since it drops
20077 // the "#define SIMPLE 1" which causes it to be treated a "0" (causing errors in the generated code).
20078 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(original_statement);
20079 vector<PreprocessingInfo*> requiredDirectivesList = collectCppDirectives(sourceFile);
20080
20081 SgFunctionDeclaration* outlinedFunctionDeclaration = isSgFunctionDeclaration(decl);
20082 ROSE_ASSERT(outlinedFunctionDeclaration != NULL);
20083 SgGlobal* originalFileGlobalScope = TransformationSupport::getGlobalScope(original_statement);
20084 ROSE_ASSERT(originalFileGlobalScope != NULL);
20085 if ( SgProject::get_verbose() >= 1 )
20086 printf ("WARNING: In SageInterface::appendStatementWithDependentDeclaration(): I think this is the wrong lookup symbol function that is being used here! \n");
20087
20088 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
20089 // SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name()));
20090 SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name(),NULL,NULL));
20091
20092 // SgSymbol* outlinedFunctionSymbolFromOutlinedFile = scope->lookup_symbol(outlinedFunctionDeclaration->get_name());
20093 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20094 SgFunctionSymbol* outlinedFunctionSymbolFromOutlinedFile = isSgFunctionSymbol(decl->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table());
20095#if 0
20096 printf ("outlinedFunctionSymbolFromOriginalFile = %p outlinedFunctionSymbolFromOutlinedFile = %p \n",outlinedFunctionSymbolFromOriginalFile,outlinedFunctionSymbolFromOutlinedFile);
20097
20098 printf ("TransformationSupport::getSourceFile(decl)->getFileName() = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20099 printf ("TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName() = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20100 printf ("TransformationSupport::getSourceFile(original_statement)->getFileName() = %s \n",TransformationSupport::getSourceFile(original_statement)->getFileName().c_str());
20101#endif
20102
20103 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile != NULL);
20104 ROSE_ASSERT(outlinedFunctionSymbolFromOutlinedFile != NULL);
20105
20106 // TV (07/24/2013): Symbol are unified across files through the project wide global scope
20107 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile == outlinedFunctionSymbolFromOutlinedFile);
20108
20109 // Add the SgGlobal referenece to the replacementMap
20110 replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
20111
20112 // Add the non-defining declarations of the outlined function to the replacementMap
20113 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOriginalFile = isSgFunctionDeclaration(outlinedFunctionSymbolFromOriginalFile->get_declaration());
20114 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOutlinedFile = isSgFunctionDeclaration(decl->get_firstNondefiningDeclaration());
20115 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOriginalFile != NULL);
20116 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOutlinedFile != NULL);
20117 replacementMap.insert(pair<SgNode*,SgNode*>(outlinedNondefiningFunctionDeclarationFromOriginalFile,outlinedNondefiningFunctionDeclarationFromOutlinedFile));
20118
20119
20120 // list<SgDeclarationStatement>::iterator i = declarationList.begin();
20121 // while (i != declarationList.end())
20122 // for (list<SgDeclarationStatement>::iterator i = declarationList.begin(); i != declarationList.end(); i++)
20123
20124// cout<<"\n*******************************************\n"<<endl;
20125// cout<<"Inserting dependent decls: count="<<dependentDeclarationList.size()<<endl;
20126 for (size_t i = 0; i < dependentDeclarationList.size(); i++)
20127 {
20128 SgDeclarationStatement* d = dependentDeclarationList[i]; // copies of dependent declarations
20129#if 0
20130 SgDeclarationStatement* originalDeclaration = dependentDeclarationList_inOriginalFile[i];
20131 printf ("declarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20132 printf ("originalDeclaration = %p \n",originalDeclaration);
20133
20134 d->get_file_info()->display("SageInterface::appendStatementWithDependentDeclaration()");
20135#endif
20136
20137 // DQ (2/20/2009): Added assertion.
20138 ROSE_ASSERT(d->get_parent() == NULL);
20139
20140 // scope->append_declaration(d);
20141 // scope->insert_statement (decl, d, /* bool inFront= */ true);
20142 ROSE_ASSERT(decl->get_scope() == scope);
20143 ROSE_ASSERT(find(scope->getDeclarationList().begin(),scope->getDeclarationList().end(),decl) != scope->getDeclarationList().end());
20144 scope->insert_statement (decl, d, /* bool inFront= */ true);
20145 d->set_parent (scope);
20146
20147#if 0
20148 printf ("Add the required symbol information to the symbol table: scope = %p = %s \n",scope,scope->class_name().c_str());
20149#endif
20150
20151 // For whatever type of declaration we add to the global scope in the new separate
20152 // file we have to add the required symbol information to the symbol table.
20153 switch(d->variantT())
20154 {
20155 case V_SgClassDeclaration:
20156 {
20157 if ( declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20158 printf ("Warning: This class contains dependent declarations (not implemented) \n");
20159 break;
20160 }
20161
20162 case V_SgMemberFunctionDeclaration:
20163 printf ("Sorry, support for dependent member function declarations not implemented! \n");
20164 ROSE_ABORT();
20165
20166 case V_SgTemplateInstantiationDecl:
20167 printf ("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration \n");
20168 d->get_file_info()->display("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration");
20169
20170 printf ("Case of SgTemplateInstantiationDecl not implemented. \n");
20171 ROSE_ABORT();
20172
20173 case V_SgNamespaceDeclarationStatement:
20174 if (declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20175 printf ("Warning: This namespace contains dependent declarations (not supported) \n");
20176 break;
20177
20178 case V_SgFunctionDeclaration:
20179 case V_SgTypedefDeclaration:
20180 case V_SgEnumDeclaration:
20181 break;
20182
20183 default:
20184 printf ("default case in SageInterface::appendStatementWithDependentDeclaration() (handling dependentDeclarationList) d = %p = %s \n",d,d->class_name().c_str());
20185 ROSE_ABORT();
20186 }
20187
20188
20189 // Collect include directives that are already attached to this dependent declaration.
20190 vector<PreprocessingInfo*> cppDirectivesAlreadyAttachedToDependentDeclarations = collectCppDirectives(d);
20191
20192#if 0
20193 printf ("directives BEFORE excluding those already present in dependent declarations \n");
20194 outputPreprocessingInfoList(requiredDirectivesList);
20195
20196 printf ("directives already attached to dependent declarations \n");
20197 outputPreprocessingInfoList(cppDirectivesAlreadyAttachedToDependentDeclarations);
20198#endif
20199
20200 // Remove these include directives from the requiredDirectivesList (to prevent redundant output in the generated file)
20201 vector<PreprocessingInfo*>::iterator j = cppDirectivesAlreadyAttachedToDependentDeclarations.begin();
20202 while ( j != cppDirectivesAlreadyAttachedToDependentDeclarations.end() )
20203 {
20204 // Remove this directive from the requiredDirectivesList (to avoid having them output redundently).
20205 vector<PreprocessingInfo*>::iterator entry = find(requiredDirectivesList.begin(),requiredDirectivesList.end(),*j);
20206 ROSE_ASSERT(entry != requiredDirectivesList.end());
20207
20208 requiredDirectivesList.erase(entry);
20209
20210 j++;
20211 }
20212
20213#if 0
20214 printf ("directives AFTER excluding those already present in dependent declarations \n");
20215 outputPreprocessingInfoList(requiredDirectivesList);
20216#endif
20217 }
20218
20219 // Add a message to the top of the outlined function that has been added
20220 addMessageStatement(decl,"/* OUTLINED FUNCTION */");
20221
20222 // Insert the dependent declarations ahead of the input "decl".
20223 SgStatement* firstStatmentInFile = NULL;
20224 if (dependentDeclarationList.empty() == true)
20225 {
20226 firstStatmentInFile = decl;
20227 }
20228 else
20229 {
20230 firstStatmentInFile = dependentDeclarationList[0];
20231 }
20232
20233 ROSE_ASSERT(firstStatmentInFile != NULL);
20234
20235 // Add a message to the top of the dependent declarations that have been added
20236 addMessageStatement(firstStatmentInFile,"/* REQUIRED DEPENDENT DECLARATIONS */");
20237
20238 // DQ (3/6/2009): Added support to permit exclusion of "#include<header.h>" files since they can make it
20239 // much more difficult for external tools. Later we will check if there are remaining unsatisfied dependent
20240 // declarations (which must be in the header file) so we can automate this step.
20241 if (excludeHeaderFiles == false)
20242 {
20243 // Include all the "#include<header.h>" cpp directives obtained from the original file.
20244 vector<PreprocessingInfo*>::reverse_iterator j = requiredDirectivesList.rbegin();
20245 while ( j != requiredDirectivesList.rend() )
20246 {
20247 firstStatmentInFile->addToAttachedPreprocessingInfo(*j,PreprocessingInfo::before);
20248 j++;
20249 }
20250 }
20251
20252 // Add a message to the top of the CPP directives that have been added
20253 addMessageStatement(firstStatmentInFile,"/* REQUIRED CPP DIRECTIVES */");
20254
20255 // ****************************************************************************
20256 // **************** Fixup AST to Reset References To IR nodes ***************
20257 // ****************************************************************************
20258 // This traversal of the replacement map modified the AST to reset pointers to subtrees that will be shared.
20259 // The whole AST is traversed (using the memory pool traversal) and the data member pointers to IR nodes that
20260 // are found in the replacement map are used to lookup the replacement values that are used to reset the
20261 // pointers in the AST. As the replacement is computed the pointer values that are marked in the replacement
20262 // list for update are added to the intermediateDeleteSet.
20263
20264 SgSourceFile* outlinedFile = TransformationSupport::getSourceFile(scope);
20265 ROSE_ASSERT(outlinedFile != NULL);
20266
20267 // This replacement will be done over the entire file (parts of it are redundant with what has already
20268 // been done by the AST copy (so this step need not do as much and may be reduced to just operating
20269 // on the outlined function, I think).
20270#if 0
20271 printf ("\n\n************************************************************\n");
20272 printf ("Calling Utils::edgePointerReplacement() \n");
20273#endif
20274
20275 Rose::AST::Utility::edgePointerReplacement(outlinedFile,replacementMap);
20276
20277#if 0
20278 printf ("Calling Utils::edgePointerReplacement(): DONE \n");
20279 printf ("************************************************************\n\n");
20280
20281 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
20282 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
20283#endif
20284
20285 // Repeated test from above
20286 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20287
20288// endif for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20289#endif
20290
20291#if 0
20292 // The replacementMap should include the symbols associated with the dependentDeclarationList
20293 // and the outlined function (so dependentDeclarationList.size() + 1).
20294 printf ("replacementMap.size() = %" PRIuPTR " dependentDeclarationList.size() = %" PRIuPTR " \n",replacementMap.size(),dependentDeclarationList.size());
20295 // ROSE_ASSERT(replacementMap.size() == dependentDeclarationList.size() + 1);
20296#endif
20297 }
20298
20299void
20301 {
20302//Tan, August/25/2010: //Re-implement DeleteAST function
20303
20304 //Use MemoryPoolTraversal to count the number of references to a certain symbol
20305 //This class defines the visitors for the MemoryPoolTraversal
20306
20307 class ClassicVisitor : public ROSE_VisitorPattern
20308 {
20309 private:
20310 int SgVariableSymbol_count;
20311 int SgFunctionSymbol_count;
20312 int SgClassDeclaration_count;
20313 int SgTypedefSymbol_count;
20314 int SgMemFuncSymbol_count;
20315 int SgTemplateSymbol_count;
20316 int SgEnumFieldSymbol_count;
20317
20318 SgVariableSymbol* SgVariableSymbolPtr;
20319 SgFunctionSymbol* SgFunctionSymbolPtr;
20320 SgClassSymbol * SgClassSymbolPtr;
20321 SgTypedefSymbol * SgTypedefPtr;
20322 SgEnumFieldSymbol * SgEnumFieldSymbolPtr;
20323 SgMemberFunctionSymbol * SgMemFuncSymbolPtr;
20324 SgTemplateSymbol * SgTemplateSymbolPtr;
20325 SgClassDeclaration * class_defining;
20326 SgTemplateDeclaration * template_defining;
20328 SgTypedefDeclaration * typedef_defining;
20329 SgFunctionDeclaration * function_decl;
20330 SgTemplateInstantiationDecl * templateInstantiate_defining;
20331
20332 public:
20333 ClassicVisitor(SgVariableSymbol* symbol){
20334 SgVariableSymbol_count = 0;
20335 SgVariableSymbolPtr = symbol;
20336 SgFunctionSymbolPtr =NULL;
20337 SgClassSymbolPtr =NULL;
20338 SgTypedefPtr = NULL;
20339 SgMemFuncSymbolPtr =NULL;
20340 class_defining = NULL;
20341 memFunc =NULL;
20342 typedef_defining =NULL;
20343 function_decl = NULL;
20344 SgTemplateSymbolPtr = NULL;
20345 template_defining = NULL;
20346 SgEnumFieldSymbolPtr = NULL;
20347 templateInstantiate_defining =NULL;
20348 }
20349
20350 ClassicVisitor(SgFunctionSymbol* symbol){
20351 SgFunctionSymbol_count = 0;
20352 SgFunctionSymbolPtr = symbol;
20353
20354 // DQ (5/2/2013): Added to fix test2013_141.C.
20355 SgMemFuncSymbol_count =0;
20356
20357 SgVariableSymbolPtr = NULL;
20358 SgClassSymbolPtr =NULL;
20359 SgTypedefPtr = NULL;
20360 SgMemFuncSymbolPtr =NULL;
20361 class_defining = NULL;
20362 memFunc =NULL;
20363 typedef_defining =NULL;
20364 function_decl = NULL;
20365 SgTemplateSymbolPtr = NULL;
20366 template_defining = NULL;
20367 SgEnumFieldSymbolPtr = NULL;
20368 templateInstantiate_defining =NULL;
20369 }
20370
20371 ClassicVisitor(SgClassSymbol* symbol){
20372 SgClassDeclaration_count = 0;
20373 SgClassSymbolPtr = symbol;
20374 SgFunctionSymbolPtr = NULL;
20375 SgVariableSymbolPtr = NULL;
20376 SgTypedefPtr = NULL;
20377 SgMemFuncSymbolPtr =NULL;
20378 class_defining = NULL;
20379 memFunc =NULL;
20380 typedef_defining =NULL;
20381 function_decl = NULL;
20382 SgTemplateSymbolPtr = NULL;
20383 template_defining = NULL;
20384 SgEnumFieldSymbolPtr = NULL;
20385 templateInstantiate_defining =NULL;
20386 }
20387
20388 ClassicVisitor(SgTypedefSymbol* symbol){
20389 SgTypedefSymbol_count =0;
20390 SgTypedefPtr = symbol;
20391 SgClassSymbolPtr = NULL;
20392 SgFunctionSymbolPtr = NULL;
20393 SgVariableSymbolPtr = NULL;
20394 SgMemFuncSymbolPtr =NULL;
20395 class_defining = NULL;
20396 memFunc =NULL;
20397 typedef_defining =NULL;
20398 function_decl = NULL;
20399 SgTemplateSymbolPtr = NULL;
20400 template_defining = NULL;
20401 SgEnumFieldSymbolPtr = NULL;
20402 templateInstantiate_defining =NULL;
20403 }
20404
20405 ClassicVisitor(SgMemberFunctionSymbol* symbol){
20406 SgMemFuncSymbolPtr = symbol;
20407 SgMemFuncSymbol_count =0;
20408 SgTypedefPtr = NULL;
20409 SgClassSymbolPtr = NULL;
20410 SgFunctionSymbolPtr = NULL;
20411 SgVariableSymbolPtr = NULL;
20412 class_defining = NULL;
20413 memFunc =NULL;
20414 typedef_defining =NULL;
20415 function_decl = NULL;
20416 SgTemplateSymbolPtr = NULL;
20417 template_defining = NULL;
20418 SgEnumFieldSymbolPtr = NULL;
20419 templateInstantiate_defining =NULL;
20420 }
20421
20422 ClassicVisitor(SgTemplateSymbol* symbol){
20423 SgTemplateSymbolPtr = symbol;
20424 SgTemplateSymbol_count =0;
20425 SgMemFuncSymbolPtr = NULL;
20426 SgTypedefPtr = NULL;
20427 SgClassSymbolPtr = NULL;
20428 SgFunctionSymbolPtr = NULL;
20429 SgVariableSymbolPtr = NULL;
20430 class_defining = NULL;
20431 memFunc =NULL;
20432 typedef_defining =NULL;
20433 function_decl = NULL;
20434 template_defining = NULL;
20435 SgEnumFieldSymbolPtr = NULL;
20436 templateInstantiate_defining =NULL;
20437 }
20438
20439 ClassicVisitor(SgEnumFieldSymbol* symbol){
20440 SgEnumFieldSymbolPtr = symbol;
20441 SgEnumFieldSymbol_count =0;
20442 SgTemplateSymbolPtr = NULL;
20443 SgMemFuncSymbolPtr = NULL;
20444 SgTypedefPtr = NULL;
20445 SgClassSymbolPtr = NULL;
20446 SgFunctionSymbolPtr = NULL;
20447 SgVariableSymbolPtr = NULL;
20448 class_defining = NULL;
20449 memFunc =NULL;
20450 typedef_defining =NULL;
20451 function_decl = NULL;
20452 template_defining = NULL;
20453 templateInstantiate_defining =NULL;
20454 }
20455
20456
20457 ClassicVisitor(SgClassDeclaration* node){
20458 class_defining = node;
20459 SgMemFuncSymbolPtr = NULL;
20460 SgTypedefPtr = NULL;
20461 SgClassSymbolPtr = NULL;
20462 SgFunctionSymbolPtr = NULL;
20463 SgVariableSymbolPtr = NULL;
20464 memFunc =NULL;
20465 typedef_defining =NULL;
20466 function_decl = NULL;
20467 SgTemplateSymbolPtr = NULL;
20468 template_defining = NULL;
20469 SgEnumFieldSymbolPtr = NULL;
20470 templateInstantiate_defining =NULL;
20471 }
20472
20473 ClassicVisitor(SgTemplateDeclaration* node){
20474 template_defining = node;
20475 class_defining = NULL;
20476 SgMemFuncSymbolPtr = NULL;
20477 SgTypedefPtr = NULL;
20478 SgClassSymbolPtr = NULL;
20479 SgFunctionSymbolPtr = NULL;
20480 SgVariableSymbolPtr = NULL;
20481 memFunc =NULL;
20482 typedef_defining =NULL;
20483 function_decl = NULL;
20484 SgTemplateSymbolPtr = NULL;
20485 SgEnumFieldSymbolPtr = NULL;
20486 templateInstantiate_defining =NULL;
20487 }
20488 ClassicVisitor(SgFunctionDeclaration* node){
20489 function_decl =node;
20490 class_defining = NULL;
20491 SgMemFuncSymbolPtr = NULL;
20492 SgTypedefPtr = NULL;
20493 SgClassSymbolPtr = NULL;
20494 SgFunctionSymbolPtr = NULL;
20495 SgVariableSymbolPtr = NULL;
20496 memFunc =NULL;
20497 typedef_defining =NULL;
20498 SgTemplateSymbolPtr = NULL;
20499 template_defining = NULL;
20500 SgEnumFieldSymbolPtr = NULL;
20501 templateInstantiate_defining =NULL;
20502 }
20503
20504 ClassicVisitor(SgMemberFunctionDeclaration* node){
20505 memFunc = node;
20506 function_decl =NULL;
20507 class_defining = NULL;
20508 SgMemFuncSymbolPtr = NULL;
20509 SgTypedefPtr = NULL;
20510 SgClassSymbolPtr = NULL;
20511 SgFunctionSymbolPtr = NULL;
20512 SgVariableSymbolPtr = NULL;
20513 typedef_defining =NULL;
20514 SgTemplateSymbolPtr = NULL;
20515 template_defining = NULL;
20516 SgEnumFieldSymbolPtr = NULL;
20517 templateInstantiate_defining =NULL;
20518 }
20519
20520 ClassicVisitor(SgTypedefDeclaration* node){
20521 typedef_defining = node;
20522 memFunc = NULL;
20523 function_decl =NULL;
20524 class_defining = NULL;
20525 SgMemFuncSymbolPtr = NULL;
20526 SgTypedefPtr = NULL;
20527 SgClassSymbolPtr = NULL;
20528 SgFunctionSymbolPtr = NULL;
20529 SgVariableSymbolPtr = NULL;
20530 SgTemplateSymbolPtr = NULL;
20531 template_defining = NULL;
20532 SgEnumFieldSymbolPtr = NULL;
20533 templateInstantiate_defining =NULL;
20534 }
20535
20536 ClassicVisitor(SgTemplateInstantiationDecl* node){
20537 templateInstantiate_defining =node;
20538 typedef_defining = NULL;
20539 memFunc = NULL;
20540 function_decl =NULL;
20541 class_defining = NULL;
20542 SgMemFuncSymbolPtr = NULL;
20543 SgTypedefPtr = NULL;
20544 SgClassSymbolPtr = NULL;
20545 SgFunctionSymbolPtr = NULL;
20546 SgVariableSymbolPtr = NULL;
20547 SgTemplateSymbolPtr = NULL;
20548 template_defining = NULL;
20549 SgEnumFieldSymbolPtr = NULL;
20550 }
20551
20552
20553 // SgVariableSymbol and SgEnumFieldSymbol
20554 void visit(SgInitializedName* node)
20555 {
20556 if(SgVariableSymbolPtr !=NULL)
20557 {
20558 if(node->get_scope()!=NULL)
20559 {
20560 // DQ (5/21/2013): We want to restrict access to the symbol table.
20561 if(node->get_scope()->get_symbol_table()!=NULL)
20562 {
20564 if (isSgVariableSymbol(s) == SgVariableSymbolPtr) SgVariableSymbol_count++;
20565 }
20566 }
20567 }
20568
20569 if(SgEnumFieldSymbolPtr !=NULL)
20570 {
20571 if(node->get_scope()!=NULL)
20572 {
20573 // DQ (5/21/2013): We want to restrict access to the symbol table.
20574 if(node->get_scope()->get_symbol_table()!=NULL)
20575 {
20577 if (isSgEnumFieldSymbol(s) == SgEnumFieldSymbolPtr) SgEnumFieldSymbol_count++;
20578 }
20579 }
20580 }
20581 }
20582
20583 void visit(SgVarRefExp* node)
20584 {
20585 if(SgVariableSymbolPtr !=NULL){
20586 SgVariableSymbol* s = node->get_symbol();
20587 if (s == SgVariableSymbolPtr) SgVariableSymbol_count++;
20588 }
20589 }
20590
20591 int get_num_variable_pointers(){return SgVariableSymbol_count;}
20592
20593 int get_num_EnumField_pointers(){return SgEnumFieldSymbol_count;}
20594
20595
20596 // SgFunctionSymbol
20597 void visit(SgFunctionDeclaration* node) {
20598 if(SgFunctionSymbolPtr !=NULL){
20599 if(node->get_scope()!=NULL){
20600 // DQ (5/21/2013): We want to restrict access to the symbol table.
20601 if(node->get_scope()->get_symbol_table()!=NULL)
20602 {
20604 if ((SgFunctionSymbol *)s == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20605 }
20606 }
20607 }
20608#if 0
20609 if(function_decl!=NULL){
20610 if(node->get_symbol_from_symbol_table() == NULL){
20613 if(node!=function_decl && (define==function_decl || first_nondefine==function_decl)) delete node;
20614 }
20615 }
20616#endif
20617 }
20618
20619 void visit(SgFunctionRefExp* node)
20620 {
20621#if 0
20622 printf ("In visit(SgFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20623#endif
20624 if (SgFunctionSymbolPtr !=NULL)
20625 {
20626 SgFunctionSymbol* s = node->get_symbol_i();
20627 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20628 {
20629 SgFunctionSymbol_count++;
20630#if 0
20631 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20632#endif
20633 }
20634 }
20635 }
20636
20637 // DQ (5/2/2013): Added support for SgMemberFunctionRefExp which is not derived from SgFunctionRefExp.
20638 void visit(SgMemberFunctionRefExp* node)
20639 {
20640#if 0
20641 printf ("In visit(SgMemberFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20642#endif
20643 if (SgFunctionSymbolPtr !=NULL)
20644 {
20645 SgFunctionSymbol* s = node->get_symbol_i();
20646 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20647 {
20648 SgFunctionSymbol_count++;
20649#if 0
20650 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20651#endif
20652 }
20653 }
20654 }
20655
20656 void visit(SgUserDefinedBinaryOp* node)
20657 {
20658 if (SgFunctionSymbolPtr !=NULL){
20659 SgFunctionSymbol* s = node->get_symbol();
20660 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20661 }
20662 }
20663
20664 int get_num_Function_pointers(){return SgFunctionSymbol_count;}
20665
20666 // SgClassSymbol
20667 void visit(SgClassDeclaration* node)
20668 {
20669 if(SgClassSymbolPtr !=NULL){
20670 if(node->get_scope()!=NULL){
20671 if(node->get_scope()->get_symbol_table()!=NULL)
20672 {
20674 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20675 }
20676 }
20677 }
20678
20679 if(class_defining!=NULL) {
20680 if(node->get_symbol_from_symbol_table() == NULL){
20683 if((class_decl==class_defining||class_decl1==class_defining) && node!=class_defining )
20684 delete node;
20685 }
20686 }
20687 }
20688
20689 void visit(SgTemplateInstantiationDecl* node)
20690 {
20691 if(SgClassSymbolPtr !=NULL){
20692 if(node->get_scope()!=NULL){
20693 if(node->get_scope()->get_symbol_table()!=NULL)
20694 {
20696 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20697 }
20698 }
20699 }
20700
20701 if(templateInstantiate_defining!=NULL) {
20702 if(node->get_scope()!=NULL){
20703 if(node->get_scope()->get_symbol_table()!=NULL)
20704 {
20705 if(node->get_symbol_from_symbol_table() == NULL){
20708 if((template_decl==templateInstantiate_defining||template_decl1==templateInstantiate_defining) && node!=templateInstantiate_defining){
20709 /*vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
20710 foreach (SgTemplateArgument* element, tempargs){
20711 SgTemplateArgument* temparg = isSgTemplateArgument(element);
20712 if(temparg){
20713 delete temparg;
20714 }
20715 printf("SgTemplateArg in Memory Pool traversal\n");
20716 }*/
20717 delete node;
20718 //printf("SgTemplateInstantiationDecl in Memory Pool traversal\n");
20719 }
20720 }
20721 }
20722 }
20723 }
20724 }
20725
20726 void visit(SgThisExp* node)
20727 {
20728 if (SgClassSymbolPtr !=NULL){
20729 SgSymbol* s = node->get_class_symbol();
20730 if (s == SgClassSymbolPtr) SgClassDeclaration_count++;
20731 }
20732 }
20733
20734 void visit(SgClassNameRefExp* node)
20735 {
20736 if (SgClassSymbolPtr !=NULL){
20737 SgSymbol* s = node->get_symbol();
20738 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20739 }
20740 }
20741
20742
20743 int get_num_Class_pointers(){return SgClassDeclaration_count;}
20744
20745
20746 // SgMemberFunctionSymbol
20747 void visit(SgCtorInitializerList* node)
20748 {
20749 if(memFunc !=NULL){
20751 if(func == memFunc){
20752 delete node;
20753 }
20754 }
20755 }
20756
20757
20758 void visit(SgMemberFunctionDeclaration* node)
20759 {
20760 if (SgMemFuncSymbolPtr !=NULL){
20761 if(node->get_scope()!=NULL){
20762 if(node->get_scope()->get_symbol_table()!=NULL)
20763 {
20764 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20765 if(symbol == SgMemFuncSymbolPtr){
20766 SgMemFuncSymbol_count++;
20767 }
20768 }
20769 }
20770 }
20771 }
20772
20774 {
20775 if (SgMemFuncSymbolPtr !=NULL){
20776 if(node->get_scope()!=NULL){
20777 if(node->get_scope()->get_symbol_table()!=NULL)
20778 {
20779 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
20780 if(symbol == SgMemFuncSymbolPtr){
20781 SgMemFuncSymbol_count++;
20782 }
20783 }
20784 }
20785 }
20786 }
20787
20788
20789
20790 int get_num_memFunc_pointers(){return SgMemFuncSymbol_count;}
20791
20792
20793 // SgTypedefSymbol
20794 void visit(SgTypedefDeclaration* node)
20795 {
20796 if(SgTypedefPtr!=NULL){
20797 if(node->get_scope()!=NULL){
20798 if(node->get_scope()->get_symbol_table()!=NULL)
20799 {
20801 if ((SgTypedefSymbol *)s == SgTypedefPtr) SgTypedefSymbol_count++;
20802 }
20803 }
20804 }
20805 if(typedef_defining!=NULL){
20807 if(typedef_define == typedef_defining && node != typedef_defining ) {
20808 delete node;
20809 }
20810 }
20811 }
20812
20813 int get_num_Typedef_pointers(){return SgTypedefSymbol_count;}
20814
20815
20816
20817 void visit(SgTemplateDeclaration* node)
20818 {
20819 if (SgTemplateSymbolPtr !=NULL){
20820 if(node->get_scope()!=NULL){
20821 if(node->get_scope()->get_symbol_table()!=NULL)
20822 {
20823 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
20824 if(symbol == SgTemplateSymbolPtr){
20825 SgTemplateSymbol_count++;
20826 }
20827 }
20828 }
20829 }
20830
20831 if(template_defining !=NULL) {
20832 if(node->get_scope()!=NULL){
20833 if(node->get_scope()->get_symbol_table()!=NULL)
20834 {
20835 if(node->get_symbol_from_symbol_table() == NULL){
20838 if((template_decl==template_defining||template_decl1==template_defining) && node!=template_defining) {
20839 delete node;
20840
20841 }
20842 }
20843 }
20844 }
20845 }
20846 }
20847
20848 int get_num_Template_pointers(){return SgTemplateSymbol_count;}
20849
20850 };
20851
20852
20853 //Tan August,25,2010 //Traverse AST in post order, delete nodes and their symbols if it's safe to do so
20854 class DeleteAST : public SgSimpleProcessing, ROSE_VisitTraversal
20855 {
20856 public:
20857
20858 void visit (SgNode* node)
20859 {
20860 //These nodes are manually deleted because they cannot be visited by the traversal
20862 //remove SgVariableDefinition, SgVariableSymbol and SgEnumFieldSymbol
20864#if 0
20865 printf ("In DeleteAST::visit(): node = %p = %s \n",node,node->class_name().c_str());
20866#endif
20867#if 0
20868 // DQ (3/2/2014): I think this might be a problem...
20869 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
20870 if (isSgScopeStatement(node) !=NULL)
20871 {
20872 SgScopeStatement* scope = isSgScopeStatement(node);
20873#if 1
20874 printf ("Deleting the scopes type table: scope->get_type_table() = %p \n",scope->get_type_table());
20875#endif
20876 delete scope->get_type_table();
20877 }
20878#endif
20879#if 0
20880 // DQ (3/2/2014): I think this might be a problem...
20881 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
20882 if (isSgTypeTable(node) !=NULL)
20883 {
20884 SgTypeTable* typeTable = isSgTypeTable(node);
20885#if 1
20886 printf ("Deleting the type table (SgSymbolTable): typeTable->get_type_table() = %p \n",typeTable->get_type_table());
20887#endif
20888 delete typeTable->get_type_table();
20889 }
20890#endif
20891 if(isSgInitializedName(node) !=NULL){
20892 //remove SgVariableDefinition
20893 SgDeclarationStatement* var_def;
20894 var_def = ((SgInitializedName *)node)->get_definition();
20895 if(isSgVariableDefinition(var_def) !=NULL){
20896 delete var_def;
20897 //printf("A SgVariableDefinition was deleted\n");
20898 }
20899
20900
20901 //remove SgVariableSymbol
20902 if(isSgInitializedName(node)->get_scope()!=NULL){
20903 if(isSgInitializedName(node)->get_scope()->get_symbol_table()!=NULL)
20904 {
20905 SgSymbol* symbol = ((SgInitializedName *)node)->get_symbol_from_symbol_table();
20906 if(isSgVariableSymbol(symbol) !=NULL){
20907 ClassicVisitor visitor((SgVariableSymbol*)symbol);
20908 traverseMemoryPoolVisitorPattern(visitor);
20909 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20910 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20911 delete symbol;
20912 //printf("A SgVariableSymbol was deleted\n");
20913 }
20914 }
20915
20916 if(isSgEnumFieldSymbol(symbol) !=NULL){
20917 ClassicVisitor visitor((SgEnumFieldSymbol*)symbol);
20918 traverseMemoryPoolVisitorPattern(visitor);
20919 if(visitor.get_num_EnumField_pointers()==1){
20920 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20921 delete symbol;
20922 //printf("A SgEnumFieldSymbol was deleted\n");
20923 }
20924 }
20925
20926 }
20927 }
20928 }
20929
20930 if(isSgVarRefExp(node) !=NULL){
20931 SgVariableSymbol *symbol = ((SgVarRefExp*)node)->get_symbol();
20932 ClassicVisitor visitor(symbol);
20933 traverseMemoryPoolVisitorPattern(visitor);
20934 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20935 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20936 delete symbol;
20937 //printf("A SgVariableSymbol was deleted\n");
20938 }
20939 }
20940
20941 /*////////////////////////////////////////////////
20942 /remove SgFunctionSymbol
20944
20945 {
20946 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(node);
20947 if (funcDecl != NULL){
20948 if (isSgMemberFunctionDeclaration(node) == NULL) {
20949 if (funcDecl->get_scope() != NULL) {
20950 if (funcDecl->get_scope()->get_symbol_table() != NULL) {
20951 SgSymbol* symbol = ((SgFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20952 ClassicVisitor visitor((SgFunctionSymbol *)symbol);
20953 traverseMemoryPoolVisitorPattern(visitor);
20954 if (visitor.get_num_Function_pointers()==1) { //only one reference to this FunctionSymbol => safe to delete
20955 ((SgFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
20956 delete symbol;
20957 //printf("A SgFunctionSymbol was deleted\n");
20958 }
20959 ClassicVisitor visitor1((SgFunctionDeclaration *)node);
20960 traverseMemoryPoolVisitorPattern(visitor1);
20961 }
20962 }
20963 }
20964 }
20965 }
20966
20967 if(isSgFunctionRefExp(node) !=NULL)
20968 {
20969#if 0
20970 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(node);
20971 ROSE_ASSERT(functionRefExp->get_symbol_i() != NULL);
20972 printf ("In DeleteAST::visit(): functionRefExp->get_symbol_i() = %p = %s \n",functionRefExp->get_symbol_i(),functionRefExp->get_symbol_i()->class_name().c_str());
20973#endif
20974 SgFunctionSymbol *symbol = ((SgFunctionRefExp*)node)->get_symbol_i();
20975 ClassicVisitor visitor(symbol);
20976 traverseMemoryPoolVisitorPattern(visitor);
20977 if(visitor.get_num_Function_pointers()==1)
20978 {
20979 // only one reference to this FunctionSymbol => safe to delete
20980 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20981 delete symbol;
20982 //printf("A SgFunctionSymbol was deleted\n");
20983 }
20984
20985 }
20986
20987 if(isSgUserDefinedBinaryOp(node) !=NULL){
20988 SgFunctionSymbol *symbol = ((SgUserDefinedBinaryOp*)node)->get_symbol();
20989 ClassicVisitor visitor(symbol);
20990 traverseMemoryPoolVisitorPattern(visitor);
20991 if(visitor.get_num_Function_pointers()==1){ //only one reference to this FunctionSymbol => safe to delete
20992 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20993 delete symbol;
20994 //printf("A SgFunctionSymbol was deleted\n");
20995 }
20996 }
20997
20998 /*/
20999 /remove SgTypedefSymbol
21001
21002 if(isSgTypedefDeclaration(node) !=NULL){
21003 if(((SgTypedefDeclaration*)node)->get_scope()!=NULL){
21004 if(((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21005 {
21006 SgSymbol* symbol = ((SgTypedefDeclaration*)node)->get_symbol_from_symbol_table();
21007 if(isSgTypedefSymbol(symbol)){
21008 ClassicVisitor visitor((SgTypedefSymbol*) symbol);
21009 traverseMemoryPoolVisitorPattern(visitor);
21010 if(visitor.get_num_Typedef_pointers()==1){ //only one reference to this SgTypedefSymbol => safe to delete
21011 ((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21012 delete symbol;
21013 //printf("A SgTypedefSymbol was deleted\n");
21014 }
21015 }
21016 }
21017 }
21018
21019 if(node == isSgTypedefDeclaration(node)->get_definingDeclaration()){
21020 ClassicVisitor visitor1((SgTypedefDeclaration*) node);
21021 traverseMemoryPoolVisitorPattern(visitor1);
21022 }
21023 }
21024
21025 /*////////////////////////////////////////////////
21026 /remove SgNamespaceDeclarationSymbol
21028
21029 if(isSgNamespaceDeclarationStatement(node) !=NULL){
21030 if(((SgNamespaceDeclarationStatement*)node)->get_scope()!=NULL){
21031 if(((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21032 {
21033 SgSymbol* symbol = ((SgNamespaceDeclarationStatement*)node)->get_symbol_from_symbol_table();
21034 if(isSgNamespaceSymbol(symbol)){
21035 ((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21036 delete symbol;
21037 //printf("A SgNamespaceSymbol was deleted\n");
21038 }
21039 }
21040 }
21041 }
21042
21043
21044 if(isSgNamespaceAliasDeclarationStatement(node) !=NULL){
21045 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()!=NULL){
21046 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21047 {
21048 SgSymbol* symbol = ((SgNamespaceAliasDeclarationStatement*)node)->get_symbol_from_symbol_table();
21049 if(isSgNamespaceSymbol(symbol)){
21050 ((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21051 delete symbol;
21052 //printf("A SgNamespaceSymbol was deleted\n");
21053 }
21054 }
21055 }
21056 }
21057
21058
21059 /*/
21060 /remove SgLabelSymbol
21062
21063 if(isSgLabelStatement(node) !=NULL){
21064 if(((SgLabelStatement*)node)->get_scope()!=NULL){
21065 if(((SgLabelStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21066 {
21067 SgSymbol* symbol = ((SgLabelStatement*)node)->get_symbol_from_symbol_table();
21068 if(isSgLabelSymbol(symbol)){
21069 ((SgLabelStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21070 delete symbol;
21071 //printf("A SgLabelSymbol was deleted\n");
21072 }
21073 }
21074 }
21075 }
21076
21077 if(isSgLabelRefExp(node) !=NULL){
21078 SgLabelSymbol* symbol = ((SgLabelRefExp*)node)->get_symbol();
21079 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21080 delete symbol;
21081 //printf("A SgLabelSymbol was deleted\n");
21082 }
21083
21084
21085 /*////////////////////////////////////////////////
21086 /remove SgEnumSymbol
21088
21089 if(isSgEnumDeclaration(node) !=NULL){
21090 if(((SgEnumDeclaration*)node)->get_scope()!=NULL){
21091 if(((SgEnumDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21092 {
21093 SgSymbol* symbol = ((SgEnumDeclaration*)node)->get_symbol_from_symbol_table();
21094 if(isSgEnumSymbol(symbol) !=NULL){
21095 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21096 delete symbol;
21097 //printf("A SgEnumSymbol was deleted\n");
21098 }
21099 }
21100 }
21101 SgEnumType* type= ((SgEnumDeclaration*)node)->get_type();
21102 if(type !=NULL){
21103 delete type;
21104 //printf("A SgEnumType was deleted\n");
21105 }
21106 }
21107
21108
21109 /*/
21110 /remove SgClassSymbol
21112
21113 if(isSgClassDeclaration(node) !=NULL && isSgTemplateInstantiationDecl(node) ==NULL){
21114 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21115 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21116 {
21117 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21118 if(isSgClassSymbol(symbol) !=NULL){
21119 ClassicVisitor visitor((SgClassSymbol*)symbol);
21120 traverseMemoryPoolVisitorPattern(visitor);
21121 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21122 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21123 delete symbol;
21124 //printf("A SgClassSymbol was deleted\n");
21125 }
21126 }
21127 }
21128 }
21129
21130 ClassicVisitor visitor((SgClassDeclaration*) node );
21131 traverseMemoryPoolVisitorPattern(visitor);
21132
21133 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21134 if(type !=NULL){
21135 delete type;
21136 //printf("A SgClassType was deleted\n");
21137 }
21138 }
21139
21140 if(isSgThisExp(node) !=NULL){
21141 SgSymbol* symbol = ((SgThisExp*)node)->get_class_symbol();
21142 ClassicVisitor visitor((SgClassSymbol*)symbol);
21143 traverseMemoryPoolVisitorPattern(visitor);
21144 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21145 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21146 delete symbol;
21147 //printf("A SgClassSymbol was deleted\n");
21148 }
21149
21150 }
21151
21152 if(isSgClassNameRefExp(node) !=NULL){
21153 SgSymbol* symbol = ((SgClassNameRefExp*)node)->get_symbol();
21154 if(isSgClassSymbol(symbol) !=NULL)
21155 {
21156 ClassicVisitor visitor((SgClassSymbol*)symbol);
21157 traverseMemoryPoolVisitorPattern(visitor);
21158 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21159 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21160 delete symbol;
21161 //printf("A SgClassSymbol was deleted\n");
21162 }
21163 }
21164 }
21165
21166 /*////////////////////////////////////////////////
21167 /remove SgMemberFunctionSymbol
21169
21170
21171 if(isSgMemberFunctionDeclaration(node) !=NULL){
21172 if(((SgMemberFunctionDeclaration*)node)->get_scope()!=NULL){
21173 if(((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21174 {
21175 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21176 if(isSgMemberFunctionSymbol(symbol)){
21177 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21178 traverseMemoryPoolVisitorPattern(visitor);
21179 if(visitor.get_num_memFunc_pointers()==1){
21180 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21181 delete symbol;
21182 //printf("A SgMemberFunctionSymbol was deleted\n");
21183 }
21184 }
21185 }
21186 }
21187 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21188 traverseMemoryPoolVisitorPattern(visitor);
21189
21190 }
21191//Tan: I have no idea why the codes below cannot work. Perhaps it conflicts with some prior works
21192#if 0
21193 if(isSgMemberFunctionRefExp(node) !=NULL){
21194 SgMemberFunctionSymbol* symbol = ((SgMemberFunctionRefExp*)node)->get_symbol_i();
21195 ClassicVisitor visitor(symbol);
21196 traverseMemoryPoolVisitorPattern(visitor);
21197 if(visitor.get_num_memFunc_pointers()==1){ //only one reference to this symbol => safe to delete
21198 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21199 delete symbol;
21200 //printf("A SgClassSymbol was deleted\n");
21201 }
21202
21203 }
21204
21205 if(isSgFunctionType(node) !=NULL){
21206 SgSymbol* symbol = ((SgFunctionType*)node)->get_symbol_from_symbol_table();
21207 if(isSgFunctionTypeSymbol(symbol)){
21208 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21209 delete symbol;
21210 //printf("A SgFunctionTypeSymbol was deleted\n");
21211 }
21212 }
21213#endif
21214
21215 /*/
21218
21219 if(isSgInterfaceStatement(node) !=NULL){
21220 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21221 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21222 {
21223 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21224 if(isSgInterfaceSymbol(symbol)){
21225 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21226 delete symbol;
21227 //printf("A SgInterfaceSymbol was deleted\n");
21228 }
21229 }
21230 }
21231
21232 }
21233
21234
21235 if(isSgModuleStatement(node) !=NULL){
21236 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21237 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21238 {
21239 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21240 if(isSgModuleSymbol(symbol)){
21241 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21242 delete symbol;
21243 //printf("A SgModuleSymbol was deleted\n");
21244 }
21245 }
21246 }
21247
21248 }
21249
21250
21251//Tan: I got stuck in deleting the SgTemplateArgument
21252#if 0
21253 if(isSgTemplateInstantiationMemberFunctionDecl(node) !=NULL){
21254 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()!=NULL){
21255 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21256 {
21257 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
21258 if(isSgMemberFunctionSymbol(symbol)){
21259 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21260 traverseMemoryPoolVisitorPattern(visitor);
21261 if(visitor.get_num_memFunc_pointers()==1){
21262 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21263 delete symbol;
21264 //printf("A SgMemberFunctionSymbol was deleted\n");
21265 }
21266 }
21267 }
21268 }
21269 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21270 traverseMemoryPoolVisitorPattern(visitor);
21271 }
21272
21273 if(isSgTemplateDeclaration(node) !=NULL){
21274 if(((SgTemplateDeclaration*)node)->get_scope()!=NULL){
21275 if(((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21276 {
21277 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
21278 ClassicVisitor visitor((SgTemplateSymbol*)symbol);
21279 traverseMemoryPoolVisitorPattern(visitor);
21280 if(visitor.get_num_Template_pointers()==1){
21281 ((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21282 delete symbol;
21283 printf("A SgTemplateSymbol was deleted\n");
21284 }
21285 }
21286 }
21287 //if(isSgTemplateDeclaration(node) == ((SgTemplateDeclaration*)node)->get_firstNondefiningDeclaration()){
21288 ClassicVisitor visitor1((SgTemplateDeclaration*) node );
21289 traverseMemoryPoolVisitorPattern(visitor1);
21290 //}
21291
21292 }
21293
21294 if(isSgInterfaceStatement(node) !=NULL){
21295 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21296 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21297 {
21298 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21299 if(isSgInterfaceSymbol(symbol)){
21300 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21301 delete symbol;
21302 //printf("A SgInterfaceSymbol was deleted\n");
21303 }
21304 }
21305 }
21306
21307 }
21308
21309
21310 if(isSgModuleStatement(node) !=NULL){
21311 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21312 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21313 {
21314 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21315 if(isSgModuleSymbol(symbol)){
21316 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21317 delete symbol;
21318 //printf("A SgModuleSymbol was deleted\n");
21319 }
21320 }
21321 }
21322
21323 }
21324
21325 if(isSgTemplateInstantiationDecl(node) !=NULL){
21326 if(((SgTemplateInstantiationDecl*)node)->get_scope()!=NULL){
21327 if(((SgTemplateInstantiationDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21328 {
21329 SgSymbol* symbol = ((SgTemplateInstantiationDecl*)node)->get_symbol_from_symbol_table();
21330 if(isSgClassSymbol(symbol)){
21331 ClassicVisitor visitor((SgClassSymbol*)symbol);
21332 traverseMemoryPoolVisitorPattern(visitor);
21333 if(visitor.get_num_Class_pointers()==1){
21334 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21335 delete symbol;
21336 }
21337 }
21338 }
21339 }
21340 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21341 if(type !=NULL){
21342 delete type;
21343 //printf("A SgClassType was deleted\n");
21344 }
21345
21346 vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
21347 foreach (SgTemplateArgument* element, tempargs){
21348 SgTemplateArgument* temparg = isSgTemplateArgument(element);
21349 if(temparg){
21350 delete temparg;
21351 }
21352 printf("SgTemplateArg in normal traversal\n");
21353 }
21354 printf("SgTemplateInstantiationDecl in normal traversal\n");
21355
21356 ClassicVisitor visitor((SgTemplateInstantiationDecl*) node);
21357 traverseMemoryPoolVisitorPattern(visitor);
21358 }
21359
21360#endif
21361#if 0
21362 printf ("Deleting node = %p = %s = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
21363#endif
21364 // Normal nodes will be removed in a post-order way
21365 delete node;
21366#if 0
21367 printf ("After delete node: node = %p = %s \n",node,node->class_name().c_str());
21368#endif
21369 }
21370 };
21371
21372
21373 DeleteAST deleteTree;
21374
21375 // Deletion must happen in post-order to avoid traversal of (visiting) deleted IR nodes
21376 deleteTree.traverse(n,postorder);
21377
21378#if 0
21379 printf ("Leaving SageInterface::deleteAST(): n = %p = %s \n",n,n->class_name().c_str());
21380#endif
21381 }
21382
21383
21384
21385
21386#ifndef USE_ROSE
21387// DQ (9/25/2011): The deleteAST() function will not remove original expression trees behind constant folded expressions.
21388// These exist in the AST within the internal construction of the AST until they are simplified in the AST post-processing.
21389// In the post-processing either:
21390// 1) the constant folded values are kept and the original expression trees deleted (optional, controled by default parameter to function "frontend()", OR
21391// 2) the constant folded values are replaced by the original expression trees, and the constant folded values are deleted (default).
21392// Either way, after the AST post-processing the AST is simplified. Until then the expression trees can contain constant
21393// folded values and the values will have a pointer to the original expression tree. Before (9/16/2011) the original
21394// tree would also sometimes (not uniformally) be traversed as part of the AST. This was confusing (to people and
21395// to numerous forms of analysis), so this is being fixed to be uniform (using either of the methods defined above).
21396// However, the fact that until post-processing the AST has this complexity, and that the AST traversal does not
21397// traverse the original expression trees (now uniform); means that we need a special delete function for subtrees
21398// that are not use post-processed. This is the special purpose function that we need.
21399//
21400// NOTE: This function is called from the SgArrayType::createType() member function and in the constant folding AST post-processing.
21401//
21403 {
21404 struct Visitor: public AstSimpleProcessing
21405 {
21406 virtual void visit(SgNode* n)
21407 {
21408 SgExpression* expression = isSgExpression(n);
21409 if (expression != NULL)
21410 {
21411 Visitor().traverse(expression->get_originalExpressionTree(), postorder);
21412 }
21413
21414 delete (n);
21415 }
21416 };
21417
21418 Visitor().traverse(root, postorder);
21419 }
21420#endif
21421 // move symbol table from one scope to another
21422static void moveSymbolTableBetweenBlocks(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, std::vector <SgInitializedName*>& initname_vec)
21423{
21424 // Move the symbol table
21425 SgSymbolTable* s_table = sourceBlock->get_symbol_table();
21426 ASSERT_not_null(sourceBlock->get_symbol_table());
21427 // Liao, 11/26/2019 make sure the symbol table has symbols for init names before and after the move
21428 for (SgInitializedName* iname : initname_vec)
21429 {
21430 SgSymbol* symbol = s_table->find(iname);
21431 ASSERT_not_null(symbol);
21432 }
21433 // entirely move source block's symbol table to target block
21434 targetBlock->set_symbol_table(sourceBlock->get_symbol_table());
21435
21436 ASSERT_not_null(sourceBlock);
21437 ASSERT_not_null(targetBlock);
21438 ASSERT_not_null(targetBlock->get_symbol_table());
21439 ASSERT_not_null(sourceBlock->get_symbol_table());
21440 targetBlock->get_symbol_table()->set_parent(targetBlock);
21441
21442 ASSERT_not_null(sourceBlock->get_symbol_table());
21443 sourceBlock->set_symbol_table(nullptr);
21444
21445 // Reset with a valid symbol table
21446 sourceBlock->set_symbol_table(new SgSymbolTable());
21447 sourceBlock->get_symbol_table()->set_parent(sourceBlock);
21448
21449 ASSERT_require(targetBlock->get_symbol_table() == s_table);
21450 for (SgInitializedName* iname : initname_vec)
21451 {
21452 SgSymbol* symbol = s_table->find(iname);
21453 ASSERT_not_null(symbol);
21454 }
21455
21456 // Liao, 11/26/2019 make sure init names have symbols after the move.
21457 for (SgInitializedName* iname : initname_vec)
21458 {
21459 SgSymbol* symbol = iname->get_symbol_from_symbol_table();
21460 ASSERT_not_null(symbol);
21461 }
21462}
21463
21464// helper function to move a single statement or declaration from a block to another
21465static void moveOneStatement(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, SgStatement* stmt, std::vector <SgInitializedName*>& initname_vec)
21466{
21467 // append statement to the target block
21468 targetBlock->append_statement(stmt);
21469
21470 // Make sure that the parents are set.
21471 ASSERT_require(stmt->get_parent() == targetBlock);
21472 if (stmt->hasExplicitScope())
21473 {
21474 if (stmt->get_scope() != targetBlock)
21475 {
21476 if (SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt))
21477 {
21478 // why only move if it is a first nondefining declaration?
21479 // We have a case to move both defining and nondefining function declarations of Ada package body to namespace definition.
21480 // comment out the if condition for now. 1/20/2021
21481 //
21482 // A call to a undeclared function will introduce a hidden func prototype declaration in the enclosing scope .
21483 // The func declaration should be moved along with the call site.
21484 // The scope should be set to the new block also
21485 // Liao 1/14/2011
21486 func->set_scope(targetBlock);
21487 // This is needed to move functions in Ada package body into C++ namespace
21488 // We may have compiler generated first nondefining declaration. We need to move its scope also
21489 SgFunctionDeclaration* nondef_decl= isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
21490 if (func != nondef_decl)
21491 {
21492 ASSERT_not_null(nondef_decl);
21493 ASSERT_not_null(nondef_decl->get_file_info());
21494 if (nondef_decl->get_file_info()->isCompilerGenerated()) {
21495 nondef_decl->set_scope(targetBlock);
21496 }
21497 }
21498 }
21499 else if (auto labelStmt = isSgLabelStatement(stmt))
21500 {
21501 if (labelStmt->get_scope() == sourceBlock) {
21502 labelStmt->set_scope(targetBlock);
21503 // Make sure the labelStmt is in the enclosing function scope of targetBlock
21504 SageInterface::fixLabelStatement(labelStmt, targetBlock);
21505 }
21506 }
21507 else if (isSgJovialTableStatement(stmt) || isSgTypedefDeclaration(stmt) || isSgEnumDeclaration(stmt))
21508 {
21509 // Rasmussen 9/21/2020,10/27/2020,11/4/2020: Uncovered by issues RC-135 and RC-227.
21510 // The issues are fixed in the switch statement below but this test is needed
21511 // so that the warning message immediately below is not triggered.
21512 }
21513 else
21514 {
21515 mlog[Rose::Diagnostics::WARN] << "test failing stmt->get_scope() == targetBlock in SageInterface::moveStatementsBetweenBlocks(): class: "
21516 << stmt->class_name() << "\n";
21517 }
21518 }
21519 }
21520
21521 SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
21522 if (declaration != nullptr)
21523 {
21524 // Need to reset the scope from sourceBlock to targetBlock.
21525 switch(declaration->variantT())
21526 {
21527 // There will be other cases to handle, but likely not all declaration will be possible to support.
21528
21529 case V_SgVariableDeclaration:
21530 {
21531 // Reset the scopes on any SgInitializedName objects.
21532 SgVariableDeclaration* varDecl = isSgVariableDeclaration(declaration);
21533 SgInitializedNamePtrList & l = varDecl->get_variables();
21534 for (SgInitializedNamePtrList::iterator ii = l.begin(); ii != l.end(); ii++)
21535 {
21536 // reset the scope, but make sure it was set to sourceBlock to make sure.
21537 // This might be an issue for extern variable declaration that have a scope
21538 // in a separate namespace of a static class member defined external to
21539 // its class, etc. I don't want to worry about those cases right now.
21540
21541 SgInitializedName * init_name = (*ii);
21542
21543 // Rasmussen (3/16/2021): Use the base type in case type is modified (i.e., const)
21544 SgType* var_type = init_name->get_type();
21545 if (SgModifierType* mod_type = isSgModifierType(var_type))
21546 {
21547 var_type = mod_type->get_base_type();
21548 }
21549
21550 // Rasmussen (6/29/2020) and (10/19/2020): Variable declarations related to anonymous types are not
21551 // moved. This is fixed below. Note that SgJovialTableType derives from SgClassType, it may
21552 // be that class types are not moved correctly either.
21553 //
21554 if (isSgEnumType(var_type))
21555 {
21556 SgEnumType* enum_type = isSgEnumType(var_type);
21557 SgEnumDeclaration* decl = isSgEnumDeclaration(enum_type->get_declaration());
21558 SgEnumDeclaration* def_decl = isSgEnumDeclaration(decl->get_definingDeclaration());
21559 SgEnumDeclaration* nondef_decl = isSgEnumDeclaration(decl->get_firstNondefiningDeclaration());
21560
21561 if (decl->get_scope() == sourceBlock)
21562 {
21563 // Needs to be moved
21564 def_decl->set_scope(targetBlock);
21565 nondef_decl->set_scope(targetBlock);
21566 nondef_decl->set_parent(targetBlock);
21567
21568 // Move the scope of the enumerators to the new block as well
21569 for (SgInitializedName* enumerator : def_decl->get_enumerators())
21570 {
21571 enumerator->set_scope(targetBlock);
21572 }
21573 }
21574 }
21575 else if (isSgJovialTableType(var_type))
21576 {
21577 SgJovialTableType* table_type = isSgJovialTableType(var_type);
21578 SgDeclarationStatement* decl = table_type->get_declaration();
21579 if (decl->get_scope() == sourceBlock)
21580 {
21581 // Needs to be moved
21584 def_decl->set_scope(targetBlock);
21585 nondef_decl->set_scope(targetBlock);
21586 nondef_decl->set_parent(targetBlock);
21587 }
21588 }
21589
21590 // Must also move the symbol into the source block, Liao 2019/8/14
21591 SgVariableSymbol* var_sym = isSgVariableSymbol(init_name -> search_for_symbol_from_symbol_table ()) ;
21592 ASSERT_not_null(var_sym);
21593 SgScopeStatement * old_scope = var_sym -> get_scope();
21594#if 1 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21595 if (old_scope != sourceBlock)
21596 {
21597 old_scope->remove_symbol (var_sym);
21598 sourceBlock ->insert_symbol(init_name->get_name(), var_sym);
21599 }
21600#endif
21601 init_name->set_scope(targetBlock);
21602 initname_vec.push_back(init_name);
21603 }
21604 break;
21605 }
21606 case V_SgFunctionDeclaration: // Liao 1/15/2009, I don't think there is any extra things to do here
21607 {
21608 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(declaration);
21609 ASSERT_not_null(funcDecl);
21610#if 0 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21611 // move function symbols also: search_for_symbol_from_symbol_table()
21613 if (func_sym)
21614 {
21615 SgScopeStatement * old_scope = func_sym -> get_scope();
21616 if (old_scope != sourceBlock)
21617 {
21618 old_scope->remove_symbol (func_sym);
21619 sourceBlock ->insert_symbol(func_sym->get_name(), func_sym);
21620 }
21621 }
21622#endif
21623 break;
21624 }
21625 // needed to move Ada record into definition of C++ namespace
21626 case V_SgProgramHeaderStatement:
21627 case V_SgProcedureHeaderStatement:
21628 case V_SgClassDeclaration:
21629 case V_SgEnumDeclaration:
21630 {
21631 SgDeclarationStatement* nondef_decl = declaration->get_firstNondefiningDeclaration();
21632 ASSERT_not_null(nondef_decl);
21633
21634 nondef_decl->set_parent(targetBlock);
21635 nondef_decl->set_scope(targetBlock);
21636
21637 SgDeclarationStatement* def_decl = declaration->get_definingDeclaration();
21638 if (def_decl)
21639 {
21640 def_decl->set_parent(targetBlock);
21641 def_decl->set_scope(targetBlock);
21642 }
21643 else
21644 {
21645 // Set the scope of the function arguments
21646 if (auto proc = isSgProcedureHeaderStatement(nondef_decl)) {
21647 for (auto arg : proc->get_parameterList()->get_args()) {
21648 if (arg->get_scope() != proc->get_scope()) {
21649 // Note: arg (is an SgInitializedName) from the parameter list does not have
21650 // a symbol in the scope of the procedure declaration (proc). Should add
21651 // arg to initname_vec, which will check for missing symbols [GL-387, Rasmussen 7/22/2024].
21652 arg->set_scope(proc->get_scope());
21653 }
21654 }
21655 }
21656 }
21657
21658 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(stmt);
21659 if (enum_decl)
21660 {
21661 // Set the scope of the enumerators [Rasmussen 12/23/2020]
21662 for (SgInitializedName* name : enum_decl->get_enumerators())
21663 {
21664 name->set_scope(targetBlock);
21665 }
21666 }
21667 break;
21668 }
21669 case V_SgJovialTableStatement:
21670 {
21671 // [RC-135, Rasmussen 9/21/2020]
21672 SgJovialTableStatement* table = isSgJovialTableStatement(declaration);
21673 ROSE_ASSERT (table);
21674
21677 nondef_decl->set_parent(targetBlock);
21678 nondef_decl->set_scope(targetBlock);
21679 def_decl->set_scope(targetBlock);
21680 break;
21681 }
21682 case V_SgTypedefDeclaration:
21683 {
21684 // [RC-227, Rasmussen 10/19/2020]
21685 SgTypedefDeclaration* typedef_decl = isSgTypedefDeclaration(declaration);
21686 ASSERT_not_null(typedef_decl);
21687 typedef_decl->set_parent(targetBlock);
21688 typedef_decl->set_scope(targetBlock);
21689 break;
21690 }
21691 case V_SgAttributeSpecificationStatement:
21692 case V_SgEmptyDeclaration:
21693 case V_SgFortranIncludeLine:
21694 case V_SgImplicitStatement: // Rasmussen 5/13/2021: TODO: implicit statement with letter-list
21695 case V_SgJovialDefineDeclaration:
21696 case V_SgJovialDirectiveStatement:
21697 case V_SgJovialLabelDeclaration:
21698 case V_SgJovialOverlayDeclaration:
21699 case V_SgPragmaDeclaration:
21700 case V_SgAdaAttributeClause:
21701 break;
21702 default:
21703 {
21704 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());
21705 declaration->get_file_info()->display("file info");
21706 ROSE_ABORT();
21707 }
21708 }
21709 } // end if
21710}
21711
21712// different handling for scopes with declarations only
21713template <class T1, class T2>
21714void moveDeclarationsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21715{
21716 // This function moves statements from one block to another (used by the outliner).
21717 // printf ("***** Moving statements from sourceBlock %p to targetBlock %p ***** \n",sourceBlock,targetBlock);
21718 ROSE_ASSERT (sourceBlock && targetBlock);
21719 ROSE_ASSERT (sourceBlock->containsOnlyDeclarations() && targetBlock->containsOnlyDeclarations());
21720 if ((void*)sourceBlock == (void*)targetBlock)
21721 {
21722 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21723 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21724 return;
21725 }
21726
21727 SgDeclarationStatementPtrList& srcStmts = sourceBlock->get_declarations ();
21728 std::vector <SgInitializedName*> initname_vec;
21729
21730 for (auto stmt : srcStmts)
21731 {
21732 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21733 }
21734
21735 // Remove the statements in the sourceBlock
21736 srcStmts.clear();
21737 ROSE_ASSERT(srcStmts.empty() == true);
21738 ROSE_ASSERT(sourceBlock->get_declarations().empty() == true);
21739
21740 // move symbol table from one scope to another
21741 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21742
21743 // Liao 2/4/2009
21744 // Finally , move preprocessing information attached inside the source block to the target block
21745 // Outliner uses this function to move a code block to the outlined function.
21746 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21747 // to the target block to match #if (which is attached
21748 // before some statement moved to the target block)
21749 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21750}
21751
21752
21753// source and destination class, both are derived classes of scope statement but with support of get_statements()
21754template <class T1, class T2>
21755void moveStatementsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21756{
21757 // This function moves statements from one block to another (used by the outliner).
21758 ROSE_ASSERT (sourceBlock && targetBlock);
21759 if ((void*)sourceBlock == (void*)targetBlock)
21760 {
21761 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21762 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21763 return;
21764 }
21765
21766 SgStatementPtrList & srcStmts = sourceBlock->get_statements();
21767 std::vector <SgInitializedName*> initname_vec;
21768
21769 for (SgStatement* stmt : srcStmts)
21770 {
21771 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21772 }
21773
21774 // Remove the statements in the sourceBlock
21775 srcStmts.clear();
21776 ROSE_ASSERT(srcStmts.empty() == true);
21777 ROSE_ASSERT(sourceBlock->get_statements().empty() == true);
21778
21779 // move symbol table from one scope to another
21780 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21781
21782 // Liao 2/4/2009
21783 // Finally , move preprocessing information attached inside the source block to the target block
21784 // Outliner uses this function to move a code block to the outlined function.
21785 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21786 // to the target block to match #if (which is attached
21787 // before some statement moved to the target block)
21788 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21789
21790}
21791
21792static void createAliasSymbols (SgNamespaceDeclarationStatement* decl)
21793{
21794 ASSERT_not_null(decl);
21796 SgNamespaceDefinitionStatement* global_def = local_def->get_global_definition();
21797
21798 ASSERT_require(local_def && global_def && (local_def!=global_def));
21799
21800 for (auto symbol : local_def->get_symbol_table()->get_symbols())
21801 {
21802 SgSymbol *orig_sym = isSgSymbol(symbol);
21803 ASSERT_not_null(orig_sym);
21804 SgAliasSymbol* asym = new SgAliasSymbol (orig_sym);
21805 global_def->get_symbol_table()->insert (asym->get_name(), asym);
21806 }
21807}
21808
21809//TODO: now with more types, we need to use template functions
21811{
21812 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21813 //create alias symbols in its global definition
21814 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21815}
21816
21818{
21819 moveStatementsBetweenScopes(sourceBlock, targetBlock);
21820 //create alias symbols in its global definition
21821 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21822}
21823
21825{
21826 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21827}
21828
21829void
21831{
21832 moveStatementsBetweenScopes (sourceBlock, targetBlock);
21833}
21834
21836// TODO, expose to SageInterface namespace
21838{
21839 bool rt = false;
21840 ROSE_ASSERT (func != NULL);
21841 SgNode* p = func->get_parent();
21842 ROSE_ASSERT (p != NULL);
21843 SgLambdaExp* le = isSgLambdaExp (p);
21844 if (le && le->get_lambda_function() == func)
21845 rt = true;
21846 return rt;
21847}
21848
21849// check if a variable reference is this->a[i] inside of a lambda function
21850// SgArrowExp <SgThisExp, SgVarRefExp>, both are compiler generated nodes
21851// class symbol of ThisExp 's declaration is AutonomousDeclaration SgClassDeclaration
21852// its parent is SgLambdaExp, and lambda_closure_class points back to this class declaration
21854{
21855 bool rt = false;
21856#ifdef _MSC_VER
21857 #pragma message ("WARNING: MSVC does not handle isLambdaCapturedVariable() properly.")
21858#else
21859 ROSE_ASSERT (varRef!= NULL);
21860 SgNode* parent = varRef->get_parent();
21861 if (SgArrowExp *p = isSgArrowExp(parent))
21862 {
21863 SgThisExp* te = isSgThisExp(p->get_lhs_operand_i());
21864 if (te != NULL)
21865 {
21866 SgClassSymbol* csym = te->get_class_symbol();
21867 ROSE_ASSERT (csym!= NULL);
21868 SgClassDeclaration* xdecl = isSgClassDeclaration(csym->get_declaration());
21869 // each this exp should have a class decl
21870 ROSE_ASSERT (xdecl != NULL);
21871 SgLambdaExp* le = isSgLambdaExp(xdecl->get_parent());
21872 if (le != NULL)
21873 {
21874 if (le->get_lambda_closure_class() == xdecl ) // the class is a lambda closure class
21875 rt = true;
21876 }
21877 }
21878 }
21879#endif
21880 return rt;
21881}
21882
21885//TODO consult AstInterface::IsVarRef() for more cases
21887{
21888 SgInitializedName* name = NULL;
21889 SgExpression* nameExp = NULL;
21890 ROSE_ASSERT(current != NULL);
21891
21892 if (isSgInitializedName(current))
21893 {
21894 name = isSgInitializedName(current);
21895 }
21896 else if (isSgPntrArrRefExp(current) != NULL)
21897 {
21898 bool suc=false;
21899 SgExpression* exp = isSgExpression(current);
21900 ROSE_ASSERT(exp != NULL);
21901 suc = SageInterface::isArrayReference(exp,&nameExp);
21902 ROSE_ASSERT(suc == true);
21903 // has to resolve this recursively
21904 return convertRefToInitializedName(nameExp, coarseGrain);
21905 }
21906 else if (isSgVarRefExp(current) != NULL)
21907 {
21908 if (coarseGrain)
21909 {
21910 // Outliner needs coarse grain mem objects to work. Always returning fine grain objects will cause problems.
21911 SgNode* parent = current->get_parent();
21912 if (isSgDotExp(parent))
21913 {
21914 if (isSgDotExp(parent)->get_rhs_operand() == current)
21915 return convertRefToInitializedName(parent, coarseGrain);
21916 }
21917 // avoid backtracking to parent if this is part of lambda function
21918 else if(isSgArrowExp(parent) && ! isLambdaCapturedVariable ( isSgVarRefExp(current) ) )
21919 {
21920 if (isSgArrowExp(parent)->get_rhs_operand() == current)
21921 return convertRefToInitializedName(parent, coarseGrain);
21922 }
21923 }
21924 name = isSgVarRefExp(current)->get_symbol()->get_declaration();
21925 }
21926 else if (isSgFunctionRefExp(current) != NULL ||
21927 isSgTemplateFunctionRefExp(current) != NULL ||
21928 isSgMemberFunctionRefExp(current) != NULL ||
21929 isSgTemplateMemberFunctionRefExp(current) != NULL)
21930 {
21931 //If a function is here it's probably related to a function pointer, it can't be converted to an SgInitailizedName
21932 return NULL;
21933 }
21934 else if (isSgNonrealRefExp(current) != NULL)
21935 {
21936 //SgNonrealRefExp is not a reasonable thing to convert to an SgInitializedName (I think) -Jim Leek
21937 return NULL;
21938 }
21939 else if (isSgDotExp(current))
21940 {
21941 SgExpression* child = NULL;
21942 if (coarseGrain)
21943 child= isSgDotExp(current)->get_lhs_operand();
21944 else
21945 child= isSgDotExp(current)->get_rhs_operand();
21946 ROSE_ASSERT(child);
21947 // has to resolve this recursively
21948 return convertRefToInitializedName(child, coarseGrain);
21949 }
21950 else if (isSgArrowExp(current))
21951 {
21952 SgExpression* child = NULL;
21953 if (coarseGrain)
21954 {
21955 SgExpression* lhs = isSgArrowExp(current)->get_lhs_operand();
21956 ROSE_ASSERT(lhs);
21957 // Liao 9/12/2016, special handling for variables inside of C++11 lambda functions
21958 // They capture variables outside of the lambda function.
21959 // They are represented as a class variable of an anonymous class, this->a[i]
21960 // So, we have to recognize this pattern, and pass the rhs variable to obtain initialized name.
21961 // has to resolve this recursively
21963
21964 if (isLambdaFunction (efunc) )
21965 child= isSgArrowExp(current)->get_rhs_operand();
21966 else
21967 child = lhs;
21968 }
21969 else
21970 child = isSgArrowExp(current)->get_rhs_operand();
21971 ROSE_ASSERT(child);
21972 // has to resolve this recursively
21973
21974 return convertRefToInitializedName(child, coarseGrain);
21975 } // The following expression types are usually introduced by left hand operands of DotExp, ArrowExp
21976 else if (isSgThisExp(current))
21977 {
21978 //SgThisExp* texp = isSgThisExp(current);
21979 name = NULL; // inside a class, there is no initialized name at all!! what to do??
21980 }
21981 else if (isSgPointerDerefExp(current))
21982 {
21983 return convertRefToInitializedName(isSgPointerDerefExp(current)->get_operand(), coarseGrain);
21984 }
21985 else if(isSgUnaryOp(current)) { //Written for SgAddressOfOp, but seems generally aplicable to all Unary Ops (replace above?) -JL
21986 return convertRefToInitializedName(isSgUnaryOp(current)->get_operand(), coarseGrain);
21987 }
21988 else if (isSgCastExp(current))
21989 {
21990 return convertRefToInitializedName(isSgCastExp(current)->get_operand(), coarseGrain);
21991 }
21992 // Scientific applications often use *(address + offset) to access array elements
21993 // If a pointer dereferencing is applied to AddOp, we assume the left operand is the variable of our interests
21994 else if (isSgAddOp(current))
21995 {
21996 SgExpression* lhs = isSgAddOp(current)->get_lhs_operand();
21997 return convertRefToInitializedName(lhs, coarseGrain);
21998 }
21999 else if (isSgSubtractOp(current))
22000 {
22001 SgExpression* lhs = isSgSubtractOp(current)->get_lhs_operand();
22002 return convertRefToInitializedName(lhs, coarseGrain);
22003 }
22004 // operator->() may be called upon a class object.
22005 // e.g. we need to get the function: it a SgDotExp node, (lhs is the class object, rhs is its member function)
22006 else if (SgFunctionCallExp * func_call = isSgFunctionCallExp(current))
22007 {
22008 return convertRefToInitializedName(func_call->get_function(), coarseGrain);
22009 }
22010 else if (isSgIntVal(current))
22011 {
22012 //It is very rare, but sometimes a constant is treated as a
22013 //variable. In which case we don't need an SgInitializdName
22014 return NULL;
22015 }
22016
22017 else
22018 {
22019 // side effect analysis will return rhs of Class A a = A(); as a read ref exp. SgConstructorInitializer
22020 if (!isSgConstructorInitializer(current))
22021 {
22022 mlog[Sawyer::Message::Common::WARN] <<
22023 "convertRefToInitializedName: " <<
22024 current->get_file_info()->get_filename() << ":" <<
22025 current->get_file_info()->get_line() << "-" << current->get_file_info()->get_col()<<endl;
22026 cerr<<"In SageInterface::convertRefToInitializedName(): unhandled reference type:"<<current->class_name()<<endl;
22027 ROSE_ABORT();
22028 }
22029 }
22030 //ROSE_ASSERT(name != NULL);
22031 return name;
22032}
22033
22036{
22037#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22038 printf ("AbstractHandle support is disabled for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT \n");
22039 ROSE_ABORT();
22040#else
22042
22043 // trim off the possible leading handle for project: "Project<numbering,1>::"
22044 size_t pos = input_string.find("SourceFile<");
22045 ROSE_ASSERT (pos != string::npos);
22046 string trimed_string = input_string.substr(pos);
22047 AbstractHandle::abstract_handle * handle = new AbstractHandle::abstract_handle(project_handle, trimed_string);
22048 if (handle)
22049 {
22050 if (handle->getNode()!=NULL)
22051 {
22052#ifdef _MSC_VER
22053 // DQ (11/28/2009): This is related to the use of covariant return types (I think).
22054 SgNode* result = NULL; // (SgNode*)(handle->getNode()->getNode());
22055#pragma message ("WARNING: covariant return type for get_node() not supported in MSVC.")
22056 printf ("ERROR: covariant return type for get_node() not supported in MSVC. \n");
22057 ROSE_ABORT();
22058#else
22059 SgNode* result = (SgNode*)(handle->getNode()->getNode());
22060#endif
22061 // deallocate memory, should not do this!!
22062 // May corrupt the internal std maps used in abstract handle namespace
22063 //delete handle->getNode();
22064 //delete handle;
22065 return result;
22066 }
22067 }
22068#endif
22069
22070 return NULL;
22071}
22072
22073
22075// unparseToString() is too strict for debugging purpose
22076// we provide this instead.
22077void SageInterface::dumpInfo(SgNode* node, std::string desc/*=""*/)
22078{
22079 ROSE_ASSERT(node != NULL);
22080 cout<<desc<<endl;
22081 // base information for all SgNode:
22082 cout<<"///////////// begin of SageInterface::dumpInfo() ///////////////"<<endl;
22083 cout<<"--------------base info. for SgNode---------------"<<endl;
22084 cout<<node<<" "<<node->class_name()<<endl;
22085 SgLocatedNode* snode = isSgLocatedNode(node);
22086 if (snode)
22087 {
22088 // source file info. dump
22089 cout<<"--------------source location info. for SgNode---------------"<<endl;
22090 cout<<snode->get_file_info()->get_filename()
22091 << ":"<<snode->get_file_info()->get_line()<<"-"
22092 << snode->get_file_info()->get_col()<<endl;
22093 // preprocessing info dump
22094 AttachedPreprocessingInfoType *comments = snode->getAttachedPreprocessingInfo ();
22095 if (comments)
22096 {
22097 cout<<"--------------preprocessing info. for SgNode---------------"<<endl;
22098 AttachedPreprocessingInfoType::iterator i;
22099 cout<<"Total attached preprocessingInfo count="<<comments->size()<<endl;
22100 for (i = comments->begin (); i != comments->end (); i++)
22101 {
22102 PreprocessingInfo * pinfo = *i;
22103 pinfo->display("");
22104 }
22105 }
22106 cout<<"--------------name info. for SgNode---------------"<<endl;
22107 // print out namea for named nodes
22108 SgFunctionDeclaration * decl = isSgFunctionDeclaration(snode);
22109 if (decl)
22110 cout<<"\tqualified name="<<decl->get_qualified_name().getString()<<endl;
22111 SgVarRefExp * varRef = isSgVarRefExp(snode);
22112 if (varRef)
22113 cout<<"\treferenced variable name= "<<varRef->get_symbol()->get_name().getString()<<endl;
22114 }
22115 SgInitializedName * iname = isSgInitializedName(snode);
22116 if (iname)
22117 cout<<"\tvariable name= "<<iname->get_qualified_name().getString()<<endl;
22118
22119 cout<<endl;
22120 cout<<"///////////// end of SageInterface::dumpInfo() ///////////////"<<endl;
22121}
22122
22128bool
22129SageInterface::collectReadWriteRefs(SgStatement* stmt, std::vector<SgNode*>& readRefs, std::vector<SgNode*>& writeRefs, bool useCachedDefUse)
22130{ // The type cannot be SgExpression since variable declarations have SgInitializedName as the reference, not SgVarRefExp.
22131 bool retVal = true;
22132
22133 ROSE_ASSERT(stmt !=NULL);
22134
22135#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22136 // We should allow accumulate the effects for multiple statements
22137 // ROSE_ASSERT(readRefs.size() == 0);
22138 // ROSE_ASSERT(writeRefs.size() == 0);
22139
22140 // convert a request for a defining function declaration to its function body
22141 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(stmt);
22142 if (funcDecl != NULL)
22143 {
22144 funcDecl= isSgFunctionDeclaration(funcDecl->get_definingDeclaration ());
22145 if (funcDecl == NULL)
22146 {
22147 cerr<<"In collectReadWriteRefs(): cannot proceed without a function body!"<<endl;
22148 }
22149 else
22150 stmt = funcDecl->get_definition()->get_body();
22151 }
22152
22153 // get function level information
22154 SgFunctionDefinition* funcDef = isSgFunctionDefinition(stmt);
22155 if (!funcDef)
22157
22158 ROSE_ASSERT(funcDef != NULL);
22159 SgBasicBlock* funcBody = funcDef->get_body();
22160 ROSE_ASSERT(funcBody!= NULL);
22161
22162 // prepare Loop transformation environment
22163 AstInterfaceImpl faImpl(funcBody);
22164 AstInterface fa(&faImpl);
22165 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
22166 if( useCachedDefUse ){
22167 ArrayInterface* array_interface = ArrayInterface::get_inst(*annot, fa, funcDef, AstNodePtrImpl(funcDef));
22168 LoopTransformInterface::set_arrayInfo(array_interface);
22169 } else {
22170 ArrayInterface array_interface(*annot);
22171 // Alias analysis and value propagation are called in initialize(). Turn both off for now.
22172// array_interface.initialize(fa, AstNodePtrImpl(funcDef));
22173 array_interface.observe(fa);
22174 LoopTransformInterface::set_arrayInfo(&array_interface);
22175 }
22176 LoopTransformInterface::set_astInterface(fa);
22177 // Liao, 3/27/2015. connect to annotations for function side effect
22178 LoopTransformInterface::set_sideEffectInfo(annot);
22179
22180 // variables to store results
22181 DoublyLinkedListWrap<AstNodePtr> rRef1, wRef1;
22182 CollectDoublyLinkedList<AstNodePtr> crRef1(rRef1),cwRef1(wRef1);
22183 AstNodePtr s1 = AstNodePtrImpl(stmt);
22184
22185 // Actual side effect analysis
22186 if (!AnalyzeStmtRefs(fa, s1, cwRef1, crRef1))
22187 {
22188 //False returned here just means that the function called a
22189 //function that was not annotated with Qing's RWset annotation
22190 //method. This doesn't matter for my tool. -Jim Leek 03/21/2023
22191 mlog[Sawyer::Message::Common::DEBUG] << "Function: " << funcDef->get_declaration()->get_qualified_name() << " calls at least one function that has not been annotated." << endl;
22192 retVal = false;
22193 }
22194
22195 // transfer results into STL containers.
22196 for (DoublyLinkedEntryWrap<AstNodePtr>* p = rRef1.First(); p != 0; )
22197 {
22198 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22199 p = rRef1.Next(p);
22200 AstNodePtr cur = p1->GetEntry();
22201 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22202 ROSE_ASSERT(sgRef != NULL);
22203 readRefs.push_back(sgRef);
22204 //cout<<"read reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22205 // " sage type:"<< sgRef->class_name()<< endl;
22206 }
22207
22208 for (DoublyLinkedEntryWrap<AstNodePtr>* p = wRef1.First(); p != 0; )
22209 {
22210 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22211 p = wRef1.Next(p);
22212 AstNodePtr cur = p1->GetEntry();
22213 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22214 ROSE_ASSERT(sgRef != NULL);
22215 writeRefs.push_back(sgRef);
22216 // cout<<"write reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22217 // " sage type:"<< sgRef->class_name()<< endl;
22218 }
22219
22220#endif
22221
22222 return retVal;
22223}
22224#if 0
22225// The side effect analysis will report three references for a statement like this->x = ...
22226// 1.SgThisExp 2. SgArrowExp 3. SgVarRefExp
22227// We only need to keep SgVarRefExp and skip the other two.
22228static bool skipSomeRefs(SgNode* n)
22229{
22230 ROSE_ASSERT (n);
22231 return (isSgThisExp(n)||isSgArrowExp(n)||isSgDotExp(n));
22232}
22233#endif
22235bool SageInterface::collectReadWriteVariables(SgStatement* stmt, set<SgInitializedName*>& readVars, set<SgInitializedName*>& writeVars, bool coarseGrain/*=true*/)
22236{
22237 ROSE_ASSERT(stmt != NULL);
22238 vector <SgNode* > readRefs, writeRefs;
22239
22240 bool retVal = collectReadWriteRefs(stmt, readRefs, writeRefs);
22241 // process read references
22242 vector<SgNode*>::iterator iter = readRefs.begin();
22243 for (; iter!=readRefs.end();iter++)
22244 {
22245 SgNode* current = *iter;
22246 //if (skipSomeRefs(current)) continue;
22247
22248 ROSE_ASSERT (current != NULL);
22249 SgInitializedName* name= convertRefToInitializedName(current, coarseGrain);
22250 //ROSE_ASSERT (name); // this pointer will return NULL
22251 if (!name) continue;
22252 // Only insert unique ones
22253 // We use std::set to ensure uniqueness now
22254 readVars.insert(name);
22255 }
22256 // process write references
22257 vector<SgNode*>::iterator iterw = writeRefs.begin();
22258 for (; iterw!=writeRefs.end();iterw++)
22259 {
22260 SgNode* current = *iterw;
22261 ROSE_ASSERT (current != NULL);
22262 SgInitializedName* name = convertRefToInitializedName(current, coarseGrain);
22263 if (!name) continue;
22264 //ROSE_ASSERT (name); // this pointer will return NULL
22265 // Only insert unique ones
22266 // We use std::set to ensure uniqueness now
22267 writeVars.insert(name);
22268 }
22269 return retVal;
22270}
22271
22273void SageInterface::collectReadOnlyVariables(SgStatement* stmt, std::set<SgInitializedName*>& readOnlyVars, bool coarseGrain/*=true*/)
22274{
22275 ROSE_ASSERT(stmt != NULL);
22276 set<SgInitializedName*> readVars, writeVars;
22277 // Only collect read only variables if collectReadWriteVariables() succeeded.
22278 if (collectReadWriteVariables(stmt, readVars, writeVars, coarseGrain))
22279 {
22280 // read only = read - write
22281 set_difference(readVars.begin(), readVars.end(),
22282 writeVars.begin(), writeVars.end(),
22283 std::inserter(readOnlyVars, readOnlyVars.begin()));
22284 }
22285 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
22286 {
22287 RoseAst ast(stmt);
22288
22289 for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
22290 if (SgVarRefExp* v_ref = isSgVarRefExp(*i))
22291 {
22292 if (isConstType(v_ref->get_type()))
22293 readOnlyVars.insert (v_ref->get_symbol()->get_declaration());
22294 }
22295 } // end for
22296 } // end else
22297}
22298
22299
22301void SageInterface::collectReadOnlySymbols(SgStatement* stmt, std::set<SgVariableSymbol*>& readOnlySymbols, bool coarseGrain/*=true*/)
22302{
22303 set<SgInitializedName*> temp;
22304 collectReadOnlyVariables(stmt, temp, coarseGrain);
22305
22306 for (set<SgInitializedName*>::const_iterator iter = temp.begin();
22307 iter!=temp.end(); iter++)
22308 {
22309 SgSymbol* symbol = (*iter)->get_symbol_from_symbol_table () ;
22310 ROSE_ASSERT(symbol != NULL );
22311 ROSE_ASSERT(isSgVariableSymbol(symbol));
22312 readOnlySymbols.insert(isSgVariableSymbol(symbol));
22313 }
22314
22315}
22316
22319{
22320 bool result = false;
22321 ROSE_ASSERT(ref != NULL);
22322 ROSE_ASSERT(ref->get_parent() != NULL);
22323 // case 1: ref is used as an operator for & (SgAddressofOp)
22324 // TODO tolerate possible type casting operations in between ?
22325 if (isSgAddressOfOp(ref->get_parent()))
22326 {
22327 result = true;
22328 }
22329 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22330 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22331 {
22332 SgNode* grandparent = ref->get_parent()->get_parent();
22333 ROSE_ASSERT(grandparent);
22334 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22335 {
22336 // find which parameter ref is in SgExpressionPtrList
22337
22338 // DQ (8/12/2020): This is a compiler warning where it is used below in comparision between signed and unsigned types.
22339 // int param_index = 0;
22340 size_t param_index = 0;
22341
22342 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22343 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22344 for (; iter!=expList.end(); iter++)
22345 {
22346 if (*iter == ref)
22347 break;
22348 else
22349 param_index++;
22350 }
22351 // find the parameter type of the corresponding function declaration
22352 SgExpression* func_exp = isSgFunctionCallExp(grandparent)->get_function();
22353 ROSE_ASSERT (func_exp);
22354 SgFunctionRefExp * funcRef = isSgFunctionRefExp(func_exp);
22355 if (funcRef) // regular functions
22356 {
22357 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22358 SgInitializedNamePtrList nameList = funcDecl->get_args();
22359 //TODO tolerate typedef chains
22360 // printf() has only two arguments to express variable arguments.
22361 // The third argument index ==2 will be out of bounds for nameList[index]
22362 // So we must check the bound first.
22363 if (param_index >= nameList.size() ||isSgTypeEllipse(nameList[param_index]->get_type()) )
22364 {
22365 if (isSgReferenceType(ref))
22366 result = true;
22367 }
22368 else // now within the bound: two situations,
22369 if (isSgReferenceType(nameList[param_index]->get_type()))
22370 {
22371 result = true;
22372 }
22373 } //It also could be a dot or arrow expression where its right hand operand is a SgMemberFunctionRefExp
22374 else if (isSgDotExp (func_exp) || isSgArrowExp(func_exp)) // ArrowExp TODO
22375 {
22376 SgBinaryOp* binOp = isSgBinaryOp(func_exp);
22377 ROSE_ASSERT (binOp);
22378 SgMemberFunctionRefExp* mfuncRef = isSgMemberFunctionRefExp(binOp->get_rhs_operand_i());
22379 ROSE_ASSERT (mfuncRef);
22380 SgMemberFunctionDeclaration * mfuncDecl = isSgMemberFunctionSymbol (mfuncRef->get_symbol())->get_declaration();
22381 ROSE_ASSERT (mfuncDecl);
22382 SgInitializedNamePtrList nameList = mfuncDecl->get_args();
22383 //TODO tolerate typedef chains
22384 if (isSgReferenceType(nameList[param_index]->get_type()))
22385 {
22386 result = true;
22387 }
22388 }
22389
22390 }
22391 }
22392 return result;
22393}
22394
22395
22397void SageInterface::collectUseByAddressVariableRefs (const SgStatement* s, std::set<SgVarRefExp* >& varSetB)
22398{
22399 Rose_STL_Container <SgNode*> var_refs = NodeQuery::querySubTree (const_cast<SgStatement *> (s), V_SgVarRefExp);
22400
22401 Rose_STL_Container<SgNode*>::iterator iter = var_refs.begin();
22402 for (; iter!=var_refs.end(); iter++)
22403 {
22404 SgVarRefExp* ref = isSgVarRefExp(*iter);
22405 ROSE_ASSERT(ref != NULL);
22406 ROSE_ASSERT(ref->get_parent() != NULL);
22407#if 0
22408 // case 1: ref is used as an operator for & (SgAddressofOp)
22409 // TODO tolerate possible type casting operations in between ?
22410 if (isSgAddressOfOp(ref->get_parent()))
22411 {
22412 varSetB.insert(ref);
22413 }
22414 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22415 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22416 {
22417 SgNode* grandparent = ref->get_parent()->get_parent();
22418 ROSE_ASSERT(grandparent);
22419 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22420 {
22421 // find which parameter ref is in SgExpressionPtrList
22422 int param_index =0;
22423 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22424 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22425 for (; iter!=expList.end(); iter++)
22426 {
22427 if (*iter == ref)
22428 break;
22429 else
22430 param_index++;
22431 }
22432 // find the parameter type of the corresponding function declaration
22433 SgFunctionRefExp * funcRef = isSgFunctionRefExp(isSgFunctionCallExp(grandparent)->get_function());
22434 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22435 SgInitializedNamePtrList nameList = funcDecl->get_args();
22436 //TODO tolerate typedef chains
22437 if (isSgReferenceType(nameList[param_index]->get_type()))
22438 {
22439 varSetB.insert(ref);
22440 }
22441 }
22442 }
22443#endif
22445 varSetB.insert(ref);
22446 }
22447}
22448
22449#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22451LivenessAnalysis * SageInterface::call_liveness_analysis(SgProject* project, bool debug/*=false*/)
22452{
22453 // We expect this function to be called multiple times but always return the result generated from the first execution.
22454 static LivenessAnalysis* liv = NULL; // one instance
22455 if (liv!=NULL)
22456 return liv;
22457
22458 static DFAnalysis * defuse = NULL; // only one instance
22459 // Prepare def-use analysis
22460 if (defuse==NULL)
22461 {
22462 ROSE_ASSERT(project != NULL);
22463 defuse = new DefUseAnalysis(project);
22464 }
22465
22466 ROSE_ASSERT(defuse != NULL);
22467 defuse->run(debug);
22468
22469 if (debug)
22470 defuse->dfaToDOT();
22471
22472 //Prepare variable liveness analysis
22473 liv = new LivenessAnalysis(debug,(DefUseAnalysis*)defuse);
22474 ROSE_ASSERT(liv != NULL);
22475
22476 std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions;
22477 NodeQuerySynthesizedAttributeType vars =
22478 NodeQuery::querySubTree(project, V_SgFunctionDefinition);
22479 NodeQuerySynthesizedAttributeType::const_iterator i;
22480 bool abortme=false;
22481 // run liveness analysis on each function body
22482 for (i= vars.begin(); i!=vars.end();++i)
22483 {
22484 SgFunctionDefinition* func = isSgFunctionDefinition(*i);
22485 ROSE_ASSERT(func != NULL);
22486 if (debug)
22487 {
22488 std::string name = func->class_name();
22489 string funcName = func->get_declaration()->get_qualified_name().str();
22490 cout<< " .. running liveness analysis for function: " << funcName << endl;
22491 }
22492 FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
22493 // propagate results to statement level
22494 liv->fixupStatementsINOUT(func);
22495 if (rem_source.getNode()!=NULL)
22496 dfaFunctions.push_back(rem_source);
22497 if (abortme)
22498 break;
22499 } // end for ()
22500 if(debug)
22501 {
22502 cout << "Writing out liveness analysis results into var.dot... " << endl;
22503 std::ofstream f2("var.dot");
22504 dfaToDot(f2, string("var"), dfaFunctions, (DefUseAnalysis*)defuse, liv);
22505 f2.close();
22506 }
22507 if (abortme) {
22508 cerr<<"Error: Liveness analysis is ABORTING ." << endl;
22509 ROSE_ABORT();
22510 }
22511 return liv;
22512 //return !abortme;
22513}
22514#endif
22515
22516#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22518void SageInterface::getLiveVariables(LivenessAnalysis * liv, SgForStatement* loop, std::set<SgInitializedName*>& liveIns, std::set<SgInitializedName*> & liveOuts)
22519{
22520 ROSE_ASSERT(liv != NULL);
22521 ROSE_ASSERT(loop != NULL);
22522 SgForStatement *forstmt = loop;
22523 std::vector<SgInitializedName*> liveIns0, liveOuts0; // store the original one
22524
22525 // Jeremiah's hidden constructor parameter value '2' to grab the node for forStmt's
22526 // Several CFG nodes are used for the same SgForStatement, only one of the is needed.
22527 // We have to check the full control flow graph to find all SgForStatement's nodes,
22528 // check the index numbers from 0 , find the one with two out edges (true, false)
22529 // The CFG node should have a caption like" <SgForStatement> @ 8: 1",
22530 // which means this is a CFG node for a for statement at source line 8, with an index 1.
22531 // For SgForStatement, there are 5 cfg nodes, 0 and 4 are for begin and end CFG nodes
22532 // 1: after init statement, 2: after test expression (the remaining one after filtering), 3: before increment
22533 CFGNode cfgnode(forstmt,2);
22534 FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (cfgnode);
22535 // This one does not return the one we want even its getNode returns the
22536 // right for statement
22537 //FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (forstmt->cfgForBeginning());
22538 ROSE_ASSERT(filternode.getNode()==forstmt);
22539
22540 // Check out edges
22541 vector<FilteredCFGEdge < IsDFAFilter > > out_edges = filternode.outEdges();
22542 ROSE_ASSERT(out_edges.size()==2);
22543 vector<FilteredCFGEdge < IsDFAFilter > >::iterator iter= out_edges.begin();
22544
22545 for (; iter!=out_edges.end();iter++)
22546 {
22547 FilteredCFGEdge < IsDFAFilter > edge= *iter;
22548 //SgForStatement should have two outgoing edges based on the loop condition
22549 // one true(going into the loop body) and one false (going out the loop)
22550 //x. Live-in (loop) = live-in (first-stmt-in-loop)
22551 if (edge.condition()==eckTrue)
22552 {
22553 SgNode* firstnode= edge.target().getNode();
22554 liveIns0 = liv->getIn(firstnode);
22555 // cout<<"Live-in variables for loop:"<<endl;
22556 for (std::vector<SgInitializedName*>::iterator iter = liveIns0.begin();
22557 iter!=liveIns0.end(); iter++)
22558 {
22559 // SgInitializedName* name = *iter;
22560 liveIns.insert(*iter);
22561 // cout<< name->get_qualified_name().getString()<<endl;
22562 }
22563 }
22564 //x. live-out(loop) = live-in (first-stmt-after-loop)
22565 else if (edge.condition()==eckFalse)
22566 {
22567 SgNode* firstnode= edge.target().getNode();
22568 liveOuts0 = liv->getIn(firstnode);
22569 // cout<<"Live-out variables for loop:"<<endl;
22570 for (std::vector<SgInitializedName*>::iterator iter = liveOuts0.begin();
22571 iter!=liveOuts0.end(); iter++)
22572 {
22573 // SgInitializedName* name = *iter;
22574 // cout<< name->get_qualified_name().getString()<<endl;
22575 liveOuts.insert(*iter);
22576 }
22577 }
22578 else
22579 {
22580 cerr<<"Unexpected CFG out edge type for SgForStmt!"<<endl;
22581 ROSE_ABORT();
22582 }
22583 } // end for (edges)
22584
22585}
22586#endif
22587
22588//Check if two references form an idiom like: x= x op expr, x = expr op x (except for subtraction)
22589static bool isAssignReduction (SgVarRefExp* ref_exp1, SgVarRefExp* ref_exp2, OmpSupport::omp_construct_enum& optype)
22590{
22591 bool isReduction = false;
22592 // Sanity check
22593 ROSE_ASSERT (ref_exp1!= NULL);
22594 ROSE_ASSERT (ref_exp2!= NULL);
22595 ROSE_ASSERT (ref_exp1-> get_symbol() == ref_exp2-> get_symbol());
22596 // must be scalar type
22597 ROSE_ASSERT (SageInterface::isScalarType(ref_exp1-> get_symbol()->get_type() ) );
22598
22601 if (stmt != stmt2) return false; // early return false;
22602
22603 // must be assignment statement using
22604 // x= x op expr, x = expr op x (except for subtraction)
22605 // one reference on left hand, the other on the right hand of assignment expression
22606 // the right hand uses associative operators +, *, -, &, ^ ,|, &&, ||
22607 SgExprStatement* exp_stmt = isSgExprStatement(stmt);
22608 if (exp_stmt && isSgAssignOp(exp_stmt->get_expression()))
22609 {
22610 SgExpression* assign_lhs=NULL, * assign_rhs =NULL;
22611 assign_lhs = isSgAssignOp(exp_stmt->get_expression())->get_lhs_operand();
22612 assign_rhs = isSgAssignOp(exp_stmt->get_expression())->get_rhs_operand();
22613 ROSE_ASSERT(assign_lhs && assign_rhs);
22614 // x must show up in both lhs and rhs in any order:
22615 // e.g.: ref1 = ref2 op exp or ref2 = ref1 op exp
22616 if (((assign_lhs==ref_exp1)&&SageInterface::isAncestor(assign_rhs,ref_exp2))
22617 ||((assign_lhs==ref_exp2)&&SageInterface::isAncestor(assign_rhs,ref_exp1)))
22618 {
22619 // assignment's rhs must match the associative binary operations
22620 // +, *, -, &, ^ ,|, &&, ||
22621 SgBinaryOp * binop = isSgBinaryOp(assign_rhs);
22622 if (binop!=NULL){
22623 SgExpression* op_lhs = binop->get_lhs_operand();
22624 SgExpression* op_rhs = binop->get_rhs_operand();
22625
22626 // double check that the binary expression has either ref1 or ref2 as one operand
22627 if( !((op_lhs==ref_exp1)||(op_lhs==ref_exp2))
22628 && !((op_rhs==ref_exp1)||(op_rhs==ref_exp2)))
22629 return false; // early return false;
22630
22631 bool isOnLeft = false; // true if it has form (refx op exp), instead (exp or refx)
22632 if ((op_lhs==ref_exp1)|| // TODO might have in between !!
22633 (op_lhs==ref_exp2))
22634 isOnLeft = true;
22635 switch (binop->variantT())
22636 {
22637 case V_SgAddOp:
22638 {
22639 optype = OmpSupport::e_reduction_plus;
22640 isReduction = true;
22641 break;
22642 }
22643 case V_SgMultiplyOp:
22644 {
22645 optype = OmpSupport::e_reduction_mul;
22646 isReduction = true;
22647 break;
22648 }
22649 case V_SgSubtractOp: // special handle here!!
22650 {
22651 optype = OmpSupport::e_reduction_minus;
22652 if (isOnLeft) // cannot allow (exp - x)a
22653 {
22654 isReduction = true;
22655 }
22656 break;
22657 }
22658 case V_SgBitAndOp:
22659 {
22660 optype = OmpSupport::e_reduction_bitand ;
22661 isReduction = true;
22662 break;
22663 }
22664 case V_SgBitXorOp:
22665 {
22666 optype = OmpSupport::e_reduction_bitxor;
22667 isReduction = true;
22668 break;
22669 }
22670 case V_SgBitOrOp:
22671 {
22672 optype = OmpSupport::e_reduction_bitor;
22673 isReduction = true;
22674 break;
22675 }
22676 case V_SgAndOp:
22677 {
22678 optype = OmpSupport::e_reduction_logand;
22679 isReduction = true;
22680 break;
22681 }
22682 case V_SgOrOp:
22683 {
22684 optype = OmpSupport::e_reduction_logor;
22685 isReduction = true;
22686 break;
22687 }
22688 default:
22689 break;
22690 }
22691 } // end matching associative operations
22692 }
22693 } // end if assignop
22694 return isReduction;
22695}
22696// A helper function for reduction recognition
22697// check if two references to the same variable form a reduction idiom using if-statement
22698// example 1: if (array[i]> maxV) maxV = array[i]
22699// example 2: if (array[i]< minV) minV = array[i]
22700// If it matches, return true and the reduction operator type
22701static bool isIfReduction(SgVarRefExp* ref1, SgVarRefExp* ref2, OmpSupport::omp_construct_enum& optype)
22702{
22703 bool matchStmt1 = false;
22704 bool matchStmt2 = false;
22705
22706 //TODO: ensure ref1, ref2 are ordered as pre-order manner in AST
22707 // SgExpression* reduction_var_ref = NULL;
22708 // SgExpression* source_var_ref = NULL; //array[i] is the source var ref
22709
22710 // Sanity check
22711 ROSE_ASSERT (ref1 != NULL);
22712 ROSE_ASSERT (ref2 != NULL);
22713 ROSE_ASSERT (ref1-> get_symbol() == ref2-> get_symbol());
22714 // must be scalar type
22715 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22716
22719
22720 //early return if the same stmt
22721 if (stmt1 == stmt2) return false;
22722
22723 // check stmt2 first. It is easier.
22724 // stmt2 should be an assignment stmt like:
22725 // reduction_variable = else;
22726 // minV = array[i];
22727 SgExpression* lhs2 = NULL;
22728 SgExpression* rhs2 = NULL;
22729 if (SageInterface::isAssignmentStatement (stmt2, &lhs2, &rhs2 ))
22730 {
22731 // lhs2 must be ref2
22732 if (lhs2 == ref2 )
22733 {
22734 matchStmt2 = true;
22735 // reduction_var_ref = lhs2;
22736 // source_var_ref= rhs2;
22737 }
22738 } // end assignment stmt
22739
22740 // stmt1 should be a if-stmt's conditional expression stmt
22741 // and its body should be stmt2
22742 if (SgExprStatement* if_cond_stmt = isSgExprStatement(stmt1))
22743 {
22744 bool matchBody = false;
22745 bool matchCondition= false;
22746 if (SgIfStmt * if_stmt = isSgIfStmt (if_cond_stmt->get_parent()) )
22747 {
22748 if (SgStatement* body = if_stmt->get_true_body())
22749 {
22750 if (SgBasicBlock* block = isSgBasicBlock (body))
22751 {
22752 // stmt2 must be the only child of the if true body
22753 ROSE_ASSERT(stmt2 != NULL);
22754 if ( ((block->get_statements()).size() == 1) && stmt2->get_scope() == block )
22755 matchBody = true;
22756 }
22757 else
22758 {
22759 if (body == stmt2)
22760 matchBody = true;
22761 }
22762 } // body match test
22763
22764 // match condition SgExprStatement ref1 SgLessThanOp source_var
22765 if (SgExprStatement* cond_exp_stmt = isSgExprStatement (if_stmt->get_conditional()) )
22766 {
22767 SgExpression* cond_exp = cond_exp_stmt->get_expression();
22768 if (SgBinaryOp * binop = isSgBinaryOp (cond_exp))
22769 {
22770 if (ref1 == binop->get_lhs_operand_i())
22771 {
22772 // minV > array[i] ;
22773 if (isSgLessThanOp (binop))
22774 {
22775 optype = OmpSupport::e_reduction_max;
22776 matchCondition= true;
22777 }
22778 else if (isSgGreaterThanOp(binop))
22779 {
22780 optype = OmpSupport::e_reduction_min;
22781 matchCondition= true;
22782 }
22783 }
22784 else if ( ref1 == binop->get_rhs_operand_i() )
22785 {
22786 // array[i] < minV
22787 if (isSgLessThanOp (binop))
22788 {
22789 optype = OmpSupport::e_reduction_min;
22790 matchCondition= true;
22791 }
22792 else if (isSgGreaterThanOp(binop))
22793 {
22794 optype = OmpSupport::e_reduction_max;
22795 matchCondition= true;
22796 }
22797 }
22798 } // end if binary op
22799 // TODO the source_var should match the source_var from stmt2
22800 }
22801 }
22802 matchStmt1 = matchBody && matchCondition;
22803 } // end if-stmt
22804
22805
22806 return (matchStmt2 && matchStmt1);
22807}
22808
22809// check if a var ref is a form of
22810// --x, x--, ++x, x++
22811// x+= .., x-= ..., etc.
22812// The reduction variable appears only once in the reduction idiom.
22813static bool isSingleAppearanceReduction(SgVarRefExp* ref1, OmpSupport::omp_construct_enum& optype )
22814{
22815 bool isReduction = false;
22816
22817 ROSE_ASSERT (ref1 != NULL);
22818 // must be scalar type
22819 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22820
22822
22823 if (isSgExprStatement(stmt))
22824 {
22825 SgExpression* exp = isSgExprStatement(stmt)->get_expression();
22826 SgExpression* binop = isSgBinaryOp(exp);
22827 if (isSgPlusPlusOp(exp)) // x++ or ++x
22828 { // Could have multiple reduction clause with different operators!!
22829 // So the variable list is associated with each kind of operator
22830 optype = OmpSupport::e_reduction_plus;
22831 isReduction = true;
22832 }
22833 else if (isSgMinusMinusOp(exp)) // x-- or --x
22834 {
22835 optype = OmpSupport::e_reduction_minus;
22836 isReduction = true;
22837 }
22838 else
22839 // x binop= expr where binop is one of + * - & ^ |
22840 // x must be on the left hand side
22841 if (binop!=NULL) {
22842 SgExpression* lhs= isSgBinaryOp(exp)->get_lhs_operand ();
22843 if (lhs==ref1)
22844 {
22845 switch (exp->variantT())
22846 {
22847 case V_SgPlusAssignOp:
22848 {
22849 optype = OmpSupport::e_reduction_plus;
22850 isReduction = true;
22851 break;
22852 }
22853 case V_SgMultAssignOp:
22854 {
22855 optype = OmpSupport::e_reduction_mul;
22856 isReduction = true;
22857 break;
22858 }
22859 case V_SgMinusAssignOp:
22860 {
22861 optype = OmpSupport::e_reduction_minus;
22862 isReduction = true;
22863 break;
22864 }
22865 case V_SgAndAssignOp:
22866 {
22867 optype = OmpSupport::e_reduction_bitand;
22868 isReduction = true;
22869 break;
22870 }
22871 case V_SgXorAssignOp:
22872 {
22873 optype = OmpSupport::e_reduction_bitxor;
22874 isReduction = true;
22875 break;
22876 }
22877 case V_SgIorAssignOp:
22878 {
22879 optype = OmpSupport::e_reduction_bitor;
22880 isReduction = true;
22881 break;
22882 }
22883 default:
22884 break;
22885 } // end
22886 }// end if on left side
22887 }
22888 }
22889 return isReduction;
22890}
22891
22893/* This code is refactored from project/autoParallelization/autoParSupport.C
22894 std::vector<SgInitializedName*>
22895 RecognizeReduction(SgNode *loop, OmpSupport::OmpAttribute* attribute, std::vector<SgInitializedName*>& candidateVars/)
22896 * Algorithms:
22897 * for each scalar candidate which are both live-in and live-out for the loop body
22898 * (We don't use liveness analysis here for simplicity)
22899 * and which is not the loop invariant variable (loop index).
22900 * Consider those with only 1 or 2 references
22901 * 1 reference
22902 * the operation is one of x++, ++x, x--, --x, x binop= expr
22903 * 2 references belonging to the same operation
22904 * operations: one of x= x op expr, x = expr op x (except for subtraction)
22905 * The reduction description from the OpenMP 3.0 specification.
22906 * x is not referenced in exp
22907 * expr has scalar type (no array, objects etc)
22908 * x: scalar only, aggregate types (including arrays), pointer types and reference types may not appear in a reduction clause.
22909 * op is not an overloaded operator, but +, *, -, &, ^ ,|, &&, ||
22910 * binop is not an overloaded operator, but: +, *, -, &, ^ ,|
22911 */
22912void SageInterface::ReductionRecognition(SgForStatement* loop, std::set< std::pair <SgInitializedName*, OmpSupport::omp_construct_enum > > & results)
22913{
22914 //x. Collect variable references of scalar types as candidates, excluding loop index
22915 SgInitializedName* loopindex;
22916 if (!(isCanonicalForLoop(loop, &loopindex)))
22917 {
22918// cerr<<"Skip reduction recognition for non-canonical for loop"<<endl;
22919 return;
22920 }
22921 std::set<SgInitializedName*> candidateVars; // scalar variables used within the loop
22922 //Store the references for each scalar variable
22923 std::map <SgInitializedName*, vector<SgVarRefExp* > > var_references;
22924
22925 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(loop, V_SgVarRefExp);
22926 SgStatement* lbody= loop->get_loop_body();
22927 ROSE_ASSERT(lbody != NULL);
22928 Rose_STL_Container<SgNode*>::iterator iter = reflist.begin();
22929 for (; iter!=reflist.end(); iter++)
22930 {
22931 SgVarRefExp* ref_exp = isSgVarRefExp(*iter);
22932 SgInitializedName* initname= ref_exp->get_symbol()->get_declaration();
22933 // candidates are of scalar types and are not the loop index variable
22934 // And also should be live-in:
22935 // not declared locally (var_scope equal or lower than loop body )
22936 // or redefined (captured by ref count)
22937 SgScopeStatement* var_scope = initname->get_scope();
22938 ROSE_ASSERT(var_scope != NULL);
22939 if ((isScalarType(initname->get_type())) &&(initname !=loopindex)
22940 && !(SageInterface::isAncestor(lbody, var_scope)||(lbody==var_scope)))
22941 {
22942 candidateVars.insert(initname);
22943 var_references[initname].push_back(ref_exp);
22944 }
22945 }
22946
22947 //Consider variables referenced at most twice
22948 std::set<SgInitializedName*>::iterator niter=candidateVars.begin();
22949 for (; niter!=candidateVars.end(); niter++)
22950 {
22951 SgInitializedName* initname = *niter;
22952 bool isReduction = false;
22953 OmpSupport::omp_construct_enum optype;
22954 // referenced once only
22955 if (var_references[initname].size()==1)
22956 {
22957 mlog[Sawyer::Message::Common::DEBUG] << "Debug: SageInterface::ReductionRecognition() A candidate used once:"<<initname->get_name().getString()<<endl;
22958 SgVarRefExp* ref_exp = *(var_references[initname].begin());
22959 if (isSingleAppearanceReduction (ref_exp, optype))
22960 isReduction = true;
22961 }
22962 // referenced twice within a same statement
22963 else if (var_references[initname].size()==2)
22964 {
22965 mlog[Sawyer::Message::Common::DEBUG] << "Debug: A candidate used twice:"<<initname->get_name().getString()<<endl;
22966 SgVarRefExp* ref_exp1 = *(var_references[initname].begin());
22967 SgVarRefExp* ref_exp2 = *(++var_references[initname].begin());
22968 // TODO: recognize maxV = array[i]>maxV? array[i]:maxV // this can be normalized to if () stmt
22969 // TODO: recognize maxV = max (maxV, array[i])
22970 if (isAssignReduction (ref_exp1, ref_exp2, optype) || isIfReduction (ref_exp1, ref_exp2, optype) )
22971 {
22972 isReduction = true;
22973 }
22974
22975 }// end referenced twice
22976
22977 if (isReduction)
22978 results.insert(make_pair(initname,optype));
22979 }// end for ()
22980}
22981
22984{
22985 ROSE_ASSERT(r!=NULL);
22986#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22987 ConstantFolding::constantFoldingOptimization(r,false);
22988#endif
22989}
22990
22993{
22995 {
22996 public:
22997 virtual void visit (SgNode * n)
22998 {
22999 SgExpression* exp = isSgExpression(n);
23000 if (exp)
23001 {
23002 string u_name = generateUniqueName(exp,false)+"-"+exp->class_name();
23003 AstAttribute * name_attribute = new UniqueNameAttribute(u_name);
23004 ROSE_ASSERT (name_attribute != NULL);
23005 exp->addNewAttribute("UniqueNameAttribute",name_attribute);
23006 }
23007 }
23008 };
23009 visitorTraversal exampleTraversal;
23010 //Sriram FIX: should traverse using the traverse function
23011 // exampleTraversal.traverseInputFiles(project,preorder);
23012 exampleTraversal.traverse(project, preorder);
23013}
23014
23015
23016 //
23017 // wrap free-standing function body in another function
23018
23020 {
23021 ROSE_ASSERT(vardecl.get_variables().size());
23022
23023 return *vardecl.get_variables().front();
23024 }
23025
23026#if 0
23027 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23028 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23029
23037 static
23039 cloneParameterList(const SgFunctionParameterList& params, SgFunctionDefinition* fundef = NULL)
23040 {
23041 namespace SB = SageBuilder;
23042
23043 SgFunctionParameterList& copy = *SB::buildFunctionParameterList();
23044 const SgInitializedNamePtrList& orig_decls = params.get_args();
23045
23046 std::transform( orig_decls.begin(), orig_decls.end(), sg::sage_inserter(copy), sg::InitNameCloner(copy, fundef) );
23047
23048 return copy;
23049 }
23050#endif
23051
23052#if 0
23053 // DQ (2/16/2017): This is a static function that is defined but not used in this file (compiler waring).
23054
23056 static
23057 void swapDefiningElements(SgFunctionDeclaration& ll, SgFunctionDeclaration& rr)
23058 {
23059 // swap definitions
23060 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_definition, &SgFunctionDeclaration::set_definition);
23061 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_parameterList, &SgFunctionDeclaration::set_parameterList);
23062
23063 // \todo do we need to swap also exception spec, decorator_list, etc. ?
23064 }
23065#endif
23066
23067#if 0
23068 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23069 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23070
23071 std::pair<SgStatement*, SgInitializedName*>
23072 SageInterface::wrapFunction(SgFunctionDeclaration& definingDeclaration, SgName newName)
23073 {
23074 namespace SB = SageBuilder;
23075
23076 // handles freestanding functions only
23077 ROSE_ASSERT(typeid(SgFunctionDeclaration) == typeid(definingDeclaration));
23078 ROSE_ASSERT(definingDeclaration.get_definingDeclaration() == &definingDeclaration);
23079
23080 // clone function parameter list
23081 SgFunctionParameterList& param_list = cloneParameterList(*definingDeclaration.get_parameterList());
23082
23083 // create new function definition/declaration in the same scope
23084 SgScopeStatement* containing_scope = definingDeclaration.get_scope();
23085 SgType* result_type = definingDeclaration.get_type()->get_return_type();
23086 SgExprListExp* decorators = deepCopy( definingDeclaration.get_decoratorList() );
23087
23088 // DQ (4/9/2015): Suggested fix for this function.
23089 // SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope, decorators);
23090 SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope);
23091
23092 SgFunctionDefinition* wrapperdef = wrapperfn->get_definition();
23093 ROSE_ASSERT(wrapperdef);
23094
23095 // copy the exception specification
23096 wrapperfn->set_exceptionSpecification(definingDeclaration.get_exceptionSpecification());
23097
23098 // swap the original's function definition w/ the clone's function def
23099 // and the original's func parameter list w/ the clone's parameters
23100 swapDefiningElements(definingDeclaration, *wrapperfn);
23101
23102 // call original function from within the defining decl's body
23103 SgBasicBlock* body = wrapperdef->get_body();
23104 SgExprListExp* args = SB::buildExprListExp();
23105 SgInitializedNamePtrList& param_decls = param_list.get_args();
23106
23107 std::transform( param_decls.begin(), param_decls.end(), sg::sage_inserter(*args), sg::VarRefBuilder(*wrapperdef) );
23108
23109 SgFunctionCallExp* callWrapped = SB::buildFunctionCallExp( newName, result_type, args, body );
23110 SgInitializedName* resultName = NULL;
23111 SgStatement* callStatement = NULL;
23112
23113 // \todo skip legal qualifiers that could be on top of void
23114 if (!isSgTypeVoid(result_type))
23115 {
23116 // add call to original function and assign result to variable
23117 SgVariableDeclaration* res = SB::buildVariableDeclaration( "res", result_type, SB::buildAssignInitializer(callWrapped), body );
23118 SgVarRefExp* resref = SB::buildVarRefExp( res );
23119
23120 appendStatement(res, body);
23121
23122 // add return statement, returning result
23123 resultName = &getFirstVariable(*res);
23124 callStatement = res;
23125
23126 appendStatement(SB::buildReturnStmt(resref), body);
23127 }
23128 else
23129 {
23130 // add function call statement to original function
23131 callStatement = SB::buildExprStatement(callWrapped);
23132 appendStatement(callStatement, body);
23133 }
23134
23135 ROSE_ASSERT(callStatement);
23136
23137 // create non defining declaration
23138 SgExprListExp* decorator_proto = deepCopy( decorators );
23139 SgFunctionDeclaration* wrapperfn_proto = SB::buildNondefiningFunctionDeclaration(wrapperfn, containing_scope, decorator_proto);
23140
23141 // add the new functions at the proper location of the surrounding scope
23142 insertStatementBefore(&definingDeclaration, wrapperfn_proto);
23143 insertStatementAfter (&definingDeclaration, wrapperfn);
23144
23145 return std::make_pair(callStatement, resultName);
23146 }
23147#endif
23148
23149 //
23150 // flatten C/C++ array dimensions
23151 namespace
23152 {
23153 struct VarrefBuilder
23154 {
23155 virtual SgVarRefExp* get() const = 0;
23156
23157 static
23158 SgVarRefExp* build(const SgVarRefExp& n)
23159 {
23160 return SageInterface::deepCopy(&n);
23161 }
23162
23163 static
23165 {
23166 SgScopeStatement* scope = sg::ancestor<SgStatement>(n).get_scope();
23167
23168 return SageBuilder::buildVarRefExp(&n, scope);
23169 }
23170 };
23171
23172 template <class AstNode>
23173 struct VarrefCreator : VarrefBuilder
23174 {
23175 AstNode& origin;
23176
23177 explicit
23178 VarrefCreator(AstNode& orig)
23179 : origin(orig)
23180 {}
23181
23182 SgVarRefExp* get() const { return VarrefBuilder::build(origin); }
23183 };
23184
23185 template <class AstNode>
23186 VarrefCreator<AstNode>
23187 varrefCreator(AstNode& n)
23188 {
23189 return VarrefCreator<AstNode>(n);
23190 }
23191
23192 SgExpression* create_mulop(SgExpression* lhs, const SgExpression* rhs)
23193 {
23194 namespace SB = SageBuilder;
23195 namespace SI = SageInterface;
23196
23197 // we own the lhs (intermediate result),
23198 // but we do not own the rhs (another top-level expression)
23199 return SB::buildMultiplyOp(lhs, SI::deepCopy(rhs));
23200 }
23201
23202 std::pair<std::vector<SgExpression*>, SgType*>
23203 get_C_array_dimensions_aux(const SgArrayType& arr_type)
23204 {
23205 namespace SB = SageBuilder;
23206 namespace SI = SageInterface;
23207
23208 const SgArrayType* arrtype = &arr_type;
23209 std::vector<SgExpression*> indices;
23210 SgType* undertype = NULL;
23211
23212 // \todo when get_index() does not return a nullptr anymore
23213 // the condition can be removed
23214 if (arrtype->get_index() == NULL)
23215 {
23216 indices.push_back(SB::buildNullExpression());
23217 undertype = arrtype->get_base_type();
23218 arrtype = isSgArrayType(undertype);
23219 }
23220
23221 while (arrtype)
23222 {
23223 SgExpression* indexexpr = arrtype->get_index();
23224 ROSE_ASSERT(indexexpr);
23225
23226 indices.push_back(SI::deepCopy(indexexpr));
23227 undertype = arrtype->get_base_type();
23228 arrtype = isSgArrayType(undertype);
23229 }
23230
23231 ROSE_ASSERT((!indices.empty()) && undertype);
23232 return std::make_pair(indices, undertype);
23233 }
23234
23236 std::vector<SgExpression*>
23237 get_C_array_dimensions_aux(const SgArrayType& arrtype, const VarrefBuilder& varrefBuilder)
23238 {
23239 namespace SB = SageBuilder;
23240
23241 std::pair<std::vector<SgExpression*>, SgType*> res = get_C_array_dimensions_aux(arrtype);
23242 const std::vector<SgExpression*>::iterator first = res.first.begin();
23243
23244 // if the first dimension was open, create the expression for it
23245 if (isSgNullExpression(*first))
23246 {
23247 // handle implicit first dimension for array initializers
23248 // for something like
23249 // int p[][2][3] = {{{ 1, 2, 3 }, { 4, 5, 6 }}}
23250 // we can calculate the first dimension as
23251 // sizeof( p ) / ( sizeof( int ) * 2 * 3 )
23252
23253 const std::vector<SgExpression*>::iterator aa = first+1;
23254 const std::vector<SgExpression*>::iterator zz = res.first.end();
23255
23256 SgExpression* sz_undertype = SB::buildSizeOfOp(res.second);
23257 SgExpression* denominator = std::accumulate(aa, zz, sz_undertype, create_mulop);
23258 SgSizeOfOp* sz_var = SB::buildSizeOfOp(varrefBuilder.get());
23259 SgExpression* sz = SB::buildDivideOp(sz_var, denominator);
23260
23261 std::swap(*first, sz);
23262 delete sz;
23263 }
23264
23265 return res.first;
23266 }
23267 }
23268
23269 std::vector<SgExpression*>
23271 {
23272 return get_C_array_dimensions_aux(arrtype).first;
23273 }
23274
23275 std::vector<SgExpression*>
23277 {
23278 return get_C_array_dimensions_aux(arrtype, varrefCreator(varref));
23279 }
23280
23281 std::vector<SgExpression*>
23283 {
23284 return get_C_array_dimensions_aux(arrtype, varrefCreator(initname));
23285 }
23286
23287// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23289 {
23290 public:
23291 set<unsigned int> sourceSequenceSet;
23292
23293 void visit ( SgNode* astNode );
23294 };
23295
23296// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23297void
23299 {
23300 Sg_File_Info* fileInfo = astNode->get_file_info();
23301 if (fileInfo != NULL)
23302 {
23303 unsigned int source_sequence_number = fileInfo->get_source_sequence_number();
23304#if 0
23305 printf ("In CollectSourceSequenceNumbers::visit(): source_sequence_number = %" PRIuPTR " \n",source_sequence_number);
23306#endif
23307 sourceSequenceSet.insert(source_sequence_number);
23308 }
23309 }
23310
23311// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23312set<unsigned int>
23314 {
23316
23317 traversal.traverse(astNode,preorder);
23318
23319 return traversal.sourceSequenceSet;
23320
23321 }
23322
23323/*Winnie, loop collapse, collapse nested for loops into one large for loop
23324 * return a SgExprListExp *, which will contain a list of SgVarRefExp * to variables newly created, inserted outside of the
23325 * loop scope, and used inside the loop scope.
23326 * If the target_loop comes with omp target directive, these variables should be added in map in clause in
23327 * transOmpCollpase(..) function in omp_lowering.cpp.
23328 *
23329 * The input loop pointer is changed to the generated collapsed loop after the transformation.
23330 *
23331 *
23332 * Loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
23333 *
23334 * to collapse two level of loops:
23335 * iteration_count_one= (ub1-lb1+1)%step1 ==0?(ub1-lb1+1)/step1: (ub1-lb1+1)/step1+1
23336 * iteration_count_two= (ub2-lb2+1)%step2 ==0?(ub2-lb2+1)/step2: (ub2-lb2+1)/step2+1
23337 * total_iteration_count = iteration_count_one * iteration_count_two
23338 *
23339 * Decide incremental/decremental loop by checking operator of test statement(ub), <=/>=, this is done in isCanonicalForLoop()
23340 *
23341 * Example 1:
23342 * for (int i=lb2;i<ub2;i+=inc2) //incremental
23343 * {
23344 * for (int j=lb1;j>ub1;i+=inc1) //decremental
23345 * {
23346 * for (int l=lb2;l<ub2;l+=inc2) //incremental
23347 * {
23348 * a[i][j][l]=i+j+l;
23349 * }
23350 * }
23351 * }
23352 *
23353 *==> translated output code ==>
23354 * int i_nom_1_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23355 * 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;
23356 * int l_nom_3_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23357 * int final_total_iters = 1 * i_nom_1_total_iters* j_nom_2_total_iters* l_nom_3_total_iters;
23358 * int i_nom_1_interval = j_nom_2_total_iters * (l_nom_3_total_iters* 1);
23359 * int j_nom_2_interval = l_nom_3_total_iters * 1;
23360 * int l_nom_3_interval = 1;
23361 *
23362 * for (int new_index = 0; new_index <= final_total_iters- 1; new_index += 1) {
23363 * i_nom_1 = new_index / i_nom_1_interval* inc2 + lb2;
23364 * int i_nom_1_remainder = new_index % i_nom_1_interval;
23365 * j_nom_2 = -(i_nom_1_remainder / j_nom_2_interval* (inc1 * -1)) + lb1;
23366 * l_nom_3 = i_nom_1_remainder % j_nom_2_interval* inc2 + lb2;
23367 * a[i_nom_1][j_nom_2][l_nom_3] = i_nom_1 + j_nom_2 + l_nom_3;
23368 * }
23369 *
23370 * Example 2 with concrete numbers:
23371 *
23372 * // collapse the following two level of for loops:
23373 * for (i=1; i<=9; i+=1) //incremental for loop
23374 * {
23375 * for(j=10; j>=1; j+=-2) //decremental for loop
23376 * {
23377 * a[i][j]=i+j;
23378 * }
23379 * }
23380 * // it becomes
23381 * // total iteration count = ((9 - 1 + 1)/1) * ((10 - 1 + 1)/2) = 45
23382 * // ub = 45
23383 * // lb = 0
23384 *
23385 * int i_nom_1_total_iters = 9;
23386 * int j_nom_1_total_iters = 5; // 10 % (-2 * -1) == 0 ? 10 / (-2 * -1) : 10 /(-2 * -1) + 1;
23387 * int final_total_iters = 45; // i_nom_1_total_iters * j_nom_2_total_iters;
23388 *
23389 * int i_nom_1_interval = 5;
23390 *
23391 * for (z=0; z<=44; z+=1)
23392 * {
23393 * i_nom_1 = z / 5 + 1;
23394 * j_nom_2 = -(z % 5 * 2) + 10;
23395 * a[i_nom_1][j_nom_2]=i_nom_1 + j_nom_2;
23396 * }
23397 * // for the generated loop, a few compiler generated variables are introduced
23398 * final_total_iters for the collapsed loop
23399 * i_interval for each of the n-1 loops
23400 **
23401*/
23402
23403#ifndef USE_ROSE
23405{
23406#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23407 //Handle 0 and 1, which means no collapsing at all
23408 if (collapsing_factor <= 1)
23409 return NULL;
23410
23411 SgExprListExp * new_var_list = buildExprListExp(); //expression list contains all the SgVarRefExp * to variables that need to be added in the mapin clause
23412
23413 /*
23414 *step 1: grab the target loops' header information
23415 */
23416 SgForStatement *& target_loop = loop;
23417
23418 // we use global scope to help generate unique variable name later
23419 // local scope-based unique names may cause conflicts if the declarations are moved around (in OpenMP target data promotion)
23420 SgGlobal* global_scope = getGlobalScope (loop);
23421 ROSE_ASSERT (global_scope != NULL);
23422 SgInitializedName** ivar = new SgInitializedName*[collapsing_factor];
23423 SgExpression** lb = new SgExpression*[collapsing_factor];
23424 SgExpression** ub = new SgExpression*[collapsing_factor];
23425 SgExpression** step = new SgExpression*[collapsing_factor];
23426 SgStatement** orig_body = new SgStatement*[collapsing_factor];
23427
23428 SgExpression** total_iters = new SgExpression*[collapsing_factor]; //Winnie, the real iteration counter in each loop level
23429 SgExpression** interval = new SgExpression*[collapsing_factor]; //Winnie, this will be used to calculate i_nom_1_remainder
23430 bool *isPlus = new bool[collapsing_factor]; //Winnie, a flag indicates incremental or decremental for loop
23431
23432
23433 //Winnie, get loops info first
23434 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(target_loop,V_SgForStatement);
23435 ROSE_ASSERT(loops.size()>=collapsing_factor);
23436
23437 SgForStatement* temp_target_loop = NULL;
23438 SgExpression* temp_range_exp = NULL; //Raw iteration range
23439 SgExpression* temp_range_d_step_exp = NULL; //temp_range_exp / step[i]
23440 SgExpression* temp_condition_1 = NULL; //Check whether temp_range_exp % step[i] == 0
23441 SgExpression* temp_total_iter = NULL;
23442 SgExpression* ub_exp = buildIntVal(1); //Winnie, upbound
23443
23444 /*
23445 * get lb, ub, step information for each level of the loops
23446 * ub_exp is the final iterantion range(starting from 0) after loop collapsing
23447 * total_iters[i], = (ub[i] - lb[i] + 1)/step[i] is the total iter num in each level of loop before loop collapsing
23448 */
23449
23450 SgStatement* parent = isSgStatement(getScope(target_loop)->get_parent()); //Winnie, the scope that include target_loop
23451 ROSE_ASSERT(getScope(target_loop)->get_parent()!= NULL);
23452
23453 SgScopeStatement* scope = isSgScopeStatement(parent); //Winnie, the scope that include target_loop
23454
23455 while(scope == NULL)
23456 {
23457 parent = isSgStatement(parent->get_parent());
23458 scope = isSgScopeStatement(parent);
23459 }
23460
23461 SgStatement* insert_target = findLastDeclarationStatement(scope);
23462 if (insert_target != NULL)
23463 insert_target = getNextStatement(insert_target);
23464 else
23465 insert_target = getFirstStatement(scope);
23466
23467 ROSE_ASSERT(scope != NULL);
23468
23469
23470 for(size_t i = 0; i < collapsing_factor; i ++)
23471 {
23472 temp_target_loop = loops[i];
23473
23474 // normalize the target loop first // adjust to numbering starting from 0
23475 forLoopNormalization(temp_target_loop);
23476
23477 if (!isCanonicalForLoop(temp_target_loop, &ivar[i], &lb[i], &ub[i], &step[i], &orig_body[i], &isPlus[i]))
23478 {
23479 cerr<<"Error in SageInterface::loopCollapsing(): target loop is not canonical."<<endl;
23480 dumpInfo(target_loop);
23481
23482 // release memory
23483 delete[] ivar;
23484 delete[] lb;
23485 delete[] ub;
23486 delete[] step;
23487 delete[] orig_body;
23488 delete[] total_iters;
23489 delete[] interval;
23490 delete[] isPlus;
23491
23492 return NULL;
23493 }
23494
23495 ROSE_ASSERT(ivar[i]&& lb[i] && ub[i] && step[i]);
23496
23497
23498//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]
23499 if(isPlus[i] == true)
23500 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(ub[i]), copyExpression(lb[i])), buildIntVal(1));
23501 else{
23502 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(lb[i]), copyExpression(ub[i])), buildIntVal(1));
23503 step[i] = buildMultiplyOp(step[i], buildIntVal(-1));
23504 }
23505 temp_range_d_step_exp = buildDivideOp(temp_range_exp,copyExpression(step[i]));//(ub[i]-lb[i]+1)/step[i]
23506
23507 temp_condition_1 = buildEqualityOp(buildModOp(copyExpression(temp_range_exp),copyExpression(step[i])),buildIntVal(0)); //(ub[i]-lb[i]+1)%step[i] ==0
23508
23509 temp_total_iter = buildConditionalExp(temp_condition_1,temp_range_d_step_exp, buildAddOp(copyExpression(temp_range_d_step_exp),buildIntVal(1)));
23510
23511 //build variables to store iteration numbers in each loop, simplify the calculation of "final_total_iters"
23512 //insert the new variable (store real iteration number of each level of the loop) before the target loop
23513 string iter_var_name= "_total_iters";
23514 //iter_var_name = ivar[i]->get_name().getString() + iter_var_name + generateUniqueName(temp_total_iter, false);
23515 iter_var_name = "__"+ivar[i]->get_name().getString() + iter_var_name+ generateUniqueVariableName (global_scope,"");
23516 SgVariableDeclaration* total_iter = buildVariableDeclaration(iter_var_name, buildIntType(), buildAssignInitializer(temp_total_iter, buildIntType()), scope);
23517 insertStatementBefore(insert_target, total_iter);
23518 constantFolding (total_iter);
23519 total_iters[i] = buildVarRefExp(iter_var_name, scope);
23520 ub_exp = buildMultiplyOp(ub_exp, total_iters[i]); //Winnie, build up the final iteration range
23521 }
23522
23523
23524 /*
23525 * step 2: build new variables (new_index, final_total_iters, remainders...) for the new loop
23526 */
23527
23528 /*Winnie, build another variable to store final total iteration counter of the loop after collapsing*/
23529 //string final_iter_counter_name = "final_total_iters" + generateUniqueName(ub_exp, false);
23530 string final_iter_counter_name = "__final_total_iters" + generateUniqueVariableName(global_scope,"");
23531 SgVariableDeclaration * final_total_iter = buildVariableDeclaration(final_iter_counter_name, buildIntType(), buildAssignInitializer(copyExpression(ub_exp), buildIntType()), scope);
23532 insertStatementBefore(insert_target, final_total_iter);
23533 ub_exp = buildVarRefExp(final_iter_counter_name, scope);
23534 new_var_list->append_expression(isSgVarRefExp(ub_exp));
23535
23536 /*Winnie, interval[i] will make the calculation of remainders simpler*/
23537 for(unsigned int i = 0; i < collapsing_factor; i++)
23538 {
23539 interval[i] = buildIntVal(1);
23540 for(unsigned int j = collapsing_factor - 1; j > i; j--)
23541 {
23542 interval[i] = buildMultiplyOp(total_iters[j], interval[i]);
23543 }
23544 //string interval_name = ivar[i]->get_name().getString() + "_interval" + generateUniqueName(interval[i], false);
23545 string interval_name = "__"+ ivar[i]->get_name().getString() + "_interval" + generateUniqueVariableName (global_scope,"");
23546 SgVariableDeclaration* temp_interval = buildVariableDeclaration(interval_name, buildIntType(), buildAssignInitializer(copyExpression(interval[i]), buildIntType()), scope);
23547 insertStatementBefore(insert_target, temp_interval);
23548 interval[i] = buildVarRefExp(interval_name, scope);
23549 new_var_list->append_expression(isSgVarRefExp(interval[i]));
23550 }
23551
23552
23553 //Winnie, starting from here, we are dealing with variables inside loop, update scope
23554 scope = getScope(target_loop);
23555
23556 //Winnie, init statement of the loop header, copy the lower bound, we are dealing with a range, the lower bound should always be "0"
23557 //Winnie, declare a brand new var as the new index
23558 string ivar_name = "__collapsed_index"+ generateUniqueVariableName (global_scope,"");
23559 ROSE_ASSERT(insert_target != NULL);
23560 SgVariableDeclaration* new_index_decl = buildVariableDeclaration(ivar_name, buildIntType(), NULL, insert_target->get_scope());
23561 SgVariableSymbol * collapsed_index_symbol = getFirstVarSym (new_index_decl);
23562 insertStatementBefore(insert_target, new_index_decl);
23563 SgVarRefExp * clps_index_ref = buildVarRefExp(collapsed_index_symbol);
23564 new_var_list->append_expression(clps_index_ref);
23565
23566// SgVariableDeclaration* init_stmt = buildVariableDeclaration(ivar_name, buildIntType(), buildAssignInitializer(buildIntVal(0), buildIntType()), scope);
23567
23568
23569 SgBasicBlock* body = isSgBasicBlock(deepCopy(temp_target_loop->get_loop_body())); // normalized loop has a BB body
23570 ROSE_ASSERT(body != NULL);
23571 SgExpression* new_exp = NULL;
23572 SgExpression* remain_exp_temp = buildVarRefExp(ivar_name, scope);
23573 std::vector<SgStatement*> new_stmt_list;
23574
23575 SgExprStatement* assign_stmt = NULL;
23576
23577 /* Winnie
23578 * express old iterator variables (i_norm, j_norm ...) with new_index,
23579 * new_exp, create new expression for each of the iterators
23580 * i_nom_1 = (_new_index / interval[0])*step[0] + lb[0]
23581 * i_nom_1_remain_value = (_new_index % interval[0])*step[0] + lb[0], create a new var to store remain value
23582 * create a new var to store total_iters[i]
23583 */
23584 for(unsigned int i = 0; i < collapsing_factor - 1; i ++)
23585 {
23586 if(isPlus[i] == true)
23587 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]
23588 else
23589 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
23590
23591 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[i], scope), copyExpression(new_exp));
23592 new_stmt_list.push_back(assign_stmt);
23593 remain_exp_temp = buildModOp((remain_exp_temp), copyExpression(interval[i]));
23594
23595 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
23596 string remain_var_name= "_remainder";
23597 remain_var_name = "__"+ ivar[i]->get_name().getString() + remain_var_name;
23598 SgVariableDeclaration* loop_index_decl = buildVariableDeclaration(remain_var_name, buildIntType(), buildAssignInitializer(remain_exp_temp, buildIntType()), scope);
23599 remain_exp_temp = buildVarRefExp(remain_var_name, scope);
23600 new_stmt_list.push_back(loop_index_decl);
23601 }
23602 new_exp = NULL;
23603 }
23604
23605//Winnie, the inner most loop, iter
23606 if(isPlus[collapsing_factor - 1] == true)
23607 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1]), lb[collapsing_factor - 1]));
23608 else
23609 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMinusOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1])), lb[collapsing_factor - 1]));
23610 new_stmt_list.push_back(assign_stmt);
23611 prependStatementList(new_stmt_list, body);
23612
23613 /*
23614 * step 3: build the new loop, new step is always 1, disregard value of step[i]
23615 */
23616 SgExpression* incr_exp = buildPlusAssignOp(buildVarRefExp(ivar_name, scope), buildIntVal(1));
23617
23618 //Winnie, build the new conditional expression/ub
23619 SgExprStatement* cond_stmt = NULL;
23620 ub_exp = buildSubtractOp(ub_exp, buildIntVal(1));
23621 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar_name,scope),copyExpression(ub_exp)));
23622 ROSE_ASSERT(cond_stmt != NULL);
23623
23624 SgForStatement* new_loop = buildForStatement(buildAssignStatement(clps_index_ref, buildIntVal(0)), cond_stmt,incr_exp, body); //Winnie, add in the new block!
23625 new_loop->set_parent(scope); //TODO: what's the correct parent?
23626
23627 replaceStatement(target_loop, new_loop);
23628
23629 target_loop = new_loop; //Winnie, so that transOmpLoop() can work on the collapsed loop
23630 // constant folding for the transformed AST
23631 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
23632
23633 delete [] ivar;
23634 delete [] lb;
23635 delete [] ub;
23636 delete [] step;
23637 delete [] orig_body;
23638 delete [] total_iters;
23639 delete [] interval;
23640 delete [] isPlus;
23641
23642 #endif
23643
23644 return new_var_list;
23645}
23646
23647
23648
23649bool
23651 {
23652 // DQ (3/4/2014): Added support for testing two trees for equivalents using the AST iterators.
23653
23654#ifndef USE_CMAKEx
23655 // DQ (3/8/2014): Make this conditionally compiled based on when CMake is not used because the libraries are not configured yet.
23656
23657 // This is AST container for the ROSE AST that will provide an iterator.
23658 // We want two iterators (one for the copy of the snippet and one for the
23659 // original snippet so that we can query the original snippet's AST
23660 // as we process each IR node of the AST for the copy of the snippet.
23661 // Only the copy of the snippet is inserted into the target AST.
23662 RoseAst ast_of_copy(tree1);
23663 RoseAst ast_of_original(tree2);
23664
23665 // printf ("ast_of_copy.size() = %" PRIuPTR " \n",ast_of_copy.size());
23666
23667 // Build the iterators so that we can increment thorugh both ASTs one IR node at a time.
23668 RoseAst::iterator i_copy = ast_of_copy.begin();
23669 RoseAst::iterator i_original = ast_of_original.begin();
23670
23671 // Iterate of the copy of the snippet's AST.
23672 while (i_copy != ast_of_copy.end())
23673 {
23674#if 0
23675 printf ("*i_copy = %p = %s \n",*i_copy,(*i_copy)->class_name().c_str());
23676 printf ("*i_original = %p = %s \n",*i_original,(*i_original)->class_name().c_str());
23677#endif
23678 // DQ (2/28/2014): This is a problem for some of the test codes (TEST store/load heap string [test7a] and [test7a])
23679 // ROSE_ASSERT((*i_copy)->variantT() == (*i_original)->variantT());
23680 if ((*i_copy)->variantT() != (*i_original)->variantT())
23681 {
23682#if 0
23683 printf ("ERROR: return from SageInterface::isStructurallyEquivalentAST(): (*i_copy)->variantT() != (*i_original)->variantT() \n");
23684#endif
23685#if 0
23686 printf ("Making this an error! \n");
23687 ROSE_ABORT();
23688#endif
23689 return false;
23690 }
23691
23692 i_copy++;
23693
23694 // Verify that we have not reached the end of the ast for the original (both the
23695 // copy and the original are the same structurally, and thus the same size).
23696 ROSE_ASSERT(i_original != ast_of_original.end());
23697 i_original++;
23698 }
23699
23700 // We have reached the end of both ASTs.
23701 ROSE_ASSERT(i_copy == ast_of_copy.end() && i_original == ast_of_original.end());
23702#endif
23703
23704 return true;
23705 }
23706
23707
23708#endif
23709
23711 SgForStatement * for_loop,
23712 SgVariableSymbol * & iterator,
23713 SgExpression * & lower_bound,
23714 SgExpression * & upper_bound,
23715 SgExpression * & stride
23716) {
23719
23720 iterator = NULL;
23721 lower_bound = NULL;
23722 upper_bound = NULL;
23723 stride = NULL;
23724
23725 SgForInitStatement * for_init_stmt = for_loop->get_for_init_stmt();
23726 const std::vector<SgStatement *> & init_stmts = for_init_stmt->get_init_stmt();
23727 assert(init_stmts.size() == 1);
23728 SgExprStatement * init_stmt = isSgExprStatement(init_stmts[0]);
23729 assert(init_stmt != NULL);
23730 SgExpression * init = init_stmt->get_expression();
23731
23732 SgAssignOp * assign_init = isSgAssignOp(init);
23733 assert(assign_init != NULL);
23734 SgVarRefExp * iterator_init_ref = isSgVarRefExp(assign_init->get_lhs_operand_i());
23735 assert(iterator_init_ref != NULL);
23736 iterator = iterator_init_ref->get_symbol();
23737 assert(iterator != NULL);
23738 lower_bound = assign_init->get_rhs_operand_i();
23739
23740 SgExprStatement * test_stmt = isSgExprStatement(for_loop->get_test());
23741 assert(test_stmt != NULL);
23742 SgExpression * test = test_stmt->get_expression();
23743 SgBinaryOp * bin_test = isSgBinaryOp(test);
23744 assert(bin_test);
23745
23746 SgExpression * lhs_exp = bin_test->get_lhs_operand_i();
23747 while (isSgCastExp(lhs_exp)) lhs_exp = ((SgCastExp *)lhs_exp)->get_operand_i();
23748 SgVarRefExp * lhs_var_ref = isSgVarRefExp(lhs_exp);
23749 bool lhs_it = (lhs_var_ref != NULL) && (lhs_var_ref->get_symbol() == iterator);
23750
23751 SgExpression * rhs_exp = bin_test->get_rhs_operand_i();
23752 while (isSgCastExp(rhs_exp)) rhs_exp = ((SgCastExp *)rhs_exp)->get_operand_i();
23753 SgVarRefExp * rhs_var_ref = isSgVarRefExp(rhs_exp);
23754#ifndef NDEBUG
23755 bool rhs_it = (rhs_var_ref != NULL) && (rhs_var_ref->get_symbol() == iterator);
23756
23757// DQ (4/21/2016): Replacing use of bitwise xor with something more approriate for logical types.
23758// Note that the xor logica operator does not exist in C/C++ and that this is a case of using the
23759// bitwise xor operator on boolean values (not a great idea). Note that logical "a xor b" is
23760// equivalent to "!a != !b" the use of "!" only make sure that the "!=" is applied to a boolean
23761// value. Since these are boolean typed values we can use "a != b", directly.
23762// assert(lhs_it xor rhs_it);
23763 assert(lhs_it != rhs_it);
23764#endif
23765
23766 upper_bound = lhs_it ? bin_test->get_rhs_operand_i() : bin_test->get_lhs_operand_i();
23767
23768 bool inclusive;
23769 bool reversed;
23770
23771 switch (test->variantT()) {
23772 case V_SgGreaterOrEqualOp:
23773 inclusive = lhs_it;
23774 reversed = lhs_it;
23775 break;
23776 case V_SgGreaterThanOp:
23777 inclusive = !lhs_it;
23778 reversed = lhs_it;
23779 break;
23780 case V_SgLessOrEqualOp:
23781 inclusive = lhs_it;
23782 reversed = !lhs_it;
23783 break;
23784 case V_SgLessThanOp:
23785 inclusive = !lhs_it;
23786 reversed = !lhs_it;
23787 break;
23788 case V_SgEqualityOp:
23789 case V_SgNotEqualOp:
23790 default:
23791 ROSE_ABORT();
23792 }
23793
23794 SgExpression * increment = for_loop->get_increment();
23795 switch (increment->variantT()) {
23796 case V_SgPlusPlusOp:
23797 assert(!reversed);
23798 stride = SageBuilder::buildIntVal(1);
23799 break;
23800 case V_SgMinusMinusOp:
23801 assert(reversed);
23802 stride = SageBuilder::buildIntVal(-1);
23803 break;
23804 case V_SgPlusAssignOp:
23805 {
23806 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23807#ifndef NDEBUG
23808 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23809 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23810#endif
23811 stride = bin_op->get_rhs_operand_i();
23812 break;
23813 }
23814 case V_SgMinusAssignOp:
23815 {
23816 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23817#ifndef NDEBUG
23818 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23819 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23820#endif
23821 stride = bin_op->get_rhs_operand_i();
23822 break;
23823 }
23824 case V_SgAssignOp:
23825 {
23826 SgAssignOp * assign_op = (SgAssignOp *)increment;
23827#ifndef NDEBUG
23828 SgVarRefExp * inc_assign_lhs = isSgVarRefExp(assign_op->get_lhs_operand_i());
23829 assert(inc_assign_lhs != NULL && inc_assign_lhs->get_symbol() == iterator);
23830#endif
23831 SgBinaryOp * inc_assign_rhs = isSgBinaryOp(assign_op->get_rhs_operand_i());
23832 assert(inc_assign_rhs != NULL);
23833 SgVarRefExp * inc_assign_rhs_lhs = isSgVarRefExp(inc_assign_rhs->get_lhs_operand_i());
23834 if (inc_assign_rhs_lhs != NULL && inc_assign_rhs_lhs->get_symbol() == iterator)
23835 stride = inc_assign_rhs->get_rhs_operand_i();
23836 SgVarRefExp * inc_assign_rhs_rhs = isSgVarRefExp(inc_assign_rhs->get_rhs_operand_i());
23837 if (inc_assign_rhs_rhs != NULL && inc_assign_rhs_rhs->get_symbol() == iterator)
23838 stride = inc_assign_rhs->get_lhs_operand_i();
23839 break;
23840 }
23841 default:
23842 ROSE_ABORT();
23843 }
23844
23845 // DQ (7/19/2015): Added braces to avoid compiler warning about ambigious "else" case.
23846 if (!inclusive)
23847 {
23848 if (reversed)
23849 upper_bound = SageBuilder::buildAddOp(upper_bound, SageBuilder::buildIntVal(1));
23850 else
23851 upper_bound = SageBuilder::buildSubtractOp(upper_bound, SageBuilder::buildIntVal(1));
23852 }
23853
23854 return true;
23855}
23856
23857//------------------------------------------------------------------------------
23858#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
23859//------------------------------------------------------------------------------
23860
23865 jstring temp_directory = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(::currentJavaTraversalClass, Rose::Frontend::Java::Ecj::getTempDirectoryMethod);
23866
23867 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_directory, NULL);
23868 ROSE_ASSERT(utf8);
23869 string directory_name = utf8;
23870 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_directory, utf8);
23871
23872 list<string> sourcepath = project -> get_Java_sourcepath();
23873 sourcepath.push_back(directory_name); // push it in the back because it should have lower priority
23874 project -> set_Java_sourcepath(sourcepath);
23875
23876 return directory_name;
23877}
23878
23879
23883void SageInterface::destroyTempDirectory(string directory_name) {
23884 string command = string("rm -fr ") + directory_name;
23885 int status = system(command.c_str());
23886 ROSE_ASSERT(status == 0);
23887}
23888
23889
23893SgFile* SageInterface::processFile(SgProject *project, string filename, bool unparse /* = false */) {
23894 //
23895 // Set up the new source file for processing "a la Rose".
23896 //
23897 project -> get_sourceFileNameList().push_back(filename);
23898 Rose_STL_Container<std::string> arg_list = project -> get_originalCommandLineArgumentList();
23899 arg_list.push_back(filename);
23900 Rose_STL_Container<string> fileList = CommandlineProcessing::generateSourceFilenames(arg_list, false);
23901 CommandlineProcessing::removeAllFileNamesExcept(arg_list, fileList, filename);
23902 int error_code = 0; // need this because determineFileType takes a reference "error_code" argument.
23903 SgFile *file = determineFileType(arg_list, error_code, project);
23904 SgSourceFile *sourcefile = isSgSourceFile(file);
23905 ROSE_ASSERT(sourcefile);
23906 sourcefile -> set_parent(project);
23907
23908 //
23909 // Insert the file into the list of files in the project.
23910 //
23911 project -> get_fileList_ptr() -> get_listOfFiles().push_back(sourcefile);
23912 ROSE_ASSERT(sourcefile == isSgSourceFile((*project)[filename]));
23913
23914 sourcefile -> build_Java_AST(arg_list, project -> get_originalCommandLineArgumentList());
23915
23916 if (! unparse) { // if we are not supposed to unparse this file,
23917 project -> get_fileList_ptr() -> get_listOfFiles().pop_back(); // remove it from the list of files in the project
23918 ROSE_ASSERT(sourcefile != isSgSourceFile((*project)[filename]));
23919 }
23920
23921 // DQ (7/2/2020): Added assertion (fails for snippet tests).
23922 ROSE_ASSERT(file->get_preprocessorDirectivesAndCommentsList() != NULL);
23923
23924 return file;
23925}
23926
23927
23932string SageInterface::preprocessPackage(SgProject *project, string package_name) {
23933 string command = "package " + package_name + ";";
23934
23935 //
23936 // Call the Java side to create an input file with the relevant package statement; translate the file and return the file name.
23937 //
23938 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23939 Rose::Frontend::Java::Ecj::createTempFileMethod,
23940 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23941
23942 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23943 ROSE_ASSERT(utf8);
23944 string filename = (string) utf8;
23945 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23946
23947 processFile(project, filename); // translate the file
23948
23949 return package_name;
23950}
23951
23952
23957string SageInterface::preprocessImport(SgProject *project, string import_string) {
23958 string command = "import " + import_string + ";";
23959
23960 //
23961 // Call the Java side to create an input file with the relevant import statement.
23962 //
23963 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23964 Rose::Frontend::Java::Ecj::createTempFileMethod,
23965 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23966
23967 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23968 ROSE_ASSERT(utf8);
23969 string filename = (string) utf8;
23970 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23971
23972 processFile(project, filename); // translate the file
23973
23974 return import_string;
23975}
23976
23977
23982SgFile* SageInterface::preprocessCompilationUnit(SgProject *project, string file_name, string file_content, bool unparse /* true */) {
23983 //
23984 // Call the Java side to create an input file with the relevant import statement.
23985 //
23986 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23987 Rose::Frontend::Java::Ecj::createTempNamedFileMethod,
23988 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_name.c_str()),
23989 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_content.c_str()));
23990
23991 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23992 ROSE_ASSERT(utf8);
23993 string filename = (string) utf8;
23994 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23995
23996 return processFile(project, filename, unparse); // translate the file and unparse it, if requested (unparse=true is the default).
23997}
23998
23999
24004 ROSE_ASSERT(scope);
24005 SgClassDefinition *package_definition = NULL;
24006 for (int index = 0, length = package_name.size(); index < length; index++) {
24007 int n;
24008 for (n = index; n < length; n++) {
24009 if (package_name[n] == '.') {
24010 break;
24011 }
24012 }
24013 string name = package_name.substr(index, n - index);
24014
24015 SgClassSymbol *package_symbol = scope -> lookup_class_symbol(name);
24016 if (package_symbol == NULL) { // package not found?
24017 return NULL;
24018 }
24019
24020 SgJavaPackageDeclaration *package_declaration = isSgJavaPackageDeclaration(package_symbol -> get_declaration() -> get_definingDeclaration());
24021 ROSE_ASSERT(package_declaration);
24022 package_definition = package_declaration -> get_definition();
24023 ROSE_ASSERT(package_definition);
24024 scope = package_definition;
24025
24026 index = n;
24027 }
24028
24029 return package_definition;
24030}
24031
24032
24036SgClassDefinition *SageInterface::findOrInsertJavaPackage(SgProject *project, string package_name, bool create_directory /* = false */) {
24037 SgGlobal *global_scope = project -> get_globalScopeAcrossFiles();
24038 SgClassDefinition *package_definition = findJavaPackage(global_scope, package_name);
24039 if (package_definition == NULL) { // try again after loading the package
24040 preprocessPackage(project, package_name);
24041
24042 //
24043 // If requested, Create the directory associated with this package_name.
24044 //
24045 if (create_directory) {
24046 Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24047 Rose::Frontend::Java::Ecj::createTempNamedDirectoryMethod,
24048 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(package_name.c_str()));
24049 }
24050
24051 package_definition = findJavaPackage(global_scope, package_name);
24052 }
24053
24054 return package_definition;
24055}
24056
24061 ROSE_ASSERT(package_definition);
24062 SgClassSymbol *class_symbol = package_definition -> lookup_class_symbol(class_name);
24063 SgClassDeclaration *class_declaration = (class_symbol == NULL
24064 ? NULL
24065 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24066 if ((! class_declaration) || (! class_declaration -> attributeExists("complete"))) { // class not available in the scope
24067 string qualified_name = package_definition -> get_qualified_name().getString() + "." + class_name;
24068 preprocessImport(project, qualified_name);
24069 class_symbol = package_definition -> lookup_class_symbol(class_name);
24070 }
24071
24072 class_declaration = (class_symbol == NULL
24073 ? NULL
24074 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24075
24076 return class_declaration;
24077}
24078
24079
24083SgClassDeclaration *SageInterface::findOrImportJavaClass(SgProject *project, string package_name, string class_name) {
24084 return findOrImportJavaClass(project, findOrInsertJavaPackage(project, package_name, false), class_name);
24085}
24086
24087
24092 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24093 ROSE_ASSERT(class_declaration);
24094 SgClassDefinition *scope = isSgClassDefinition(class_declaration -> get_scope());
24095 while (scope && (! isSgJavaPackageDeclaration(scope -> get_parent()))) {
24096 class_declaration = isSgClassDeclaration(scope -> get_parent());
24097 ROSE_ASSERT(class_declaration);
24098 scope = isSgClassDefinition(class_declaration -> get_scope());
24099 }
24100
24101 if (! scope) { // a local type !!!
24102 return NULL;
24103 }
24104
24105 string class_name = class_declaration -> get_name().getString();
24106 return findOrImportJavaClass(project, scope, class_name);
24107}
24108
24109
24114 ROSE_ASSERT(class_definition);
24116 ROSE_ASSERT(type_list);
24117 SgArrayType *string_array_type = getUniqueJavaArrayType(Rose::Frontend::Java::StringClassType, 1);
24118 ROSE_ASSERT(string_array_type);
24119 type_list -> append_argument(string_array_type);
24120
24121 // DQ (1/11/2020): Fixing support for C++11 l-value and r-value reference modifiers for member functions.
24122 // SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, 0);
24123 SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, /* mfunc_specifier */ 0);
24124
24125 SgFunctionSymbol *method_symbol = class_definition -> lookup_function_symbol("main", member_function_type);
24126 delete type_list;
24127 return (method_symbol == NULL ? NULL : isSgMemberFunctionDeclaration(method_symbol -> get_declaration()));
24128}
24129
24130
24135 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24136 ROSE_ASSERT(class_declaration);
24137 SgClassDefinition *class_definition = class_declaration -> get_definition();
24138 return findJavaMain(class_definition);
24139}
24140
24141//------------------------------------------------------------------------------
24142#endif // ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
24143//------------------------------------------------------------------------------
24144
24146// Essentially replace variable a with b.
24148{
24149 ROSE_ASSERT (old_sym != NULL);
24150 ROSE_ASSERT (new_sym != NULL);
24151 ROSE_ASSERT (old_sym != new_sym);
24152 ROSE_ASSERT (scope != NULL);
24153
24154 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVarRefExp);
24155 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
24156 {
24157 SgVarRefExp *vRef = isSgVarRefExp(*i);
24158 if (vRef->get_symbol() == old_sym)
24159 vRef->set_symbol(new_sym);
24160 }
24161}
24162
24163
24164// 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.
24169bool
24171 {
24172 bool result = true;
24173
24174 bool includingSelf = false;
24175 SgSourceFile* sourceFile = getEnclosingSourceFile(stmt,includingSelf);
24176
24177 if (sourceFile == NULL)
24178 {
24179 printf ("In SageInterface::statementCanBeTransformed(): sourceFile not found \n");
24180 }
24181
24182 // I think we can assert this!
24183 ROSE_ASSERT(sourceFile != NULL);
24184
24185 if (sourceFile != NULL && sourceFile->get_unparse_tokens() == true && sourceFile->get_unparseHeaderFiles() == true)
24186 {
24187 // Need to look up the source file name, find the SgIncludeFile, and check if statements from this file can be transformed.
24188 // 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.
24189 string source_filename = stmt->getFilenameString();
24190#if 0
24191 printf ("In SageInterface::statementCanBeTransformed(): source_filename = %s \n",source_filename.c_str());
24192 printf (" --- Rose::includeFileMapForUnparsing.size() = %zu \n",Rose::includeFileMapForUnparsing.size());
24193#endif
24194
24195 // DQ (11/5/2019): Using the edg_include_file_map instead (constructed in EDG/ROSE translation).
24196 if (EDG_ROSE_Translation::edg_include_file_map.find(source_filename) != EDG_ROSE_Translation::edg_include_file_map.end())
24197 {
24198 SgIncludeFile* include_file = EDG_ROSE_Translation::edg_include_file_map[source_filename];
24199 ROSE_ASSERT(include_file != NULL);
24200#if 0
24201 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");
24202#endif
24203 if (include_file->get_can_be_supported_using_token_based_unparsing() == false)
24204 {
24205#if 0
24206 printf ("NOTE: Transformations of this statement cannot be supported using the header file unparsing with token unparsing options! \n");
24207#endif
24208 result = false;
24209 }
24210 }
24211 else
24212 {
24213 // DQ (5/13/2021): I think that the default (returing true) will work well.
24214 // This is likely just the original input source file (not a header file).
24215#if 0
24216 printf ("Not found in Rose::includeFileMapForUnparsing: source_filename = %s \n",source_filename.c_str());
24217#endif
24218#if 0
24219 printf ("Exiting as a test! \n");
24220 ROSE_ABORT();
24221#endif
24222 }
24223
24224#if 0
24225 printf ("Error: In statementCanBeTransformed(): this might be an issue! \n");
24226 ROSE_ABORT();
24227#endif
24228 }
24229
24230 return result;
24231 }
24232
24233
24234//Note: this function is no longer used by decl move tool: we use copy and insert instead to support moving to multiple scopes
24237{
24238 ROSE_ASSERT (decl!= NULL);
24239 ROSE_ASSERT (target_scope != NULL);
24240 ROSE_ASSERT (target_scope != decl->get_scope());
24241
24242#if 0 // at this stage, we focus on legal move only, any scope adjustment should be done earlier!
24243 // Special handling for If-Stmt, may need to climb up one level of scope when:
24244 // two bodies of if uses the same variable, but cannot be pushed down into each body.
24245 // If-stmt will be the innermost common scope for the variable.
24246 // But we should not move the declaration to if-stmt. We can only move it to the parent scope of if-stmt.
24247 if (isSgIfStmt (target_scope))
24248 {
24249 target_scope = SageInterface::getEnclosingScope (target_scope, false);
24250 if (target_scope == )
24251 }
24252# endif
24253
24254 // Move the declaration
24255 //TODO: consider another way: copy the declaration, insert the copy, replace varRefExp, and remove (delete) the original declaration
24257
24258 switch (target_scope->variantT())
24259 {
24260 case V_SgBasicBlock:
24261 {
24262 SageInterface::prependStatement (decl, target_scope);
24263 break;
24264 }
24265#if 0 // this check should be done earlier before any side effects can happen
24266 case V_SgIfStmt:
24267 {
24268 // adjust to parent scope of if-stmt
24269 break;
24270 }
24271#endif
24272 case V_SgForStatement:
24273 {
24274 // we move int i; to be for (int i=0; ...);
24275 SgForStatement* stmt = isSgForStatement (target_scope);
24276 ROSE_ASSERT(stmt != NULL);
24277 SgStatementPtrList& stmt_list = stmt->get_init_stmt();
24278 // Try to match a pattern like for (i=0; ...) here
24279 // assuming there is only one assignment like i=0
24280 // We don't yet handle more complex cases
24281 if (stmt_list.size() !=1)
24282 {
24283 cerr<<"Error in moveVariableDeclaration(): only single init statement is handled for SgForStatement now."<<endl;
24284 ROSE_ASSERT (stmt_list.size() ==1);
24285 }
24286 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
24287 ROSE_ASSERT (exp_stmt != NULL);
24288 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
24289 ROSE_ASSERT (assign_op != NULL);
24290
24291 // remove the existing i=0; preserve its right hand operand
24293 stmt_list.clear();
24294 SageInterface::deepDelete (exp_stmt);
24295
24296 // modify the decl's rhs to be the new one
24299 if (init_name->get_initptr() != NULL)
24300 SageInterface::deepDelete (init_name->get_initptr());
24301 init_name->set_initptr(initor);
24302 initor->set_parent(init_name);
24303
24304 stmt_list.insert (stmt_list.begin(), decl );
24305 break;
24306 }
24307
24308 default:
24309 {
24310 cerr<<"Error. Unhandled target scope type:"<<target_scope->class_name()<<endl;
24311 ROSE_ASSERT (false);
24312 }
24313 }
24314
24315 //make sure the symbol is moved also since prependStatement() (in fact fixVariableDeclaration()) does not handle this detail.
24317 ROSE_ASSERT(sym != NULL);
24318 SgScopeStatement* orig_scope = sym->get_scope();
24319 if (orig_scope != target_scope)
24320 {
24321 // SageInterface::fixVariableDeclaration() cannot switch the scope for init name.
24322 // it somehow always reuses previously associated scope.
24324 init_name->set_scope(target_scope);
24325 SgName sname = sym->get_name();
24326 orig_scope->remove_symbol(sym);
24327 target_scope->insert_symbol(sname, sym);
24328 }
24329 // This is difficult since C++ variables have namespaces
24330 // Details are in SageInterface::fixVariableDeclaration()
24331 ROSE_ASSERT (target_scope->symbol_exists(sym));
24332}
24333
24334class SimpleExpressionEvaluator: public AstBottomUpProcessing <struct SageInterface::const_int_expr_t> {
24335 public:
24337 }
24338
24339 struct SageInterface::const_int_expr_t getValueExpressionValue(SgValueExp *valExp) {
24340 struct SageInterface::const_int_expr_t subtreeVal;
24341 subtreeVal.hasValue_ = true;
24342
24343 if (isSgIntVal(valExp)) {
24344 subtreeVal.value_ = isSgIntVal(valExp)->get_value();
24345 } else if (isSgLongIntVal(valExp)) {
24346 subtreeVal.value_ = isSgLongIntVal(valExp)->get_value();
24347 } else if (isSgLongLongIntVal(valExp)) {
24348 subtreeVal.value_ = isSgLongLongIntVal(valExp)->get_value();
24349 } else if (isSgShortVal(valExp)) {
24350 subtreeVal.value_ = isSgShortVal(valExp)->get_value();
24351 } else if (isSgUnsignedIntVal(valExp)) {
24352 subtreeVal.value_ = isSgUnsignedIntVal(valExp)->get_value();
24353 } else if (isSgUnsignedLongVal(valExp)) {
24354 subtreeVal.value_ = isSgUnsignedLongVal(valExp)->get_value();
24355 } else if (isSgUnsignedLongLongIntVal(valExp)) {
24356 subtreeVal.value_ = isSgUnsignedLongLongIntVal(valExp)->get_value();
24357 } else if (isSgUnsignedShortVal(valExp)) {
24358 subtreeVal.value_ = isSgUnsignedShortVal(valExp)->get_value();
24359 }
24360 return subtreeVal;
24361 }
24362
24363 struct SageInterface::const_int_expr_t evaluateVariableReference(SgVarRefExp *vRef) {
24364 if (isSgModifierType(vRef->get_type()) == NULL) {
24366 val.value_ = -1;
24367 val.hasValue_ = false;
24368 return val;
24369 }
24370 if (isSgModifierType(vRef->get_type())->get_typeModifier().get_constVolatileModifier().isConst()) {
24371 // We know that the var value is const, so get the initialized name and evaluate it
24372 SgVariableSymbol *sym = vRef->get_symbol();
24373 SgInitializedName *iName = sym->get_declaration();
24374 SgInitializer *ini = iName->get_initializer();
24375
24376 if (isSgAssignInitializer(ini)) {
24377 SgAssignInitializer *initializer = isSgAssignInitializer(ini);
24378 SgExpression *rhs = initializer->get_operand();
24379 SimpleExpressionEvaluator variableEval;
24380
24381 return variableEval.traverse(rhs);
24382 }
24383 }
24385 val.hasValue_ = false;
24386 val.value_ = -1;
24387 return val;
24388 }
24389
24390 struct SageInterface::const_int_expr_t evaluateSynthesizedAttribute(SgNode *node, SynthesizedAttributesList synList) {
24391 if (isSgExpression(node) != NULL) {
24392 SgValueExp* valueExp = isSgValueExp(node);
24393 if (valueExp != NULL) {
24394 return this->getValueExpressionValue(valueExp);
24395 }
24396
24397 SgVarRefExp* varRefExp = isSgVarRefExp(node);
24398 if (varRefExp != NULL) {
24399 // std::cout << "Hit variable reference expression!" << std::endl;
24400 return evaluateVariableReference(varRefExp);
24401 }
24402 // Early break out for assign initializer // other possibility?
24403 if (isSgAssignInitializer(node)) {
24404 if(synList.at(0).hasValue_){
24405 return synList.at(0);
24406 } else {
24408 val.value_ = -1;
24409 val.hasValue_ = false;
24410 return val;
24411 }
24412 }
24413 struct SageInterface::const_int_expr_t evaluatedValue;
24414 evaluatedValue.hasValue_ = false;
24415 evaluatedValue.value_ = -1;
24416#if 0
24417 if(synList.size() != 2){
24418 for(SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it){
24419 std::cout << "Node: " << node->unparseToString() << "\n" << (*it).value_ << std::endl;
24420 std::cout << "Parent: " << node->get_parent()->unparseToString() << std::endl;
24421 std::cout << "Parent, Parent: " << node->get_parent()->get_parent()->unparseToString() << std::endl;
24422 }
24423 }
24424#endif
24425 for (SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it) {
24426 if((*it).hasValue_){
24427 if (isSgAddOp(node)) {
24428 assert(synList.size() == 2);
24429 evaluatedValue.value_ = synList[0].value_ + synList[1].value_ ;
24430 evaluatedValue.hasValue_ = true;
24431 } else if (isSgSubtractOp(node)) {
24432 assert(synList.size() == 2);
24433 evaluatedValue.value_ = synList[0].value_ - synList[1].value_ ;
24434 evaluatedValue.hasValue_ = true;
24435 } else if (isSgMultiplyOp(node)) {
24436 assert(synList.size() == 2);
24437 evaluatedValue.value_ = synList[0].value_ * synList[1].value_ ;
24438 evaluatedValue.hasValue_ = true;
24439 } else if (isSgDivideOp(node)) {
24440 assert(synList.size() == 2);
24441 evaluatedValue.value_ = synList[0].value_ / synList[1].value_ ;
24442 evaluatedValue.hasValue_ = true;
24443 } else if (isSgModOp(node)) {
24444 assert(synList.size() == 2);
24445 evaluatedValue.value_ = synList[0].value_ % synList[1].value_ ;
24446 evaluatedValue.hasValue_ = true;
24447 }
24448 } else {
24449 std::cerr << "Expression is not evaluatable" << std::endl;
24450 evaluatedValue.hasValue_ = false;
24451 evaluatedValue.value_ = -1;
24452 return evaluatedValue;
24453 }
24454 }
24455 evaluatedValue.hasValue_ = true;
24456 return evaluatedValue;
24457 }
24458 struct SageInterface::const_int_expr_t evaluatedValue;
24459 evaluatedValue.hasValue_ = false;
24460 evaluatedValue.value_ = -1;
24461 return evaluatedValue;
24462 }
24463};
24464
24468 return eval.traverse(expr);
24469}
24470
24471bool
24473
24474 class TypeEquivalenceChecker {
24475 public:
24476 TypeEquivalenceChecker(bool profile, bool useSemanticEquivalence)
24477 : profile_(profile), useSemanticEquivalence_(useSemanticEquivalence),
24478 namedType_(0), pointerType_(0), arrayType_(0), functionType_(0)
24479 {
24480 }
24481
24482 SgNode * getBasetypeIfApplicable(SgNode *t){
24483 SgNode * node = t;
24484 if (isSgTypedefType(t)) {
24485// std::cout << "This is a typedef nodeT1. We strip everything away and compare the hidden types." << std::endl;
24486 node = isSgTypedefType(t)->stripType(SgType::STRIP_TYPEDEF_TYPE);
24487 }
24488 if(useSemanticEquivalence_){
24489 if(isSgModifierType(t)){
24490 SgModifierType *modType = isSgModifierType(t);
24491 ROSE_ASSERT(modType != NULL);
24492 // We need to check for Volatile/Restrict types. These are modelled as ModifierTypes, but are equal (in some cases)
24493 // volatile seems to make no difference for basic (built in) types like int, bool etc. But it has an impact on types
24494 // like classes
24495 // restrict seems to have no impact on the type itself.
24496 if(SageInterface::isVolatileType(modType)){
24497 // handle volatile case
24498 std::cout << "Hit volatile type, stripping of modifier type" << std::endl;
24499 node = modType->get_base_type();
24500 }
24501 if(SageInterface::isRestrictType(modType)){
24502 // handle restrict case
24503 std::cout << "Hit restrict type, stripping of modifier type" << std::endl;
24504 node = modType->get_base_type();
24505 }
24506 }
24507 }
24508 ROSE_ASSERT(node != NULL);
24509 return node;
24510}
24511
24512bool typesAreEqual(SgType *t1, SgType *t2) {
24513 bool equal = false;
24514 if(t1 == NULL || t2 == NULL){
24515 std::string wasNull;
24516 if(t1 == NULL){
24517 wasNull = "t1";
24518 } else {
24519 wasNull = "t2";
24520 }
24521 std::cerr << "ERROR: " << wasNull << " was NULL" << std::endl;
24522 return equal;
24523 }
24524 // if both pointers point to same location the types MUST be equal!
24525 if(t1 == t2){
24526// std::cout << "Pointers are equal, returning true" << std::endl;
24527 return true;
24528 }
24529#ifndef USE_CMAKEx
24530 RoseAst subT1(t1);
24531 RoseAst subT2(t2);
24532
24533 for (RoseAst::iterator i = subT1.begin(), j = subT2.begin();
24534 i != subT1.end() && j != subT2.end(); ++i, ++j) {
24535 SgNode *nodeT1 = *i;
24536 SgNode *nodeT2 = *j;
24537
24538// std::cout << "nodeT1: " << nodeT1->class_name() << " nodeT2: " << nodeT2->class_name() << std::endl;
24539 nodeT1 = getBasetypeIfApplicable(nodeT1);
24540 nodeT2 = getBasetypeIfApplicable(nodeT2);
24541
24542 if (nodeT1->variantT() == nodeT2->variantT()) {
24543// std::cout << "variantT is the same" << std::endl;
24544 if(isSgModifierType(nodeT1)){
24545 // we need to check whether the modifier is the same or not
24546 SgTypeModifier modT1 = isSgModifierType(nodeT1)->get_typeModifier();
24547 SgTypeModifier modT2 = isSgModifierType(nodeT2)->get_typeModifier();
24548 if(modT1.get_constVolatileModifier().isConst() != modT2.get_constVolatileModifier().isConst()){
24549 return false;
24550 }
24551 if(modT1.get_constVolatileModifier().isVolatile() != modT2.get_constVolatileModifier().isVolatile()){
24552 return false;
24553 }
24554 } else if (isSgNamedType(nodeT1)) { // Two different names -> Must be two different things
24555 if (profile_) {
24556 namedType_++;
24557 }
24558 i.skipChildrenOnForward();
24559 j.skipChildrenOnForward();
24560 SgNamedType *c1 = isSgNamedType(nodeT1);
24561 SgNamedType *c2 = isSgNamedType(nodeT2);
24562
24563 // XXX A function to check whether a named type is anonymous or not would speed
24564 // up this check, since we could get rid of this string compare.
24565 if(!c1->get_autonomous_declaration()){
24566 return false;
24567 }
24568 if (!c2->get_autonomous_declaration()){
24569 return false;
24570 }
24571 if (c1->get_qualified_name() == c2->get_qualified_name()) {
24572 return true;
24573 } else {
24574 return false;
24575 }
24576
24577 } else if (isSgPointerType(nodeT1)) {
24578 if (profile_) {
24579 pointerType_++;
24580 }
24581 SgPointerType *t1 = isSgPointerType(nodeT1);
24582 SgPointerType *t2 = isSgPointerType(nodeT2);
24583
24584 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24585
24586 } else if(isSgReferenceType(nodeT1)){
24587 SgReferenceType *t1 = isSgReferenceType(nodeT1);
24588 SgReferenceType *t2 = isSgReferenceType(nodeT2);
24589
24590 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24591 } else if (isSgArrayType(nodeT1)) {
24592 if (profile_) {
24593 arrayType_++;
24594 }
24595 SgArrayType *a1 = isSgArrayType(nodeT1);
24596 SgArrayType *a2 = isSgArrayType(nodeT2);
24597
24598 bool arrayBaseIsEqual = typesAreEqual(a1->get_base_type(), a2->get_base_type());
24599
24602 bool arrayIndexExpressionIsEquivalent = false;
24603 if(t1Index.hasValue_ && t2Index.hasValue_){
24604 if(t1Index.value_ == t2Index.value_){
24605 arrayIndexExpressionIsEquivalent = true;
24606 }
24607 }
24608 bool arraysAreEqual = (arrayBaseIsEqual && arrayIndexExpressionIsEquivalent);
24609 return arraysAreEqual;
24610 } else if (isSgFunctionType(nodeT1)) {
24611 if(profile_) {
24612 functionType_++;
24613 }
24614 SgFunctionType *funcTypeA = isSgFunctionType(nodeT1);
24615 SgFunctionType *funcTypeB = isSgFunctionType(nodeT2);
24616// std::cout << "Inside SgFunctionType" << std::endl;
24617// assert(funcTypeA != funcTypeB);
24618 if(typesAreEqual(funcTypeA->get_return_type(), funcTypeB->get_return_type())) {
24619 // If functions don't have the same number of arguments, they are not type-equal
24620 if(funcTypeA->get_arguments().size() != funcTypeB->get_arguments().size()) {
24621 return false;
24622 }
24623 // This should always be the same as the if before...
24624 if(funcTypeA->get_argument_list()->get_arguments().size() != funcTypeB->get_argument_list()->get_arguments().size()){
24625 return false;
24626 }
24627
24628 for(SgTypePtrList::const_iterator ii = funcTypeA->get_arguments().begin(),
24629 jj = funcTypeB->get_arguments().begin();
24630 ii != funcTypeA->get_arguments().end() &&
24631 jj != funcTypeB->get_arguments().end();
24632 ++ii, ++jj) {
24633// std::cout << (*ii)->class_name() << " " << (*jj)->class_name() << std::endl;
24634 // For all argument types check whether they are equal
24635 if(!typesAreEqual((*ii), (*jj))) {
24636 return false;
24637 }
24638 }
24639 return true;
24640 }
24641 return false;
24642 } else {
24643 // We don't have a named type, pointer type or array type, so they are equal
24644 // This is for the primitive type - case
24645 return true;
24646 }
24647 } else {
24648 // In this case the types are not equal, since its variantT is not equal.
24649 return false;
24650 }
24651 }
24652 // this should be unreachable code...
24653 return equal;
24654#else
24655 std::cerr << "This feature for now is available with autotools only!" << std::endl;
24656 ROSE_ABORT();
24657#endif
24658}
24659
24660int getNamedTypeCount() {
24661 return namedType_;
24662}
24663
24664int getPointerTypeCount() {
24665 return pointerType_;
24666}
24667
24668int getArrayTypeCount() {
24669 return arrayType_;
24670}
24671
24672int getFunctionTypeCount() {
24673 return functionType_;
24674}
24675 private:
24676// SgNode * getBasetypeIfApplicable(SgNode *t);
24677 bool profile_, useSemanticEquivalence_;
24678 int namedType_, pointerType_, arrayType_, functionType_;
24679};
24680
24681TypeEquivalenceChecker tec(false, false);
24682return tec.typesAreEqual(typeA, typeB);
24683}
24684
24685
24686std::set<SgStatement*>
24688 {
24689 // DQ (6/11/2015): This reports the statements that are marked as transformed.
24690 // It is useful for debugging the token-based unparsing.
24691
24692 class StatementTraversal : public AstSimpleProcessing
24693 {
24694 public:
24695 StatementTraversal() : count (0) {}
24696 void visit (SgNode* node)
24697 {
24698 SgStatement* statement = isSgStatement(node);
24699 if (statement != nullptr && statement->isTransformation() == true)
24700 {
24701 returnset.insert(statement);
24702 count++;
24703 }
24704 }
24705
24706 int count; // running total of statements found marked as transformations in the input AST
24707 std::set<SgStatement*> returnset;
24708 };
24709
24710 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24711 StatementTraversal traversal;
24712 traversal.traverse(node, preorder);
24713
24714 return traversal.returnset;
24715 }
24716
24717std::set<SgStatement*>
24719 {
24720 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24721 // It is useful for debugging the token-based unparsing.
24722
24723#if 1
24724 printf ("In collectModifiedStatements(): node = %p = %s \n",node,node->class_name().c_str());
24725#endif
24726
24727 class StatementTraversal : public AstSimpleProcessing
24728 {
24729 public:
24730 StatementTraversal() : count (0) {}
24731 void visit (SgNode* node)
24732 {
24733 SgStatement* statement = isSgStatement(node);
24734 if (statement != NULL && statement->get_isModified() == true)
24735 {
24736 returnset.insert(statement);
24737 count++;
24738 }
24739 }
24740
24741 int count; // running total of statements found marked as transformations in the input AST
24742 std::set<SgStatement*> returnset;
24743 };
24744
24745 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24746 StatementTraversal traversal;
24747 traversal.traverse(node, preorder);
24748
24749 return traversal.returnset;
24750 }
24751
24752
24753void
24755 {
24756 // DQ (12/2/2019): This reports the file id values of all located nodes in the AST subtree represented by the input node.
24757
24758#if 0
24759 printf ("In outputFileIds(): node = %p = %s \n",node,node->class_name().c_str());
24760#endif
24761
24762 class LocatedNodeTraversal : public AstSimpleProcessing
24763 {
24764 public:
24765 LocatedNodeTraversal() {}
24766 void visit (SgNode* node)
24767 {
24768 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24769 if (locatedNode != NULL)
24770 {
24771#if 0
24772 printf ("In outputFileIds(): isModified() == %s: locatedNode = %p = %s \n",locatedNode->get_isModified() ? "true" : "false",locatedNode,locatedNode->class_name().c_str());
24773 printf (" --- file id = %d physical_file_id = %d \n",node->get_file_info()->get_file_id(),node->get_file_info()->get_physical_file_id());
24774#endif
24775 }
24776 else
24777 {
24778 SgInitializedName* initializedName = isSgInitializedName(node);
24779 if (initializedName != NULL)
24780 {
24781 printf ("In outputFileIds(): isModified() == %s: initializedName = %p = %s \n",initializedName->get_isModified() ? "true" : "false",initializedName,initializedName->class_name().c_str());
24782 printf (" --- file id = %d physical_file_id = %d \n",initializedName->get_file_info()->get_file_id(),initializedName->get_file_info()->get_physical_file_id());
24783 }
24784 }
24785 }
24786 };
24787
24788 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24789 LocatedNodeTraversal traversal;
24790 traversal.traverse(node, preorder);
24791
24792#if 0
24793 printf ("Exiting as a test! \n");
24794 ROSE_ABORT();
24795#endif
24796 }
24797
24798
24799std::set<SgLocatedNode*>
24801 {
24802 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24803 // It is useful for debugging the token-based unparsing.
24804
24805#if 0
24806 printf ("In collectModifiedLocatedNodes(): node = %p = %s \n",node,node->class_name().c_str());
24807#endif
24808
24809 class LocatedNodeTraversal : public AstSimpleProcessing
24810 {
24811 public:
24812 LocatedNodeTraversal() : count (0) {}
24813 void visit (SgNode* node)
24814 {
24815 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24816 if (locatedNode != NULL && locatedNode->get_isModified() == true)
24817 {
24818#if 0
24819 printf ("In collectModifiedLocatedNodes(): isModified() == true: locatedNode = %p = %s \n",locatedNode,locatedNode->class_name().c_str());
24820#endif
24821 returnset.insert(locatedNode);
24822 count++;
24823 }
24824 }
24825
24826 int count; // running total of statements found marked as transformations in the input AST
24827 std::set<SgLocatedNode*> returnset;
24828 };
24829
24830 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24831 LocatedNodeTraversal traversal;
24832 traversal.traverse(node, preorder);
24833
24834 return traversal.returnset;
24835 }
24836
24837
24839void
24840SageInterface::resetModifiedLocatedNodes(const std::set<SgLocatedNode*> & modifiedNodeSet)
24841 {
24842 // DQ (6/5/2019): Use a previously constructed set to reset the IR nodes to be marked as isModified.
24843
24844#if 0
24845 printf ("In resetModifiedLocatedNodes(): modifiedNodeSet.size() = %zu \n",modifiedNodeSet.size());
24846#endif
24847
24848 std::set<SgLocatedNode*>::const_iterator i = modifiedNodeSet.begin();
24849 while (i != modifiedNodeSet.end())
24850 {
24851 SgLocatedNode* node = *i;
24852#if 0
24853 printf ("Marking node = %p = %s as modified \n",node,node->class_name().c_str());
24854#endif
24855 node->set_isModified(true);
24856
24857 i++;
24858 }
24859 }
24860
24861
24862void
24864 {
24865 // DQ (10/23/2018): This reports the nodes in the AST that are marked as modified (isModified flag).
24866 // It is useful for debugging the token-based unparsing.
24867
24868 printf ("\n\n##################################################### \n");
24869 printf ("Report on modified statements: label = %s \n",label.c_str());
24870
24871 SgSourceFile* sourceFile = isSgSourceFile(node);
24872 if (sourceFile != NULL)
24873 {
24874 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24875 }
24876 else
24877 {
24878 SgGlobal* globalScope = isSgGlobal(node);
24879 if (globalScope != NULL)
24880 {
24881 sourceFile = isSgSourceFile(globalScope->get_parent());
24882 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24883 }
24884 }
24885
24886 ROSE_ASSERT(node != NULL);
24887 std::set<SgStatement*> collection = collectModifiedStatements(node);
24888
24889#if 0
24890 printf ("In reportModifiedStatements(): collection.size() = %zu \n",collection.size());
24891#endif
24892
24893 std::set<SgStatement*>::iterator i = collection.begin();
24894 while (i != collection.end())
24895 {
24896 // DQ (10/9/2019): Adding filename to debug output.
24897 string filename = (*i)->get_file_info()->get_filename();
24898
24899 // DQ (10/14/2019): Get the best name possible.
24900 if (filename == "transformation")
24901 {
24902#if 0
24903 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24904#endif
24905 // filename = (*i)->get_file_info()->get_physical_filename();
24906 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24907 if (sourceFile != NULL)
24908 {
24909 filename = sourceFile->getFileName();
24910 }
24911 }
24912
24913 printf (" --- filename = %s modified statement = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24914
24915 i++;
24916 }
24917
24918#if 1
24919 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
24920 // output spew else the message output at the top of this function will scroll off the screen.
24921 printf ("########################################################## \n");
24922 printf ("reportModifiedStatements(): Called using label = %s \n",label.c_str());
24923#endif
24924 printf ("########################################################## \n\n\n");
24925
24926#if 0
24927 printf ("Exiting as a test! \n");
24928 ROSE_ASSERT(false);
24929#endif
24930 }
24931
24932
24933
24934void
24936 {
24937 // DQ (6/21/2021): This reports the nodes in the AST that are marked as modified (isModified flag).
24938 // It is useful for debugging the token-based unparsing.
24939
24940 printf ("\n\n##################################################### \n");
24941 printf ("Report on modified locatedNodes: label = %s \n",label.c_str());
24942
24943 SgSourceFile* sourceFile = isSgSourceFile(node);
24944 if (sourceFile != NULL)
24945 {
24946 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24947 }
24948 else
24949 {
24950 SgGlobal* globalScope = isSgGlobal(node);
24951 if (globalScope != NULL)
24952 {
24953 sourceFile = isSgSourceFile(globalScope->get_parent());
24954 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24955 }
24956 }
24957
24958 ROSE_ASSERT(node != NULL);
24959 std::set<SgLocatedNode*> collection = collectModifiedLocatedNodes(node);
24960
24961#if 0
24962 printf ("In reportModifiedLocatedNode(): collection.size() = %zu \n",collection.size());
24963#endif
24964
24965 std::set<SgLocatedNode*>::iterator i = collection.begin();
24966 while (i != collection.end())
24967 {
24968 // DQ (10/9/2019): Adding filename to debug output.
24969 string filename = (*i)->get_file_info()->get_filename();
24970
24971 // DQ (10/14/2019): Get the best name possible.
24972 if (filename == "transformation")
24973 {
24974#if 0
24975 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24976#endif
24977 // filename = (*i)->get_file_info()->get_physical_filename();
24978 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24979 if (sourceFile != NULL)
24980 {
24981 filename = sourceFile->getFileName();
24982 }
24983 }
24984
24985 printf (" --- filename = %s modified locatedNode = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24986
24987 i++;
24988 }
24989
24990#if 1
24991 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
24992 // output spew else the message output at the top of this function will scroll off the screen.
24993 printf ("########################################################## \n");
24994 printf ("reportModifiedLocatedNodes(): Called using label = %s \n",label.c_str());
24995#endif
24996 printf ("########################################################## \n\n\n");
24997
24998#if 0
24999 printf ("Exiting as a test! \n");
25000 ROSE_ASSERT(false);
25001#endif
25002 }
25003
25004
25005
25006
25007// DQ (3/22/2019): Translate CPP directives from attached preprocessor information to CPP Directive Declaration IR nodes.
25008
25009void
25011 {
25012 // Debugging function to print out comments in the statements (added by DQ)
25013
25014 ROSE_ASSERT(locatedNode != NULL);
25015 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
25016
25017#if 0
25018 curprint ("/* Inside of printOutComments() */");
25019#endif
25020
25021 if (comments != NULL)
25022 {
25023#if 0
25024 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25025 curprint ("/* Inside of printOutComments(): comments != NULL */");
25026#endif
25027
25028 AttachedPreprocessingInfoType::iterator i;
25029 for (i = comments->begin(); i != comments->end(); i++)
25030 {
25031 ROSE_ASSERT ( (*i) != NULL );
25032 printf (" Attached Comment (relativePosition=%s): %s \n",
25033 // DQ (2/11/2021): Fixed to report correct relative locations.
25034 // ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25035 PreprocessingInfo::relativePositionName((*i)->getRelativePosition()).c_str(),
25036 (*i)->getString().c_str());
25037 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
25038 // curprint (string("/* Inside of printOutComments(): comments = ") + (*i)->getString() + " */");
25039
25040#if 0
25041 (*i)->get_file_info()->display("comment/directive location");
25042#endif
25043 }
25044 }
25045 else
25046 {
25047#if 0
25048 printf ("In SageInterface::printOutComments(): No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25049#endif
25050 }
25051 }
25052
25053
25054
25055bool
25057 {
25058 bool returnValue = false;
25059
25060 ROSE_ASSERT(currentPreprocessingInfo != NULL);
25061
25062 PreprocessingInfo::DirectiveType directive = currentPreprocessingInfo->getTypeOfDirective();
25063
25064 if (directive == PreprocessingInfo::C_StyleComment ||
25065 directive == PreprocessingInfo::CplusplusStyleComment ||
25066 directive == PreprocessingInfo::FortranStyleComment ||
25067 directive == PreprocessingInfo::CpreprocessorBlankLine ||
25068 directive == PreprocessingInfo::ClinkageSpecificationStart ||
25069 directive == PreprocessingInfo::ClinkageSpecificationEnd)
25070 {
25071 returnValue = true;
25072 }
25073
25074 return returnValue;
25075 }
25076
25077std::vector<SgC_PreprocessorDirectiveStatement*>
25079 {
25080 std::vector<SgC_PreprocessorDirectiveStatement*> directiveList;
25081
25082 // Find existing first and last header.
25083 AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo();
25084
25085 if (comments != nullptr)
25086 {
25087 AttachedPreprocessingInfoType::iterator i; // , firsti, lasti;
25088 for (i = comments->begin (); i != comments->end(); i++)
25089 {
25090 if (skipTranslateToUseCppDeclaration(*i) == true)
25091 {
25092 // 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).
25093 }
25094 else
25095 {
25096 SgC_PreprocessorDirectiveStatement* directive = SgC_PreprocessorDirectiveStatement::createDirective(*i);
25097 ROSE_ASSERT(directive != NULL);
25098 directiveList.push_back(directive);
25099 }
25100
25101 printf ("directiveList.size() = %zu \n",directiveList.size());
25102 }
25103 }
25104
25105 return directiveList;
25106 }
25107
25108
25109void
25111 {
25112 bool declarationsOnly = scope->containsOnlyDeclarations();
25113
25114 printf ("In translateScopeToUseCppDeclarations(): declarationsOnly = %s scope = %p = %s \n",declarationsOnly ? "true" : "false",scope,scope->class_name().c_str());
25115
25116 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> > directiveMap;
25117
25118 if (declarationsOnly == true)
25119 {
25120 // These are scopes such as global scope, namespace definitions, class definitions, etc.
25121 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
25122 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
25123 while (i != declarationList.end())
25124 {
25125 SgDeclarationStatement* declaration = *i;
25126 ROSE_ASSERT(declaration != NULL);
25127
25128 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(declaration,scope);
25129
25130 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25131
25132 if (attachDirectives.empty() == false)
25133 {
25134 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(declaration,attachDirectives));
25135 }
25136
25137 i++;
25138 }
25139
25140 // Need to save the list of things that will be added so we can avoid iterator invalidation.
25141 }
25142 else
25143 {
25144 // These are scopes such as SgBasicBlock (which can contain non-declaration statements.
25145 SgStatementPtrList & statementList = scope->getStatementList();
25146 SgStatementPtrList::iterator i = statementList.begin();
25147 while (i != statementList.end())
25148 {
25149 SgStatement* statement = *i;
25150 ROSE_ASSERT(statement != NULL);
25151
25152 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(statement,scope);
25153
25154 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25155
25156 if (attachDirectives.empty() == false)
25157 {
25158 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(statement,attachDirectives));
25159 }
25160
25161 i++;
25162 }
25163 }
25164
25165 printf ("directiveMap.size() = %zu \n",directiveMap.size());
25166
25167 printf ("Processing the directiveMap: \n");
25168 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >::iterator i = directiveMap.begin();
25169 while (i != directiveMap.end())
25170 {
25171 SgStatement* statement = i->first;
25172 std::vector<SgC_PreprocessorDirectiveStatement*> directives = i->second;
25173
25174 printf ("statement = %p = %s \n",statement,statement->class_name().c_str());
25175 printf ("directives.size() = %zu \n",directives.size());
25176 // std::vector<SgC_PreprocessorDirectiveStatement*>::reverse_iterator j = directives.begin();
25177 std::vector<SgC_PreprocessorDirectiveStatement*>::iterator j = directives.begin();
25178 while (j != directives.end())
25179 {
25180 scope->insert_statement(statement,*j);
25181
25182 j++;
25183 }
25184
25185 // Remove the directives there were attached to the statement.
25186 AttachedPreprocessingInfoType *comments = statement->getAttachedPreprocessingInfo();
25187 ROSE_ASSERT(comments != NULL);
25188
25189 AttachedPreprocessingInfoType deleteList;
25190 // std::vector<PreprocessingInfo*> deleteList;
25191
25192 // comments->erase();
25193 // statement->setAttachedPreprocessingInfo(NULL);
25194 AttachedPreprocessingInfoType::iterator k;
25195 for (k = comments->begin(); k != comments->end(); k++)
25196 {
25197#if 1
25198 ROSE_ASSERT ( (*k) != NULL );
25199 printf (" Attached Comment (relativePosition=%s): %s\n",
25200 ((*k)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25201 (*k)->getString().c_str());
25202 printf ("translateScopeToUseCppDeclarations(): Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*k)->getNumberOfLines(),(*k)->getColumnNumberOfEndOfString());
25203#endif
25204
25205 // We only want to process the CPP directives (skipping comments and a few othr kinds of obscure directives).
25206 if (skipTranslateToUseCppDeclaration(*k) == true)
25207 {
25208 // 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).
25209 printf ("Do NOT delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25210 }
25211 else
25212 {
25213 printf ("DO delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25214
25215 deleteList.push_back(*k);
25216 // delete *k;
25217 // *k = NULL;
25218 }
25219 }
25220
25221 printf ("Iterate over the deleteList: deleteList.size() = %zu comments->size() = %zu \n",deleteList.size(),comments->size());
25222 AttachedPreprocessingInfoType::iterator m = deleteList.begin();
25223 while (m != deleteList.end())
25224 {
25225 // comments->erase(m);
25226 // std::remove(comments->begin(), comments->end(), *m);
25227 comments->erase(std::remove(comments->begin(), comments->end(), *m), comments->end());
25228
25229 printf (" --- comments->size() = %zu \n",comments->size());
25230
25231 m++;
25232 }
25233
25234 // comments->clear();
25235 // delete comments; // statement->getAttachedPreprocessingInfoPtr();
25236 // statement->set_attachedPreprocessingInfoPtr(NULL);
25237
25238 i++;
25239 }
25240
25241 printf ("Leaving translateScopeToUseCppDeclarations(): scope = %p = %s \n",scope,scope->class_name().c_str());
25242 }
25243
25244
25245void
25247 {
25248 class CppTranslationTraversal : public AstSimpleProcessing
25249 {
25250 public:
25251 CppTranslationTraversal() {}
25252 void visit (SgNode* node)
25253 {
25254 printf ("In CppTranslationTraversal::visit(): node = %p = %s \n",node,node->class_name().c_str());
25255
25256 SgScopeStatement* scope = isSgScopeStatement(node);
25257 SgGlobal* globalScope = isSgGlobal(scope);
25258 if (globalScope != NULL)
25259 {
25260 printf ("In CppTranslationTraversal::visit(): processing scope = %p = %s \n",scope,scope->class_name().c_str());
25262 }
25263 else
25264 {
25265 if (scope != NULL)
25266 {
25267 printf ("In SageInterface::translateToUseCppDeclarations(): Currently skipping all but global scope! \n");
25268 }
25269 }
25270 }
25271 };
25272
25273 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
25274 CppTranslationTraversal traversal;
25275
25276 printf ("In translateToUseCppDeclarations(): Calling traversal.traverse() \n");
25277
25278 // We might want to do this traversla POSTORDER since we are transforming the AST at each scope.
25279 // traversal.traverse(n, preorder);
25280 traversal.traverse(n, postorder);
25281
25282 printf ("Leaving translateToUseCppDeclarations(): DONE: Calling traversal.traverse() \n");
25283 }
25284
25286{
25287 // print current level's info
25288 if (!n) return;
25289 cout<<"--------------"<<endl;
25290 cout<<n<<":"<<n->class_name()<< endl;
25291 if (SgLocatedNode * lnode = isSgLocatedNode(n))
25292 {
25293 cout<<"file info:\t ";
25294 lnode->get_file_info()->display();
25295 cout<<"\n unparseToString:\t ";
25296 lnode->unparseToString();
25297 }
25298
25299 // track back to its parent
25301}
25302// forward declaration is needed here,
25303//static void serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel);
25304
25305#if 0 // made it into a template function to handle various ptr lists in AST
25306// A special node in the AST text dump
25307static void serialize(SgTemplateArgumentPtrList& plist, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25308{
25309 out<<prefix;
25310 out<< (hasRemaining?"|---": "|___");
25311
25312// out<<"+"<<edgeLabel<<"+>";
25313 out<<" "<<edgeLabel<<" ->";
25314 // print address
25315 out<<"@"<<&plist<<" "<< "SgTemplateArgumentPtrList ";
25316
25317 out<<endl;
25318
25319 int last_non_null_child_idx =-1;
25320 for (int i = (int) (plist.size())-1; i>=0; i--)
25321 {
25322 if (plist[i])
25323 {
25324 last_non_null_child_idx = i;
25325 break;
25326 }
25327 }
25328
25329 for (size_t i=0; i< plist.size(); i++ )
25330 {
25331 bool n_hasRemaining=false;
25332#if 0
25333 if (i+1 < plist.size())
25334 n_hasRemaining=true;
25335#else
25336 if ((int)i< last_non_null_child_idx) n_hasRemaining = true;
25337#endif
25338 string suffix= hasRemaining? "| " : " ";
25339 string n_prefix = prefix+suffix;
25340 string n_edge_label="";
25341 if (plist[i])
25342 serialize (plist[i], n_prefix, n_hasRemaining, out,n_edge_label);
25343 }
25344}
25345#endif
25346
25347// print essential information from any AST node
25348// hasRemaining if this node has a sibling node to be visited next.
25349void SageInterface::serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25350{
25351 // there may be NULL children!!
25352 //if (!node) return;
25353
25354 out<<prefix;
25355 out<< (hasRemaining?"|---": "|___");
25356
25357 out<<" "<<edgeLabel<<" ->";
25358 if (!node)
25359 {
25360 out<<" NULL "<<endl;
25361 return;
25362 }
25363
25364 // print address
25365 out<<"@"<<node<<" "<< node->class_name()<<" ";
25366
25367 //optionally file info
25368 if (SgLocatedNode* lnode= isSgLocatedNode(node))
25369 {
25370 //Rose::StringUtility::stripPathFromFileName()
25371 out<< lnode->get_file_info()->get_filename() <<" "<<lnode->get_file_info()->get_line()<<":"<<lnode->get_file_info()->get_col();
25372 // also preprocessing info. attached.
25373 AttachedPreprocessingInfoType *comments =
25374 lnode->getAttachedPreprocessingInfo ();
25375
25376 if (comments != NULL)
25377 {
25378// printf ("Found an IR node with preprocessing Info attached:\n");
25379 out<<" AttachedPreprocessingInfoType@"<<comments;
25380 int counter = 0;
25381 AttachedPreprocessingInfoType::iterator i;
25382 out <<"{";
25383 for (i = comments->begin (); i != comments->end (); i++)
25384 {
25385 if (i!=comments->begin ())
25386 out<<endl;
25387 out<<"<id=";
25388 out<<counter++<<" ";
25389 // printf("-------------PreprocessingInfo #%d ----------- : \n",counter++);
25390 // printf("classification = %s:\n String format = %s\n",
25391 // PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str (),
25392 // (*i)->getString ().c_str ());
25393 if (*i==NULL)
25394 out<<" NULL="; // The AST may be in the middle of transformation, with NULL comments attached.
25395 else
25396 {
25397 out<<*i<<" classification="<<PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str ();
25398 out<<" string="<<(*i)->getString ().c_str ();
25399 out<<" relative pos=" ; // << (*i)->getRelativePosition ();
25400#if 1
25401 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
25402 out<<"inside";
25403 else if ((*i)->getRelativePosition () == PreprocessingInfo::before)
25404 out<<"before";
25405 else
25406 out<<"after";
25407#endif
25408 }
25409 out<<">";
25410 }
25411 out <<"}";
25412 }
25413 }
25414
25415 if (SgDeclarationStatement* v= isSgDeclarationStatement(node))
25416 {
25417 out<<" first nondefining decl@"<< v->get_firstNondefiningDeclaration();
25418 out<<" defining decl@"<< v->get_definingDeclaration();
25419 }
25420
25421 if (SgEnumVal* f = isSgEnumVal(node) )
25422 out<<" value="<< f->get_value() <<" declaration="<<f->get_declaration() << " name="<< f->get_name().getString();
25423 // optionally qualified name
25424
25425 if (SgFunctionDeclaration* f = isSgFunctionDeclaration(node) )
25426 out<<" "<< f->get_qualified_name();
25427
25428 if (SgAdaFunctionRenamingDecl* f = isSgAdaFunctionRenamingDecl(node) )
25429 out<<" renamed_function "<< f->get_renamed_function();
25430
25431 if (SgAdaRenamingDecl* f = isSgAdaRenamingDecl(node) )
25432 out<<" name="<< f->get_name() << " renamed decl "<<f->get_renamed() ;
25433
25434 if (SgClassDeclaration* f = isSgClassDeclaration(node) )
25435 out<<" "<< f->get_qualified_name();
25436
25437 if (SgTypedefDeclaration* f = isSgTypedefDeclaration(node) )
25438 out<<" "<< f->get_qualified_name();
25439
25440 if (SgAdaPackageSpecDecl * f = isSgAdaPackageSpecDecl(node) )
25441 out<<" "<< f->get_qualified_name();
25442
25443 if (SgAdaEnumRepresentationClause* f = isSgAdaEnumRepresentationClause(node) )
25444 out<<" enumType="<< f->get_enumType();
25445
25446 if (SgAdaAccessType* v = isSgAdaAccessType(node) )
25447 {
25448 // out<<" "<< v->get_qualified_name();
25449 //out<<" "<< v->get_name();
25450 // PP (2/18/22) updated to reflect properties in AdaAccessType
25451 //~ out<<" is_object_type"<< v->get_is_object_type();
25452 out<<" is_general_access"<< v->get_is_general_access();
25453 //~ out<<" is_constant:"<< v->get_is_constant();
25454 //~ out<<" is_protected:"<< v->get_is_protected ();
25455 out<<" is_anonymous:"<< v->get_is_anonymous ();
25456 }
25457
25458 if (SgAdaSubroutineType* v = isSgAdaSubroutineType(node) )
25459 {
25460 out<<" is_protected"<< v->get_is_protected();
25461 }
25462
25463 if (SgInitializedName * v = isSgInitializedName(node) )
25464 {
25465 out<<" "<< v->get_qualified_name();
25466 out<<" type@"<< v->get_type();
25467 out<<" initializer@"<< v->get_initializer();
25468 out<<" scope@"<< v->get_scope();
25469// type_set.insert (v->get_type());
25470 }
25471
25472 // associated class, function and variable declarations
25473 if (SgTemplateInstantiationDecl* f = isSgTemplateInstantiationDecl(node) )
25474 out<<" template class decl@"<< f->get_templateDeclaration();
25475
25476 if (SgMemberFunctionDeclaration* f = isSgMemberFunctionDeclaration(node) )
25477 out<<" assoc. class decl@"<< f->get_associatedClassDeclaration();
25478
25479 if (SgConstructorInitializer* ctor= isSgConstructorInitializer(node) )
25480 {
25481 out<<" member function decl@"<< ctor->get_declaration();
25482 }
25483
25484 if (SgIntVal* v= isSgIntVal(node))
25485 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25486
25487 if (SgShortVal* v= isSgShortVal(node))
25488 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25489
25490 if (SgLongIntVal* v= isSgLongIntVal(node))
25491 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25492
25493 if (SgLongLongIntVal* v= isSgLongLongIntVal(node))
25494 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25495
25496 if (SgUnsignedIntVal* v= isSgUnsignedIntVal(node))
25497 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25498
25499 if (SgUnsignedShortVal* v= isSgUnsignedShortVal(node))
25500 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25501
25502 if (SgUnsignedLongVal* v= isSgUnsignedLongVal(node))
25503 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25504
25505 if (SgUnsignedLongLongIntVal* v= isSgUnsignedLongLongIntVal(node))
25506 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25507
25508 if (SgFloatVal* v= isSgFloatVal(node))
25509 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25510
25511 if (SgDoubleVal* v= isSgDoubleVal(node))
25512 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25513
25514 if (SgLongDoubleVal* v= isSgLongDoubleVal(node))
25515 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25516
25517 if (SgVarRefExp* var_ref= isSgVarRefExp(node) )
25518 out<<" init name@"<< var_ref->get_symbol()->get_declaration() <<" symbol name="<<var_ref->get_symbol()->get_name();
25519
25520 if (SgMemberFunctionRefExp* func_ref= isSgMemberFunctionRefExp(node) )
25521 out<<" member func decl@"<< func_ref->get_symbol_i()->get_declaration();
25522
25523 if (SgTemplateInstantiationMemberFunctionDecl* cnode= isSgTemplateInstantiationMemberFunctionDecl(node) )
25524 out<<" template member func decl@"<< cnode->get_templateDeclaration();
25525
25526 if (SgFunctionRefExp* func_ref= isSgFunctionRefExp(node) )
25527 {
25528 SgFunctionSymbol* sym= func_ref->get_symbol_i();
25529 out<<" func decl@"<< sym->get_declaration() << " func sym name="<<sym->get_name();
25530 }
25531
25532 if (SgAdaRenamingRefExp* renaming_ref= isSgAdaRenamingRefExp(node) )
25533 {
25534 SgAdaRenamingDecl * renaming_decl = renaming_ref->get_decl();
25535 out<<" ada renaming decl@"<< renaming_decl;
25536 }
25537
25538 // base type of several types of nodes:
25539 if (SgTypedefDeclaration * v= isSgTypedefDeclaration(node))
25540 {
25541 out<<" base_type@"<< v->get_base_type();
25542// type_set.insert (v->get_base_type());
25543 }
25544
25545 if (SgArrayType* v= isSgArrayType(node))
25546 out<<" base_type@"<< v->get_base_type();
25547
25548 if (SgAdaAccessType* v= isSgAdaAccessType(node))
25549 out<<" base_type@"<< v->get_base_type();
25550
25551 if (SgTypeExpression* v= isSgTypeExpression(node))
25552 out<<" type@"<< v->get_type();
25553
25554 if (SgAdaAttributeExp* v= isSgAdaAttributeExp(node))
25555 out<<" attribute@"<< v->get_attribute();
25556
25557 if (SgUsingDirectiveStatement* v= isSgUsingDirectiveStatement(node))
25558 out<<" namespaceDeclaration="<< v->get_namespaceDeclaration();
25559
25560 out<<endl;
25561
25562 std::vector<SgNode* > children = node->get_traversalSuccessorContainer();
25563#if 0
25564 int total_count = children.size();
25565 int current_index=0;
25566#endif
25567
25568 int last_non_null_child_idx =-1;
25569 for (int i = (int) (children.size())-1; i>=0; i--)
25570 {
25571 if (children[i])
25572 {
25573 last_non_null_child_idx = i;
25574 break;
25575 }
25576 }
25577
25578#if 0
25579 // some Sg??PtrList are not AST nodes, not part of children , we need to handle them separatedly
25580 // we sum all children into single total_count to tell if there is remaining children.
25581 if (isSgTemplateInstantiationDecl (node))
25582 total_count += 1; // sn->get_templateArguments().size();
25583#endif
25584
25585 // handling SgTemplateArgumentPtrList first
25586 if (SgTemplateInstantiationDecl* sn = isSgTemplateInstantiationDecl (node))
25587 {
25588 SgTemplateArgumentPtrList& plist = sn->get_templateArguments();
25589 bool n_hasRemaining=false;
25590 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25591 string suffix= hasRemaining? "| " : " ";
25592 string n_prefix = prefix+suffix;
25593 string n_edge_label= "";
25594 serialize_list(plist, "SgTemplateArgumentPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25595 }
25596 else if (SgImportStatement* import_stmt = isSgImportStatement(node))
25597 {
25598 SgExpressionPtrList& plist = import_stmt->get_import_list();
25599 bool n_hasRemaining=false;
25600 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25601 string suffix= hasRemaining? "| " : " ";
25602 string n_prefix = prefix+suffix;
25603 string n_edge_label= "";
25604 serialize_list(plist, "SgExpressionPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25605 }
25606
25607 std::vector< std::string > successorNames= node->get_traversalSuccessorNamesContainer();
25608
25609 // finish sucessors
25610 for (size_t i =0; i< children.size(); i++)
25611 {
25612 bool n_hasRemaining=false;
25613#if 0
25614 if (current_index+1<total_count)
25615 n_hasRemaining=true;
25616 current_index++;
25617#else
25618 if ((int)i<last_non_null_child_idx) n_hasRemaining = true;
25619#endif
25620 string suffix= hasRemaining? "| " : " ";
25621 string n_prefix = prefix+suffix;
25622 if (children[i])
25623 serialize (children[i], n_prefix, n_hasRemaining, out, successorNames[i]);
25624 }
25625}
25626
25628{
25629 ostringstream oss;
25630 string prefix;
25631 string label="";
25632 serialize(node, prefix, false, oss, label);
25633 cout<<oss.str();
25634}
25635
25636void SageInterface::printAST(SgNode* node, const char* filename)
25637{
25638 printAST2TextFile(node, filename, true);
25639}
25640
25641void SageInterface::printAST2TextFile (SgNode* node, std::string filename, bool printType/*=true*/)
25642{
25643 // Rasmussen 9/21/2020: This leads to infinite recursion (clang warning message) and should be removed from API)
25644// ROSE_ABORT();
25645 printAST2TextFile (node, filename.c_str(), printType);
25646}
25647
25648void SageInterface::printAST2TextFile(SgNode* node, const char* filename, bool printType/*=true*/)
25649{
25650 ostringstream oss;
25651 string prefix;
25652 string label="";
25653 serialize(node, prefix, false, oss, label);
25654 ofstream textfile;
25655 textfile.open(filename, ios::out);
25656 textfile<<oss.str();
25657
25658 if (printType)
25659 {
25660 // append type information also
25661 textfile<<"Types encountered ...."<<endl;
25662 ostringstream oss2;
25663 VariantVector vv(V_SgType);
25664 Rose_STL_Container<SgNode*> tnodes= NodeQuery::queryMemoryPool(vv);
25665 for (Rose_STL_Container<SgNode*>::const_iterator i = tnodes.begin(); i != tnodes.end(); ++i)
25666 {
25667 serialize (*i, prefix, false, oss2, label);
25668 }
25669 textfile<<oss2.str();
25670 }
25671
25672 textfile.close();
25673}
25674
25676{
25677 saveToPDF(node, string("temp.pdf.json") );
25678}
25680// node to find its enclosing file node. The entire file's AST will be saved into a pdf.
25681void SageInterface:: saveToPDF(SgNode* node, std::string filename)
25682{
25683 ROSE_ASSERT(node != NULL);
25684 AstJSONGeneration json;
25685 json.generateWithinFile(filename, getEnclosingFileNode(node));
25686}
25687
25689{
25690 bool rtval = false;
25691 ROSE_ASSERT (node != NULL);
25692 Sg_File_Info* finfo = node->get_file_info();
25693 if (finfo!=NULL)
25694 {
25695 string fname = finfo->get_filenameString();
25696 string buildtree_str1 = string("include-staging/gcc_HEADERS");
25697 string buildtree_str2 = string("include-staging/g++_HEADERS");
25698 string installtree_str1 = string("include/edg/gcc_HEADERS");
25699 string installtree_str2 = string("include/edg/g++_HEADERS");
25700 string system_headers = string("/usr/include");
25701 // if the file name has a sys header path of either source or build tree
25702 if ((fname.find (buildtree_str1, 0) != string::npos) ||
25703 (fname.find (buildtree_str2, 0) != string::npos) ||
25704 (fname.find (installtree_str1, 0) != string::npos) ||
25705 (fname.find (installtree_str2, 0) != string::npos) ||
25706 (fname.find (system_headers, 0) != string::npos)
25707 )
25708 rtval = true;
25709 }
25710 return rtval;
25711}
25712
25713
25714// DQ (2/27/2021): Adding support to detect if a SgLocatedNode is located in a header file.
25716 {
25717 // Check if a node is from a header file
25718
25719 bool returnValue = false;
25720
25721 Sg_File_Info* fileInfo = node->get_file_info();
25722 ROSE_ASSERT(fileInfo != NULL);
25723 string filename = fileInfo->get_filenameString();
25724
25725#if 0
25726 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());
25727#endif
25728
25729 // DQ (2/27/2021): We save a map of all of the header files processed in the generation of the ROSE AST,
25730 // so the test is only if the filename is in the list.
25731 if (EDG_ROSE_Translation::edg_include_file_map.find(filename) == EDG_ROSE_Translation::edg_include_file_map.end())
25732 {
25733#if 0
25734 printf ("This is NOT in the EDG_ROSE_Translation::edg_include_file_map \n");
25735#endif
25736 }
25737 else
25738 {
25739#if 0
25740 printf ("This IS in the EDG_ROSE_Translation::edg_include_file_map \n");
25741#endif
25742 returnValue = true;
25743 }
25744
25745 return returnValue;
25746 }
25747
25748
25751{
25752 ROSE_ASSERT(return_type != NULL);
25753 ROSE_ASSERT(typeList != NULL);
25755 ROSE_ASSERT(fTable);
25756
25757 // This function make clever use of a static member function which can't be built
25758 // for the case of a SgMemberFunctionType (or at least not without more work).
25759 SgName typeName = SgFunctionType::get_mangled(return_type, typeList);
25760 SgFunctionType* funcType = isSgFunctionType(fTable->lookup_function_type(typeName));
25761
25762 return funcType;
25763}
25764
25769{
25770 ROSE_ASSERT (lhs != NULL);
25771 ROSE_ASSERT (rhs != NULL);
25772 if (lhs == rhs)
25773 return true;
25774
25775 bool rt = false;
25776 SgType* rt1 = lhs->get_return_type();
25777 SgType* rt2 = rhs->get_return_type();
25778
25779 if (isEquivalentType (rt1, rt2))
25780 {
25781 SgTypePtrList f1_arg_types = lhs->get_arguments();
25782 SgTypePtrList f2_arg_types = rhs->get_arguments();
25783 // Must have same number of argument types
25784 if (f1_arg_types.size() == f2_arg_types.size())
25785 {
25786 // DQ (2/16/2017): Fixed compiler warning about comparison between signed and unsigned integers
25787 // int counter = 0;
25788 size_t counter = 0;
25789 // iterate through all argument types
25790 // for (int i=0; i< f1_arg_types.size(); i++)
25791 for (size_t i=0; i< f1_arg_types.size(); i++)
25792 {
25793 if (isEquivalentType (f1_arg_types[i], f2_arg_types[i]) )
25794 counter ++; // count the number of equal arguments
25795 else
25796 break; // found different type? jump out the loop
25797 }
25798 // all arguments are equivalent, set to true
25799 if (counter == f1_arg_types.size())
25800 rt = true;
25801 }
25802 } // end if equivalent return types
25803
25804 return rt;
25805}
25806
25807bool
25809 {
25810 // This function is called in the SgType::isEquivalentType (const SgType & Y) const function.
25811
25812 // DQ (11/28/2015): A better goal for this function should be to define it as a recursive function.
25813
25814 // DQ (12/8/2015): We need to add support for SgMemberFunctionType as demonstrated by test2007_17.C.
25815 // and for SgTemplateType as demonstrated by tests/nonsmoke/functional/CompileTests/RoseExample_tests/testRoseHeaders_03.C
25816 // Note that this is only required within the change to use this isEquivalentType() function in the
25817 // support to replace:
25818 // templateParameterOrArgumentLocal->get_initializedName()->get_type() == templateParameterOrArgumentFromSymbol->get_initializedName()->get_type()
25819 // in ROSETTA/Grammar/Support.code
25820
25821 ROSE_ASSERT(lhs != NULL);
25822 ROSE_ASSERT(rhs != NULL);
25823
25824 bool isSame = false;
25825
25826 // 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).
25827 static int counter = 0;
25828
25829 const SgType & X = *lhs;
25830 const SgType & Y = *rhs;
25831
25832 // DQ (11/28/2015): We don't want to strip off everything.
25833 // SgType* stripType(unsigned char bit_array = STRIP_MODIFIER_TYPE | STRIP_REFERENCE_TYPE | STRIP_POINTER_TYPE | STRIP_ARRAY_TYPE | STRIP_TYPEDEF_TYPE ) const;
25834
25835 // I think we need to compute the type chain to evaluate equalence.
25836 // Rose_STL_Container< SgType*> getInternalTypes () const
25837
25838#define DEBUG_TYPE_EQUIVALENCE 0
25839
25840#if DEBUG_TYPE_EQUIVALENCE
25841 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25842 printf (" --- lhs = %s \n",lhs->unparseToString().c_str());
25843 printf (" --- rhs = %s \n",rhs->unparseToString().c_str());
25844#endif
25845
25846#if DEBUG_TYPE_EQUIVALENCE || 0
25847 if (counter == 0)
25848 {
25849 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25850 printf (" --- lhs = %p = %s = %s \n",lhs,lhs->class_name().c_str(),lhs->unparseToString().c_str());
25851 printf (" --- rhs = %p = %s = %s \n",rhs,rhs->class_name().c_str(),rhs->unparseToString().c_str());
25852 }
25853#endif
25854
25855#if DEBUG_TYPE_EQUIVALENCE || 0
25856 // Debugging output.
25857 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
25858 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
25859
25860 // Debugging output.
25861 printf ("Output of type chain for lhs: \n");
25862 for (size_t i = 0; i < X_typeChain.size(); i++)
25863 {
25864 SgType* element_type = X_typeChain[i];
25865 printf ("X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25866 printf (" --- X_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25867 SgModifierType* modifierType = isSgModifierType(element_type);
25868 if (modifierType != NULL)
25869 {
25870 // modifierType->get_typeModifier().display("X type chain");
25871 string s = modifierType->get_typeModifier().displayString();
25872 printf (" --- type chain modifier: %s \n",s.c_str());
25873 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25874 }
25875 }
25876
25877 printf ("Output of type chain for rhs: \n");
25878 for (size_t i = 0; i < Y_typeChain.size(); i++)
25879 {
25880 SgType* element_type = Y_typeChain[i];
25881 printf ("Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25882 printf (" --- Y_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25883 SgModifierType* modifierType = isSgModifierType(element_type);
25884 if (modifierType != NULL)
25885 {
25886 // modifierType->get_typeModifier().display("Y type chain");
25887 string s = modifierType->get_typeModifier().displayString();
25888 printf (" --- type chain modifier: %s \n",s.c_str());
25889 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25890 }
25891 }
25892#endif
25893
25894 // Increment the static variable to control the recursive depth while we debug this.
25895 counter++;
25896
25897 // DQ (11/28/2015): exit with debug output instead of infinte recursion.
25898 // if (counter >= 280)
25899 // if (counter >= 500)
25900 if (counter >= 280)
25901 {
25902 // 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());
25903 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);
25904 }
25905
25906 // DQ (12/23/2015): ASC application code requires this to be increased to over 122 (selected 300 for extra margin of safety).
25907 // DQ (11/28/2015): exit in stead of infinte recursion.
25908 // if (counter > 300)
25909 // if (counter > 600)
25910 // if (counter > 5000)
25911 // if (counter > 300)
25912 if (counter > 350)
25913 {
25914 // DQ (11/28/2015): I think this is a reasonable limit.
25915 printf ("ERROR: In SageInterface::isEquivalentType(): recursive limit exceeded for : counter = %d \n",counter);
25916 ROSE_ABORT();
25917 }
25918
25919 // bool exit = false;
25920
25921 // Strip off any typedefs since they are equivalent by definition.
25922 SgType* X_element_type = X.stripType( SgType::STRIP_TYPEDEF_TYPE );
25923 SgType* Y_element_type = Y.stripType( SgType::STRIP_TYPEDEF_TYPE );
25924
25925 // DQ (11/29/2015): We need to handle references (when they are both references we can support then uniformally).
25926 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
25927 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
25928
25929 if (X_referenceType != NULL && Y_referenceType != NULL)
25930 {
25931 X_element_type = X_referenceType->get_base_type();
25932 Y_element_type = Y_referenceType->get_base_type();
25933
25934 counter--;
25935
25936 // Recursive call.
25937 // return (*X_element_type) == (*Y_element_type);
25938 return isEquivalentType(X_element_type,Y_element_type);
25939 }
25940 else
25941 {
25942 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25943 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
25944 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
25945
25946 if (X_pointerType != NULL && Y_pointerType != NULL)
25947 {
25948 X_element_type = X_pointerType->get_base_type();
25949 Y_element_type = Y_pointerType->get_base_type();
25950
25951 counter--;
25952
25953 // Recursive call.
25954 // return (*X_element_type) == (*Y_element_type);
25955 return isEquivalentType(X_element_type,Y_element_type);
25956 }
25957 else
25958 {
25959 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25960 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
25961 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
25962
25963 // DQ (12/8/2015): We need to check that the array size is the same.
25964 if (X_arrayType != NULL && Y_arrayType != NULL)
25965 {
25966 X_element_type = X_arrayType->get_base_type();
25967 Y_element_type = Y_arrayType->get_base_type();
25968
25969 SgExpression* X_array_index_expression = X_arrayType->get_index();
25970 SgExpression* Y_array_index_expression = Y_arrayType->get_index();
25971
25972 if (X_array_index_expression == Y_array_index_expression)
25973 {
25974#if DEBUG_TYPE_EQUIVALENCE || 0
25975 printf ("In SageInterface::isEquivalentType(): counter = %d: Need to check the array size for static equivalence \n",counter);
25976#endif
25977 counter--;
25978
25979 // Recursive call.
25980 // return (*X_element_type) == (*Y_element_type);
25981 return isEquivalentType(X_element_type,Y_element_type);
25982 }
25983 else
25984 {
25985 // Need more complex test for expression equivalence.
25986#if DEBUG_TYPE_EQUIVALENCE || 0
25987 printf ("In SageInterface::isEquivalentType(): counter = %d Need more complex test for expression equivalence \n",counter);
25988 string str1 = X_array_index_expression->unparseToString();
25989 string str2 = Y_array_index_expression->unparseToString();
25990 printf (" --- array index expressions: str1 = %s str2 = %s \n",str1.c_str(),str2.c_str());
25991#endif
25992 // DQ (12/9/2016): Need to decriment the counter as part of recursive function call.
25993 counter--;
25994
25995 // Recursive call.
25996 return isEquivalentType(X_element_type,Y_element_type);
25997 }
25998 }
25999 else
26000 {
26001 // DQ (12/15/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26002 SgNonrealType* X_templateType = isSgNonrealType(X_element_type);
26003 SgNonrealType* Y_templateType = isSgNonrealType(Y_element_type);
26004
26005 // DQ (12/15/2015): We need to check that the array size is the same.
26006 if (X_templateType != NULL && Y_templateType != NULL)
26007 {
26008 string X_name = X_templateType->get_name();
26009 string Y_name = Y_templateType->get_name();
26010
26011 SgNonrealDecl* X_templateDecl = isSgNonrealDecl(X_templateType->get_declaration());
26012 ROSE_ASSERT(X_templateDecl != NULL);
26013 SgNonrealDecl* Y_templateDecl = isSgNonrealDecl(Y_templateType->get_declaration());
26014 ROSE_ASSERT(Y_templateDecl != NULL);
26015
26016 int X_template_parameter_position = X_templateDecl->get_template_parameter_position();
26017 int Y_template_parameter_position = Y_templateDecl->get_template_parameter_position();
26018
26019 SgNode * X_parent = X_templateDecl->get_parent();
26020 SgNode * Y_parent = Y_templateDecl->get_parent();
26021
26022#if DEBUG_TYPE_EQUIVALENCE
26023 SgNode * X_parent_parent = X_parent ? X_parent->get_parent() : NULL;
26024 SgNode * Y_parent_parent = Y_parent ? Y_parent->get_parent() : NULL;
26025 printf ("In SageInterface::isEquivalentType(): case SgNonrealType:\n");
26026 printf (" -- X_name = %s Y_name = %s\n", X_name.c_str(),Y_name.c_str());
26027 printf (" -- X_template_parameter_position = %d Y_template_parameter_position = %d\n", X_template_parameter_position,Y_template_parameter_position);
26028 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() : "");
26029 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() : "");
26030 printf (" -- X_templateDecl->get_mangled_name() = %s\n", X_templateDecl->get_mangled_name().str());
26031 printf (" -- Y_templateDecl->get_mangled_name() = %s\n", Y_templateDecl->get_mangled_name().str());
26032#endif
26033 bool value = (X_parent == Y_parent);
26034
26035 if (value && X_templateDecl->get_is_template_param() && Y_templateDecl->get_is_template_param()) {
26036 value = (X_template_parameter_position == Y_template_parameter_position);
26037 } else if (value && X_templateDecl->get_is_class_member() && Y_templateDecl->get_is_class_member()) {
26038 value = (X_name == Y_name);
26039 }
26040
26041 counter--;
26042
26043 return value;
26044 }
26045 else
26046 {
26047 // DQ (2/13/2018): I an unclear if we are really done since they could have resolved to different types or the same type.
26048 // Nothing to do here since we have explored all uniform pairs of intermediate types possible.
26049#if 0
26050 printf ("Nothing to do here since we have explored all uniform pairs of intermediate types possible: isSame = %s \n",isSame ? "true" : "false");
26051 // printf (" --- X_element_type = %p = %s \n",X_element_type,X_element_type->unparseToString().c_str());
26052 // printf (" --- Y_element_type = %p = %s \n",Y_element_type,Y_element_type->unparseToString().c_str());
26053 printf (" --- lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26054 printf (" --- rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26055#endif
26056#if DEBUG_TYPE_EQUIVALENCE
26057 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");
26058#endif
26059 }
26060 }
26061 }
26062 } // end if reference type, pointer type, array type, and template type
26063
26064 SgModifierType* X_modifierType = isSgModifierType(X_element_type);
26065 SgModifierType* Y_modifierType = isSgModifierType(Y_element_type);
26066
26067#if DEBUG_TYPE_EQUIVALENCE
26068 printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %p = %s Y_element_type = %p = %s \n",
26069 counter,X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26070#endif
26071
26072 if (X_modifierType != NULL && Y_modifierType != NULL)
26073 {
26074 // Handle the case of both modifiers.
26075#if DEBUG_TYPE_EQUIVALENCE
26076 printf ("In SageInterface::isEquivalentType(): loop: these are the both SgModifierType nodes: isSame = %s \n",isSame ? "true" : "false");
26077#endif
26078 if (X_modifierType == Y_modifierType)
26079 {
26080 isSame = true;
26081#if DEBUG_TYPE_EQUIVALENCE
26082 printf ("In SageInterface::isEquivalentType(): loop: these are the same modifier type: isSame = %s \n",isSame ? "true" : "false");
26083#endif
26084 }
26085 else
26086 {
26087 if (X_modifierType->get_typeModifier() == Y_modifierType->get_typeModifier())
26088 {
26089#if DEBUG_TYPE_EQUIVALENCE
26090 printf ("In SageInterface::isEquivalentType(): loop: these are equivalent modifiers: check the base type: isSame = %s \n",isSame ? "true" : "false");
26091#endif
26092 // Recursive call.
26093 // isSame = (*X_modifierType->get_base_type()) == (*Y_modifierType->get_base_type());
26094 isSame = isEquivalentType(X_modifierType->get_base_type(),Y_modifierType->get_base_type());
26095 }
26096 else
26097 {
26098#if DEBUG_TYPE_EQUIVALENCE
26099 printf ("In SageInterface::isEquivalentType(): loop: these are not equivalent modifier types: check for default settings: isSame = %s \n",isSame ? "true" : "false");
26100#endif
26101 // DQ (5/22/2016): fixing bug which cansed infinite recursion (case there the SgModifiers were different).
26102 bool skippingOverIdentityModifier = false;
26103
26104 if (X_modifierType->get_typeModifier().isIdentity() == true)
26105 {
26106#if DEBUG_TYPE_EQUIVALENCE
26107 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26108#endif
26109 X_element_type = X_modifierType->get_base_type();
26110
26111 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26112 skippingOverIdentityModifier = true;
26113 }
26114
26115 if (Y_modifierType->get_typeModifier().isIdentity() == true)
26116 {
26117#if DEBUG_TYPE_EQUIVALENCE
26118 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26119#endif
26120 Y_element_type = Y_modifierType->get_base_type();
26121
26122 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26123 skippingOverIdentityModifier = true;
26124 }
26125
26126 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26127#if DEBUG_TYPE_EQUIVALENCE
26128 printf ("In SageInterface::isEquivalentType(): loop: skippingOverIdentityModifier = %s \n",skippingOverIdentityModifier ? "true" : "false");
26129#endif
26130 // Recursive call on non-default modifier base types.
26131 // isSame = (*X_element_type) == (*Y_element_type);
26132 // isSame = isEquivalentType(X_element_type,Y_element_type);
26133 if (skippingOverIdentityModifier == true)
26134 {
26135#if DEBUG_TYPE_EQUIVALENCE
26136 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");
26137#endif
26138 // If we have made progress in skipping over an identity modifier then we need to reevaluate if these are the equivalent types.
26139 isSame = isEquivalentType(X_element_type,Y_element_type);
26140 }
26141 else
26142 {
26143 // 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).
26144 isSame = false;
26145#if DEBUG_TYPE_EQUIVALENCE
26146 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");
26147#endif
26148 }
26149
26150#if DEBUG_TYPE_EQUIVALENCE
26151 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isSame = %s \n",isSame ? "true" : "false");
26152#endif
26153 }
26154 }
26155 }
26156 else
26157 {
26158 // At least one of these is not a SgModifierType.
26159
26160 if (X_modifierType != NULL || Y_modifierType != NULL)
26161 {
26162 bool isReduceable = false;
26163
26164 if (X_modifierType != NULL && X_modifierType->get_typeModifier().isIdentity() == true)
26165 {
26166#if DEBUG_TYPE_EQUIVALENCE
26167 printf ("In SageInterface::isEquivalentType(): loop: found default setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26168#endif
26169 X_element_type = X_modifierType->get_base_type();
26170 isReduceable = true;
26171 }
26172
26173 if (Y_modifierType != NULL && Y_modifierType->get_typeModifier().isIdentity() == true)
26174 {
26175#if DEBUG_TYPE_EQUIVALENCE
26176 printf ("In SageInterface::isEquivalentType(): loop: found default setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26177#endif
26178 Y_element_type = Y_modifierType->get_base_type();
26179 isReduceable = true;
26180 }
26181
26182 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26183#if DEBUG_TYPE_EQUIVALENCE
26184 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s \n",isReduceable ? "true" : "false");
26185#endif
26186 if (isReduceable == true)
26187 {
26188 // Recursive call on non-default modifier base types.
26189 // isSame = (*X_element_type) == (*Y_element_type);
26190 isSame = isEquivalentType(X_element_type,Y_element_type);
26191 }
26192 else
26193 {
26194 // Neither of these types were reducable.
26195 isSame = false;
26196 }
26197
26198#if DEBUG_TYPE_EQUIVALENCE
26199 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s isSame = %s \n",
26200 isReduceable ? "true" : "false",isSame ? "true" : "false");
26201#endif
26202 }
26203 else
26204 {
26205 // Neither of these are SgModifierType nodes.
26206 // X_element_type = X_element_type->stripType( STRIP_TYPEDEF_TYPE );
26207 // Y_element_type = Y_element_type->stripType( STRIP_TYPEDEF_TYPE );
26208
26209 if (X_element_type == Y_element_type)
26210 {
26211 isSame = true;
26212#if DEBUG_TYPE_EQUIVALENCE || 0
26213 // printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s \n",isSame ? "true" : "false");
26214 printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s lhs = %p = %s rhs = %p = %s \n",
26215 isSame ? "true" : "false",lhs,lhs->unparseToString().c_str(),rhs,rhs->unparseToString().c_str());
26216#endif
26217#if DEBUG_TYPE_EQUIVALENCE || 0
26218 // DQ (2/13/2018): Debugging type equivalence. If they are the same typedef, they
26219 // still might not be interchangable if one is defined in a restrcited scope.
26220 const SgTypedefType* lhs_typedefType = isSgTypedefType(lhs);
26221 const SgTypedefType* rhs_typedefType = isSgTypedefType(rhs);
26222
26223 if (lhs_typedefType != NULL || rhs_typedefType != NULL)
26224 {
26225#if 0
26226 if (lhs_typedefType != NULL)
26227 {
26228 printf ("lhs was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26229 }
26230 if (rhs_typedefType != NULL)
26231 {
26232 printf ("rhs was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26233 }
26234#else
26235 printf (" --- one was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26236 printf (" --- one was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26237#endif
26238 }
26239#endif
26240 }
26241 else
26242 {
26243 // DQ (3/20/2016): This is reported by GNU as set but not used.
26244 // bool isReduceable = false;
26245
26246 // DQ (11/29/2015): We need to handle reference (when they are both references we can support then uniformally).
26247 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26248 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26249
26250 if (X_referenceType != NULL || Y_referenceType != NULL)
26251 {
26252#if 0
26253 if (X_referenceType != NULL)
26254 {
26255 X_element_type = X_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 (Y_referenceType != NULL)
26263 {
26264 Y_element_type = Y_referenceType->get_base_type();
26265
26266 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26267 // isReduceable = true;
26268 isReduceable = false;
26269 }
26270
26271 if (isReduceable == true)
26272 {
26273 // Recursive call on non-default modifier base types.
26274 // isSame = (*X_element_type) == (*Y_element_type);
26275 isSame = isEquivalentType(X_element_type,Y_element_type);
26276 }
26277 else
26278 {
26279 // Neither of these types were reducable.
26280 isSame = false;
26281 }
26282#else
26283 isSame = false;
26284#endif
26285 }
26286 else
26287 {
26288 // Recursive call on non-typedef base types.
26289 // isSame = (*X_element_type) == (*Y_element_type);
26290 // isSame = isEquivalentType(X_element_type,Y_element_type);
26291
26292#if DEBUG_TYPE_EQUIVALENCE
26293 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26294#endif
26295
26296 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26297 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26298 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26299
26300 if (X_pointerType != NULL || Y_pointerType != NULL)
26301 {
26302#if 0
26303 if (X_pointerType != NULL)
26304 {
26305 X_element_type = X_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 (Y_pointerType != NULL)
26313 {
26314 Y_element_type = Y_pointerType->get_base_type();
26315
26316 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26317 // isReduceable = true;
26318 isReduceable = false;
26319 }
26320
26321 if (isReduceable == true)
26322 {
26323 // Recursive call on non-default modifier base types.
26324 // isSame = (*X_element_type) == (*Y_element_type);
26325 isSame = isEquivalentType(X_element_type,Y_element_type);
26326 }
26327 else
26328 {
26329 // Neither of these types were reducable.
26330 isSame = false;
26331 }
26332#else
26333 isSame = false;
26334#endif
26335 }
26336 else
26337 {
26338 // Recursive call on non-typedef base types.
26339 // isSame = (*X_element_type) == (*Y_element_type);
26340 // isSame = isEquivalentType(X_element_type,Y_element_type);
26341
26342#if DEBUG_TYPE_EQUIVALENCE
26343 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26344#endif
26345
26346 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26347 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26348 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26349
26350 if (X_arrayType != NULL || Y_arrayType != NULL)
26351 {
26352#if 0
26353 if (X_arrayType != NULL)
26354 {
26355 X_element_type = X_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 (Y_arrayType != NULL)
26363 {
26364 Y_element_type = Y_arrayType->get_base_type();
26365
26366 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26367 // isReduceable = true;
26368 isReduceable = false;
26369 }
26370
26371 if (isReduceable == true)
26372 {
26373 // Recursive call on non-default modifier base types.
26374 // isSame = (*X_element_type) == (*Y_element_type);
26375 isSame = isEquivalentType(X_element_type,Y_element_type);
26376 }
26377 else
26378 {
26379 // Neither of these types were reducable.
26380 isSame = false;
26381 }
26382#else
26383 isSame = false;
26384#endif
26385 }
26386 else
26387 {
26388 // Recursive call on non-typedef base types.
26389 // isSame = (*X_element_type) == (*Y_element_type);
26390 // isSame = isEquivalentType(X_element_type,Y_element_type);
26391
26392#if DEBUG_TYPE_EQUIVALENCE
26393 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26394#endif
26395
26396 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26397 SgFunctionType* X_functionType = isSgFunctionType(X_element_type);
26398 SgFunctionType* Y_functionType = isSgFunctionType(Y_element_type);
26399
26400 if (X_functionType != NULL || Y_functionType != NULL)
26401 {
26402 bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (X_functionType == Y_functionType) );
26403 //TODO: Liao, 9/15/2016, better comparison of function types
26404 //bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (isEquivalentFunctionType(X_functionType, Y_functionType)) );
26405#if DEBUG_TYPE_EQUIVALENCE || 0
26406 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgFunctionType: value = %s \n",value ? "true" : "false");
26407#endif
26408 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26409 // isSame == value;
26410 isSame = value;
26411
26412 // DQ (3/20/2016): This is reported by GNU as set but not used.
26413 // isReduceable = false;
26414 }
26415 else
26416 {
26417 // Recursive call on non-typedef base types.
26418 // isSame = isEquivalentType(X_element_type,Y_element_type);
26419
26420 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26421 SgMemberFunctionType* X_memberFunctionType = isSgMemberFunctionType(X_element_type);
26422 SgMemberFunctionType* Y_memberFunctionType = isSgMemberFunctionType(Y_element_type);
26423
26424 if (X_memberFunctionType != NULL || Y_memberFunctionType != NULL)
26425 {
26426 // DQ (12/15/2015): This code should be unreachable since it would have executed the code above (the case of SgFunctionType).
26427 printf ("This should be unreachable code \n");
26428 ROSE_ABORT();
26429
26430#if 0 // [Robb Matzke 2021-03-24]: unreachable
26431 bool value = ( (X_memberFunctionType != NULL && Y_memberFunctionType != NULL) && (X_memberFunctionType == Y_memberFunctionType) );
26432#if DEBUG_TYPE_EQUIVALENCE || 0
26433 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgMemberFunctionType: value = %s \n",value ? "true" : "false");
26434#endif
26435 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26436 // isSame == value;
26437 isSame = value;
26438#endif
26439 }
26440 else
26441 {
26442 // Recursive call on non-typedef base types.
26443 // isSame = isEquivalentType(X_element_type,Y_element_type);
26444#if 0
26445 // Check for irreducable types.
26446 bool X_isReduceable = true;
26447 if (isSgTypeSignedLong(X_element_type) != NULL ||
26448 isSgTypeUnsignedInt(X_element_type) != NULL ||
26449 isSgTypeBool(X_element_type) != NULL ||
26450 isSgTypeInt(X_element_type) != NULL)
26451 {
26452 X_isReduceable = false;
26453 }
26454
26455 bool Y_isReduceable = true;
26456 if (isSgTypeSignedLong(Y_element_type) != NULL ||
26457 isSgTypeUnsignedInt(Y_element_type) != NULL ||
26458 isSgTypeBool(Y_element_type) != NULL ||
26459 isSgTypeInt(Y_element_type) != NULL)
26460 {
26461 Y_isReduceable = false;
26462 }
26463#if DEBUG_TYPE_EQUIVALENCE || 0
26464 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_isReduceable = %s Y_isReduceable = %s \n",
26465 X_isReduceable ? "true" : "false",Y_isReduceable ? "true" : "false");
26466#endif
26467 if (X_isReduceable == true || Y_isReduceable == true)
26468 {
26469 // Recursive call on non-default modifier base types.
26470 isSame = isEquivalentType(X_element_type,Y_element_type);
26471 }
26472 else
26473 {
26474 // Neither of these types were reducable.
26475 isSame = false;
26476 }
26477#else
26478 // DQ (12/20/2015): This is the default case for irreducable types.
26479 if (X_element_type->variantT() == Y_element_type->variantT())
26480 {
26481#if DEBUG_TYPE_EQUIVALENCE || 0
26482 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_element_type = %p = %s Y_element_type = %p = %s \n",
26483 X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26484#endif
26485 // DQ (5/26/2016): It is not good enough that the variants match.
26486 // isSame = true;
26487 // isSame = isEquivalentType(X_element_type,Y_element_type);
26488 isSame = (X_element_type == Y_element_type);
26489 }
26490 else
26491 {
26492 // Neither of these types were reducable or equal.
26493 isSame = false;
26494 }
26495#endif
26496 }
26497 }
26498 }
26499 }
26500 }
26501 }
26502 }
26503 }
26504
26505 // Decrement the static variable to control the recursive depth while we debug this.
26506 counter--;
26507
26508#if DEBUG_TYPE_EQUIVALENCE || 0
26509 printf ("In SageInterface::isEquivalentType(): isSame = %s \n",isSame ? "true" : "false");
26510#endif
26511
26512#if DEBUG_TYPE_EQUIVALENCE || 0
26513 if (counter == 1 && isSame == true)
26514 {
26515 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());
26516
26517 // Debugging output.
26518 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26519 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26520
26521 // Debugging output.
26522 printf (" --- Output of type chain for lhs: \n");
26523 for (size_t i = 0; i < X_typeChain.size(); i++)
26524 {
26525 SgType* element_type = X_typeChain[i];
26526 printf (" --- --- X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26527 SgModifierType* modifierType = isSgModifierType(element_type);
26528 if (modifierType != NULL)
26529 {
26530 // modifierType->get_typeModifier().display("X type chain");
26531 string s = modifierType->get_typeModifier().displayString();
26532 printf (" --- type chain modifier: %s \n",s.c_str());
26533 }
26534 }
26535
26536 printf (" --- Output of type chain for rhs: \n");
26537 for (size_t i = 0; i < Y_typeChain.size(); i++)
26538 {
26539 SgType* element_type = Y_typeChain[i];
26540 printf (" --- --- Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26541 SgModifierType* modifierType = isSgModifierType(element_type);
26542 if (modifierType != NULL)
26543 {
26544 // modifierType->get_typeModifier().display("Y type chain");
26545 string s = modifierType->get_typeModifier().displayString();
26546 printf (" --- --- type chain modifier: %s \n",s.c_str());
26547 }
26548 }
26549 }
26550#endif
26551
26552#if 0
26553 if (counter == 0)
26554 {
26555 if (isSame == true)
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 // printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26560 // printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26561 printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26562 printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26563 }
26564 else
26565 {
26566 // printf ("In SageInterface::isEquivalentType(): counter = %d: isSame = %s type chain X_element_type = %s Y_element_type = %s \n",counter,isSame ? "true" : "false",X.class_name().c_str(),Y.class_name().c_str());
26567 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26568 }
26569 }
26570 else
26571 {
26572 printf (" --- counter = %d \n",counter);
26573 }
26574#endif
26575
26576 return isSame;
26577 }
26578
26579
26580#if 0
26581// This is modified to be a template function and so must be moved to the header file.
26582// DQ (8/30/2016): Added function to detect EDG AST normalization.
26583bool
26584SageInterface::isNormalizedTemplateInstantiation (SgFunctionDeclaration* function)
26585 {
26586 // This function is called in the Call graph generation to avoid filtering out EDG normalized
26587 // function template instnatiations (which come from normalized template functions and member functions).
26588
26589 bool retval = false;
26590
26591#if 1
26592 // DQ (8/30/2016): We need to mark this as an EDG normalization so that we can detect it as an exception
26593 // to some simple attempts to filter the AST (e.g. for the Call Graph implementation which filters on only
26594 // functions in the current directory). This explicit makring makes it much easier to get this test correct.
26595 // But we still need to look at if the location of the parent template is something that we wnat to output.
26596 // If tis is a template instantiation then it is not enough to look only at the non-defining declaration if
26597 // it is not compiler generated.
26598 retval = function->get_marked_as_edg_normalization();
26599#else
26600 // Test for this to be a template instantation (in which case it was marked as
26601 // compiler generated but we may want to allow it to be used in the call graph,
26602 // if it's template was a part was defined in the current directory).
26603 SgTemplateInstantiationFunctionDecl* templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(function);
26604 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(function);
26605
26606 if (templateInstantiationFunction != NULL)
26607 {
26608 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26609 templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(templateInstantiationFunction->get_firstNondefiningDeclaration());
26610 SgTemplateFunctionDeclaration* templateFunctionDeclaration = templateInstantiationFunction->get_templateDeclaration();
26611 if (templateFunctionDeclaration != NULL)
26612 {
26613 // retval = operator()(templateFunctionDeclaration);
26614 retval = (templateFunctionDeclaration->isCompilerGenerated() == false);
26615 }
26616 else
26617 {
26618 // Assume false.
26619 }
26620
26621#if DEBUG_SELECTOR
26622 printf (" --- case of templateInstantiationFunction: retval = %s \n",retval ? "true" : "false");
26623#endif
26624 }
26625 else
26626 {
26627 if (templateInstantiationMemberFunction != NULL)
26628 {
26629 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26630 templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(templateInstantiationMemberFunction->get_firstNondefiningDeclaration());
26631 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = templateInstantiationMemberFunction->get_templateDeclaration();
26632 if (templateMemberFunctionDeclaration != NULL)
26633 {
26634 // retval = operator()(templateMemberFunctionDeclaration);
26635 retval = (templateMemberFunctionDeclaration->isCompilerGenerated() == false);
26636 }
26637 else
26638 {
26639 // Assume false.
26640 }
26641
26642#if DEBUG_SELECTOR
26643 printf (" --- case of templateInstantiationMemberFunction: retval = %s \n",retval ? "true" : "false");
26644#endif
26645 }
26646 }
26647#endif
26648
26649 return retval;
26650 }
26651#endif
26652
26653void SageInterface::detectCycleInType(SgType * type, const std::string & from) {
26654#if 0
26655 printf("In detectCycleInType():\n");
26656 printf(" -- from = %s\n", from.c_str());
26657 printf(" -- type = %p (%s)\n", type, type->class_name().c_str());
26658#endif
26659 std::vector<SgType *> seen_types;
26660
26661 while (type != NULL) {
26662
26663 // DQ (4/15/2019): Added assertion.
26664 ROSE_ASSERT(type != NULL);
26665
26666 std::vector<SgType *>::const_iterator it = std::find(seen_types.begin(), seen_types.end(), type);
26667 if (it != seen_types.end()) {
26668 printf("ERROR: Cycle found in type = %p (%s):\n", type, type->class_name().c_str());
26669 size_t i = 0;
26670 for (; it != seen_types.end(); it++) {
26671 printf(" [%zd] %p (%s)\n", i, *it, (*it)->class_name().c_str());
26672 i++;
26673 }
26674 printf("-> detectCycleInType() was called from: %s\n", from.c_str());
26675 ROSE_ABORT();
26676 }
26677 seen_types.push_back(type);
26678
26679 SgModifierType * modType = isSgModifierType(type);
26680 SgPointerType * pointType = isSgPointerType(type);
26681 SgReferenceType * refType = isSgReferenceType(type);
26682 SgArrayType * arrayType = isSgArrayType(type);
26683 SgTypedefType * typedefType = isSgTypedefType(type);
26684
26685#if 0
26686 // DQ (4/15/2019): Don't count SgPointerMemberType (also fixed in SgType::stripType() function).
26687 if (isSgPointerMemberType(type) != NULL)
26688 {
26689 pointType = NULL;
26690 }
26691#endif
26692
26693 if ( modType ) {
26694 type = modType->get_base_type();
26695 } else if ( refType ) {
26696 type = refType->get_base_type();
26697 } else if ( pointType ) {
26698 type = pointType->get_base_type();
26699 // } else if ( pointerMemberType ) {
26700 // type = pointerMemberType->get_base_type();
26701 } else if ( arrayType ) {
26702 type = arrayType->get_base_type();
26703 } else if ( typedefType ) {
26704 type = typedefType->get_base_type();
26705 } else {
26706 break;
26707 }
26708 ROSE_ASSERT(type != NULL);
26709 }
26710}
26711
26712
26713#if 0
26714// DQ (11/10/2019): Older original version of the function.
26715
26716// DQ (6/6/2019): Move this to the SageInteface namespace.
26717void
26719 {
26720 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
26721 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
26722 // declarations in the outlined code we can support the outpiled code with those references. This
26723 // approach has the added advantage of also supporting the same include file tree as the original
26724 // file where the outlined code is being taken from.
26725
26726 class TransformFunctionDefinitionsTraversal : public AstSimpleProcessing
26727 {
26728 public:
26729 std::vector<SgFunctionDeclaration*> functionList;
26730 SgSourceFile* sourceFile;
26731 int sourceFileId;
26732 string filenameWithPath;
26733
26734 public:
26735 TransformFunctionDefinitionsTraversal(): sourceFile(NULL), sourceFileId(-99) {}
26736
26737 void visit (SgNode* node)
26738 {
26739#if 0
26740 printf ("In convertFunctionDefinitionsToFunctionPrototypes visit(): node = %p = %s \n",node,node->class_name().c_str());
26741#endif
26742 SgSourceFile* temp_sourceFile = isSgSourceFile(node);
26743 if (temp_sourceFile != NULL)
26744 {
26745 sourceFile = temp_sourceFile;
26746 sourceFileId = sourceFile->get_file_info()->get_file_id();
26747
26748 // The file_id is not sufficnet, not clear why, but the filenames match.
26749 filenameWithPath = sourceFile->get_sourceFileNameWithPath();
26750
26751 printf ("Found source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26752
26753 }
26754
26755 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
26756 if (functionDeclaration != NULL)
26757 {
26758 // This should have been set already.
26759 ROSE_ASSERT(sourceFile != NULL);
26760
26761 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
26762 if (functionDeclaration == definingFunctionDeclaration)
26763 {
26764#if 1
26765 printf ("Found a defining function declaration: functionDeclaration = %p = %s name = %s \n",
26766 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26767
26768 printf (" --- recorded source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26769 printf (" --- source file: file_info: id = %d name = %s \n",
26770 functionDeclaration->get_file_info()->get_file_id(),functionDeclaration->get_file_info()->get_filenameString().c_str());
26771#endif
26772 // DQ (3/20/2019): The file_id is not sufficent, using the filename with path to do string equality.
26773 // bool isInSourceFile = (sourceFileId == functionDeclaration->get_file_info()->get_file_id());
26774 bool isInSourceFile = (filenameWithPath == functionDeclaration->get_file_info()->get_filenameString());
26775#if 1
26776 printf (" --- isInSourceFile = %s \n",isInSourceFile ? "true" : "false");
26777#endif
26778 // Remove the defining declaration as a test.
26779 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
26780 if (isInSourceFile == true && functionDeclarationScope != NULL)
26781 {
26782#if 1
26783 printf (" --- Found a defining function declaration: functionDeclarationScope = %p = %s \n",
26784 functionDeclarationScope,functionDeclarationScope->class_name().c_str());
26785#endif
26786 // functionDeclarationScope->removeStatement(functionDeclaration);
26787 // removeStatement(functionDeclaration);
26788 functionList.push_back(functionDeclaration);
26789 }
26790 }
26791 }
26792 }
26793 };
26794
26795 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
26796 TransformFunctionDefinitionsTraversal traversal;
26797 traversal.traverse(node, preorder);
26798
26799 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
26800
26801#if 1
26802 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): functionList.size() = %zu \n",functionList.size());
26803#endif
26804
26805 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
26806 while (i != functionList.end())
26807 {
26808 SgFunctionDeclaration* functionDeclaration = *i;
26809 ROSE_ASSERT(functionDeclaration != NULL);
26810
26811 SgFunctionDeclaration* nondefiningFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
26812 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26813
26814#if 1
26815 printf (" --- Removing function declaration: functionDeclaration = %p = %s name = %s \n",
26816 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26817#endif
26818 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
26819 // removeStatement(functionDeclaration);
26820 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration);
26821
26822 i++;
26823 }
26824
26825#if 0
26826 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): exiting as a test! \n");
26827 ROSE_ABORT();
26828#endif
26829 }
26830#endif
26831
26832
26833void
26835 {
26836 // DQ (10/31/2020): Display function for scopes (useful for debugging).
26837 ROSE_ASSERT(scope != NULL);
26838
26839 printf ("Output the statements in scope = %p = %s \n",scope,scope->class_name().c_str());
26840
26841 // This makes a copy (on the stack) and is inefficent, but this is only for debugging.
26842 SgStatementPtrList statementList = scope->generateStatementList();
26843 for (size_t i = 0; i < statementList.size(); i++)
26844 {
26845 SgStatement* statement = statementList[i];
26846 printf (" --- statement: %zu ptr: %p IR node: %s name: %s \n",i,statement,statement->class_name().c_str(),SageInterface::get_name(statement).c_str());
26847 }
26848
26849#if 0
26850 printf ("Exiting as a test at the end of evaluation of global scope! \n");
26851 ROSE_ABORT();
26852#endif
26853 }
26854
26855
26858 {
26859 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
26860 // SgDeclarationStatement* nondefiningFunctionDeclaration = NULL;
26861
26862#if 0
26863 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p = %s name = %s \n",
26864 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26865#endif
26866
26867 // DQ (11/21/2019): Check if this is a constructor, this is a temporary fix.
26868 bool isConstructor = false;
26869 SgMemberFunctionDeclaration* tmp_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
26870 if (tmp_memberFunctionDeclaration != NULL)
26871 {
26872 isConstructor = tmp_memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
26873
26874#if 0
26875 if (isConstructor == true)
26876 {
26877 printf ("Skipping case of constructors (in building prototype from defining function declaration) \n");
26878 return;
26879 }
26880#endif
26881 }
26882
26883 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
26884 // bool replaceWithEmptyDeclaration = false;
26885 // SgDeclarationStatement* emptyDeclaration = NULL;
26886
26887 SgName name = functionDeclaration->get_name();
26888 SgType* return_type = functionDeclaration->get_type()->get_return_type();
26889
26890#if 0
26891 // DQ (12/10/2020): The issue is that the default arguments defined in template functions are represented in the AST.
26892 // Where we output the template as a string, it is included, and in the template instantiation it is represented in
26893 // the AST. So where it is used, default arguments are not represented in the AST and so the are not generated in
26894 // this function that builds the function prototype from the defining function.
26895
26896 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p \n",functionDeclaration);
26897 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
26898 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
26899
26900 // DQ (12/9/2020): Check if there is a default argument. Need to figure out how default arguments
26901 // are specified in the function declarations, and make sure the prototype reproduces them.
26902 for (size_t i = 0; i < functionDeclaration->get_args().size(); i++)
26903 {
26904 SgInitializedName* arg = functionDeclaration->get_args()[i];
26905#if 1
26906 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_args(): (i = %zu) arg = %p = %s isDefaultArgument = %s \n",
26907 i,arg,arg->get_name().str(),arg->get_file_info()->isDefaultArgument() ? "true" : "false");
26908 printf (" --- arg->get_initializer() = %p \n",arg->get_initializer());
26909#endif
26910 if (arg->get_file_info()->isDefaultArgument() == true)
26911 {
26912 printf ("NOTE: default argument (i = %zu) not reproduced in function prototype: arg = %p = %s \n",i,arg,arg->get_name().str());
26913 }
26914 }
26915#endif
26916
26917#if 1
26918 SgFunctionParameterList* param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26919#else
26920 // 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).
26921 // SgFunctionParameterList *param_list = functionDeclaration->get_parlist();
26922 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
26923 SgFunctionParameterList* param_list = NULL;
26924
26925 if (templateInstantiationFunctionDecl == NULL)
26926 {
26927 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26928 }
26929 else
26930 {
26931 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
26932 if (templateInstantiationMemberFunctionDecl == NULL)
26933 {
26934 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26935 }
26936 }
26937#endif
26938
26939
26940 // bool isTemplateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration) != NULL);
26941 bool isTemplateInstantiationMemberFunctionDecl = false;
26942
26943 SgScopeStatement* scope = functionDeclaration->get_scope();
26944 // SgTemplateParameterPtrList* templateParameterList = NULL; // functionDeclaration->get_templateParameterList();
26945 SgExprListExp* python_decoratorList = NULL;
26946 bool buildTemplateInstantiation = false;
26947 SgTemplateArgumentPtrList* templateArgumentsList = NULL;
26948
26949 // DQ (9/26/2019): Tracing down a null parent pointer.
26950 // ROSE_ASSERT(param_list->get_parent() != NULL);
26951 // ROSE_ASSERT(param_list->get_parent() == NULL);
26952 ROSE_ASSERT(param_list == NULL || param_list->get_parent() == NULL);
26953
26954 switch (functionDeclaration->variantT())
26955 {
26956 case V_SgTemplateMemberFunctionDeclaration:
26957 {
26958#if 0
26959 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template member functions \n");
26960#endif
26961 SgTemplateMemberFunctionDeclaration* original_templateMemberFunctionDeclaration = isSgTemplateMemberFunctionDeclaration(functionDeclaration);
26962 ROSE_ASSERT(original_templateMemberFunctionDeclaration != NULL);
26963
26964 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = NULL;
26965
26966 unsigned int functionConstVolatileFlags = 0;
26967
26968 ROSE_ASSERT(original_templateMemberFunctionDeclaration->get_type() != NULL);
26969
26970 // Need to call:
26971 // unsigned int get_mfunc_specifier();
26972
26973 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_templateMemberFunctionDeclaration->get_type());
26974 ROSE_ASSERT(memberFunctionType != NULL);
26975
26976 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
26977
26978 // SgTemplateMemberFunctionDeclaration*
26979 // buildNondefiningTemplateMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
26980 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList* templateParameterList );
26981
26982 SgTemplateParameterPtrList templateParameterList = original_templateMemberFunctionDeclaration->get_templateParameters();
26983 // ROSE_ASSERT(templateParameterList != NULL);
26984
26985 templateMemberFunctionDeclaration =
26986 buildNondefiningTemplateMemberFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags, &templateParameterList );
26987#if 0
26988 printf ("ERROR: Template functions are not yet supported! \n");
26989 ROSE_ABORT();
26990#endif
26991 nondefiningFunctionDeclaration = templateMemberFunctionDeclaration;
26992
26993 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26994
26995 // DQ (11/21/2019): Handle constructors.
26996 if (isConstructor == true)
26997 {
26998 templateMemberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
26999 }
27000
27001 break;
27002 }
27003
27004 case V_SgTemplateFunctionDeclaration:
27005 {
27006#if 0
27007 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template functions \n");
27008#endif
27009 SgTemplateFunctionDeclaration* original_templateFunctionDeclaration = isSgTemplateFunctionDeclaration(functionDeclaration);
27010 ROSE_ASSERT(original_templateFunctionDeclaration != NULL);
27011
27012 SgTemplateFunctionDeclaration* templateFunctionDeclaration = NULL; // isSgTemplateFunctionDeclaration(functionDeclaration);
27013
27014 // SgTemplateFunctionDeclaration*
27015 // buildNondefiningTemplateFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27016 // SgScopeStatement* scope=NULL, SgExprListExp* decoratorList = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
27017
27018 SgTemplateParameterPtrList templateParameterList = original_templateFunctionDeclaration->get_templateParameters();
27019
27020 templateFunctionDeclaration = buildNondefiningTemplateFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, &templateParameterList );
27021#if 0
27022 printf ("ERROR: Template functions are not yet supported! \n");
27023 ROSE_ABORT();
27024#endif
27025 nondefiningFunctionDeclaration = templateFunctionDeclaration;
27026
27027 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27028
27029 break;
27030 }
27031
27032 // DQ (10/29/2020): Added new case.
27033 case V_SgTemplateInstantiationMemberFunctionDecl:
27034 {
27035 buildTemplateInstantiation = true;
27036
27037 isTemplateInstantiationMemberFunctionDecl = true;
27038
27039 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
27040 ROSE_ASSERT(templateInstantiationMemberFunctionDecl != NULL);
27041 templateArgumentsList = &(templateInstantiationMemberFunctionDecl->get_templateArguments());
27042#if 0
27043 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27044 // printf ("name from templateInstantiationMemberFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_template_name().str());
27045 printf ("name from templateInstantiationMemberFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_templateName().str());
27046 SgTemplateMemberFunctionDeclaration* templateDeclaration = templateInstantiationMemberFunctionDecl->get_templateDeclaration();
27047 if (templateDeclaration != NULL)
27048 {
27049 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27050 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27051 }
27052#endif
27053 // name = functionDeclaration->get_name();
27054 // name = templateInstantiationMemberFunctionDecl->get_template_name();
27055 name = templateInstantiationMemberFunctionDecl->get_templateName();
27056#if 0
27057 printf ("In case V_SgTemplateInstantiationMemberFunctionDecl: using name = %s \n",name.str());
27058#endif
27059 // DQ (10/29/2020): Change this to include the functionality to build the member function support without fall-through.
27060 }
27061 // fall through
27062 case V_SgMemberFunctionDeclaration:
27063 {
27064#if 0
27065 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support member functions \n");
27066#endif
27067 SgMemberFunctionDeclaration* original_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
27068 ROSE_ASSERT(original_memberFunctionDeclaration != NULL);
27069
27070 SgMemberFunctionDeclaration* memberFunctionDeclaration = NULL; // isSgMemberFunctionDeclaration(functionDeclaration);
27071
27072 // SgMemberFunctionDeclaration*
27073 // buildNondefiningMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27074 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList* templateArgumentsList);
27075
27076 unsigned int functionConstVolatileFlags = 0;
27077
27078 ROSE_ASSERT(original_memberFunctionDeclaration->get_type() != NULL);
27079
27080 // Need to call:
27081 // unsigned int get_mfunc_specifier();
27082
27083 // DQ (12/2/2019): If it is defined outside of the class, then don't replace with member function prototype,
27084 // since they is not allowed to be declared outside of the class they are a member of.
27085
27086 // We do want to build prototypes for template instantiation member functions, and template instantiation non-member functions (see below).
27087 bool buildPrototype = isTemplateInstantiationMemberFunctionDecl || original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope();
27088#if 0
27089 printf ("In SageInterface::buildFunctionPrototype(): buildPrototype = %s \n",buildPrototype ? "true" : "false");
27090#endif
27091 if (buildPrototype == true)
27092 {
27093 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_memberFunctionDeclaration->get_type());
27094 ROSE_ASSERT(memberFunctionType != NULL);
27095#if 0
27096 printf ("original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope() \n");
27097#endif
27098 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
27099
27100 memberFunctionDeclaration =
27102 ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags,
27103 buildTemplateInstantiation,templateArgumentsList );
27104#if 0
27105 printf ("ERROR: Member functions are not yet supported! \n");
27106 ROSE_ABORT();
27107#endif
27108 // DQ (11/21/2019): Handle constructors.
27109 if (isConstructor == true)
27110 {
27111 memberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27112 }
27113
27114 nondefiningFunctionDeclaration = memberFunctionDeclaration;
27115
27116 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27117 }
27118 else
27119 {
27120 // Case of member function defined outside of it's class.
27121#if 0
27122 printf ("NOTE: Member functions defined outside of their class can not be output as member function prototypes (not allowed in C++) \n");
27123#endif
27124 // We want to build a SgEmptyDeclaration using buildEmptyDeclaration() but this is not a function.
27125 // nondefiningFunctionDeclaration = buildEmptyDeclaration();
27126 nondefiningFunctionDeclaration = NULL;
27127#if 0
27128 nondefiningFunctionDeclaration = NULL;
27129
27130 replaceWithEmptyDeclaration = true;
27131 emptyDeclaration = buildEmptyDeclaration();
27132 ROSE_ASSERT(emptyDeclaration != NULL);
27133#endif
27134 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27135 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27136
27137 // Since we din't build a member function we don't need the parameter list.
27138 delete param_list;
27139 param_list = NULL;
27140#if 0
27141 printf ("Exiting as a test! \n");
27142 ROSE_ABORT();
27143#endif
27144 }
27145
27146 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27147 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27148 break;
27149 }
27150
27151 case V_SgFunctionDeclaration:
27152 {
27153 // This is for a non-member non-template function declaration.
27154 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27155 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27156 break;
27157 }
27158
27159 // DQ (10/29/2020): Added new case.
27160 case V_SgTemplateInstantiationFunctionDecl:
27161 {
27162 // This is for a non-member non-template function declaration.
27163 buildTemplateInstantiation = true;
27164 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27165 ROSE_ASSERT(templateInstantiationFunctionDecl != NULL);
27166 templateArgumentsList = &(templateInstantiationFunctionDecl->get_templateArguments());
27167#if 0
27168 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27169 // printf ("name from templateInstantiationFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationFunctionDecl->get_template_name().str());
27170 printf ("name from templateInstantiationFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationFunctionDecl->get_templateName().str());
27171 SgTemplateFunctionDeclaration* templateDeclaration = templateInstantiationFunctionDecl->get_templateDeclaration();
27172 if (templateDeclaration != NULL)
27173 {
27174 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27175 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27176 }
27177#endif
27178 name = templateInstantiationFunctionDecl->get_templateName();
27179#if 0
27180 printf ("In case V_SgTemplateInstantiationFunctionDecl: using name = %s \n",name.str());
27181#endif
27182 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27183 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27184 break;
27185 }
27186
27187 default:
27188 {
27189 // DQ (12/4/2019): If this is any other case than that handled above, then we just return.
27190 // These cases would be only template instantiations.
27191
27192 // Nothing to do, except delete the parameter list we built, and return.
27193 delete param_list;
27194 param_list = NULL;
27195
27196 return NULL;
27197 }
27198 }
27199
27200 // DQ (10/29/2020): We should be able to change this now that we support SgTemplateInstantiationFunctionDecl and SgTemplateInstantiationMemberFunctionDecl IR nodes.
27201 // DQ (9/26/2019): Tracing down a null parent pointer.
27202 ROSE_ASSERT(param_list == NULL || param_list->get_parent() != NULL);
27203 // ROSE_ASSERT(param_list != NULL);
27204 // ROSE_ASSERT(param_list->get_parent() != NULL);
27205
27206 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27207
27208 if (nondefiningFunctionDeclaration != NULL)
27209 {
27210 if (nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() == NULL)
27211 {
27212#if 0
27213 printf ("Setting the firstNondefiningDeclaration \n");
27214#endif
27215 nondefiningFunctionDeclaration->set_firstNondefiningDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27216 }
27217
27218 if (nondefiningFunctionDeclaration->get_definingDeclaration() == NULL)
27219 {
27220#if 0
27221 printf ("Setting the definingDeclaration \n");
27222#endif
27223 nondefiningFunctionDeclaration->set_definingDeclaration(functionDeclaration->get_definingDeclaration());
27224 }
27225
27226 ROSE_ASSERT(nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() != NULL);
27227 ROSE_ASSERT(nondefiningFunctionDeclaration->get_definingDeclaration() != NULL);
27228
27229 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27230 if (nondefiningFunctionDeclaration != NULL)
27231 {
27232 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27233 // This is a bug in the support for building a new prototype from a defining function declaration
27234 // and caused this problem. This assertion will prevent this sort of error from happening again.
27235 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27236 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27237 }
27238 }
27239
27240 return nondefiningFunctionDeclaration;
27241 }
27242
27243
27244// 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).
27247 {
27248 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27249 ROSE_ASSERT(functionDeclaration != NULL);
27250
27251#if 0
27252 printf ("****************************************************************** \n");
27253 printf ("Attached comments and CPP directives: defining functionDeclaration \n");
27254 SageInterface::printOutComments (functionDeclaration);
27255 printf ("****************************************************************** \n");
27256#endif
27257
27258 // 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.
27259
27260 nondefiningFunctionDeclaration = buildFunctionPrototype(functionDeclaration);
27261
27262 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27263 if (nondefiningFunctionDeclaration != NULL)
27264 {
27265 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27266 // This is a bug in the support for building a new prototype from a defining function declaration
27267 // and caused this problem. This assertion will prevent this sort of error from happening again.
27268 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27269 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27270 }
27271
27272 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27273
27274 if (templateInstantiationFunctionDecl == NULL)
27275 {
27276 if (nondefiningFunctionDeclaration != NULL)
27277 {
27278 // DQ (10/29/2020): Match the associated declaration modifiers.
27279 nondefiningFunctionDeclaration->get_declarationModifier() = functionDeclaration->get_declarationModifier();
27280
27281 // DQ (11/11/2020): Match the associated other kinds of modifiers.
27282 nondefiningFunctionDeclaration->get_functionModifier() = functionDeclaration->get_functionModifier();
27283 nondefiningFunctionDeclaration->get_specialFunctionModifier() = functionDeclaration->get_specialFunctionModifier();
27284
27285 nondefiningFunctionDeclaration->set_linkage( functionDeclaration->get_linkage() );
27286 nondefiningFunctionDeclaration->set_externBrace( functionDeclaration->get_externBrace() );
27287
27288 ROSE_ASSERT(nondefiningFunctionDeclaration->get_forward() == true);
27289
27290 // DQ (10/15/2019): Set the physical_file_id of the transformation to match that of the original defining declaration.
27291 int file_id = functionDeclaration->get_file_info()->get_physical_file_id();
27292 nondefiningFunctionDeclaration->get_file_info()->set_physical_file_id(file_id);
27293
27294 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27295 // removeStatement(functionDeclaration);
27296 // DQ (11/22/2020): Note that this step will move the comments and CPP directives to the new statement
27297 // (better in this step than in the copy of the pointer to the list above, which cause an iterator invalidation error).
27298 // DQ (10/21/2020): I think we may want to return the orignal defining function declaration.
27299 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27300 // DQ (11/15/2020): Note that the default is false, and we need true.
27301 bool movePreprocessingInfo = true;
27302 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration,movePreprocessingInfo);
27303
27304 // DQ (11/25/2020): This is the cause of a problem in the outliner caught in the resetParentPointer.C (definingDeclaration->get_parent() != __null).
27305 // 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.
27306 // This is the cause of a name qualification bug when the functionDeclaration is inserted into global scope and the name qualification
27307 // is not computed correctly (since the parent was still the namespace scope where it was originally.
27308 ROSE_ASSERT(nondefiningFunctionDeclaration->get_parent() != NULL);
27309 }
27310 }
27311 else
27312 {
27313 // DQ (7/12/2019): Template instantiations are not directly from the source code, so we don't have to move them.
27314 nondefiningFunctionDeclaration = NULL;
27315 }
27316
27317 // Check that static declaration is preserved.
27318 if (functionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true)
27319 {
27320 ROSE_ASSERT(nondefiningFunctionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true);
27321 }
27322
27323 // DQ (10/27/2020): Added return value so that we can access the new function prototype.
27324 return nondefiningFunctionDeclaration;
27325 }
27326
27327
27328std::vector<SgFunctionDeclaration*>
27330 {
27331 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
27332 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
27333 // declarations in the outlined code we can support the outpiled code with those references. This
27334 // approach has the added advantage of also supporting the same include file tree as the original
27335 // file where the outlined code is being taken from.
27336
27337 class FunctionDefinitionsTraversal : public AstSimpleProcessing
27338 {
27339 public:
27340 std::vector<SgFunctionDeclaration*> functionList;
27341 FunctionDefinitionsTraversal() {}
27342
27343 void visit (SgNode* node)
27344 {
27345 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
27346 if (functionDeclaration != NULL)
27347 {
27348 // This should have been set already.
27349 // ROSE_ASSERT(sourceFile != NULL);
27350
27351 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27352 if (functionDeclaration == definingFunctionDeclaration)
27353 {
27354 // Remove the defining declaration as a test.
27355 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27356 if (functionDeclarationScope != NULL)
27357 {
27358 functionList.push_back(functionDeclaration);
27359 }
27360 }
27361 }
27362 }
27363 };
27364
27365 // Now build the traveral object and call the traversal (preorder) on the AST subtree.
27366 FunctionDefinitionsTraversal traversal;
27367
27368 traversal.traverseWithinFile(node, preorder);
27369
27370 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27371
27372 return functionList;
27373 }
27374
27375
27376void
27378 {
27379 ROSE_ASSERT(node != NULL);
27380
27381 std::vector<SgFunctionDeclaration*> functionList = generateFunctionDefinitionsList(node);
27382 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27383
27384 while (i != functionList.end())
27385 {
27386 SgFunctionDeclaration* functionDeclaration = *i;
27387 ROSE_ASSERT(functionDeclaration != NULL);
27388 // Transform into prototype.
27390 i++;
27391 }
27392 }
27393
27394
27395
27396// DQ (7/14/2020): Added test for initializers to support debugging of Cxx11_tests/test2020_69.C.
27397void
27399 {
27400 // This function checks variable declarations for initializers. An issue (bug) in EDG 6.0
27401 // support for variable declarations initialized using lambda functions is that the initalizer
27402 // is discarded at some point in the processing of the AST. This function reports on all
27403 // variable declarations and if they contain initializers and if so what kind of initializer.
27404
27405 ROSE_ASSERT(node != nullptr);
27406
27407 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
27408 class CheckInitializerTraversal : public AstSimpleProcessing
27409 {
27410 public:
27411 void visit (SgNode* node)
27412 {
27413 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node);
27414 if (variableDeclaration != NULL)
27415 {
27416 SgInitializedName* initializedName = getFirstInitializedName(variableDeclaration);
27417 SgExpression* initializer = initializedName->get_initializer();
27418
27419 printf ("variableDeclaration = %p initializedName = %p = %s initializer = %p \n",
27420 variableDeclaration,initializedName,initializedName->get_name().str(),initializer);
27421
27422 if (initializer != NULL)
27423 {
27424 printf (" --- initializer = %s \n",initializer->class_name().c_str());
27425 }
27426 }
27427 }
27428 };
27429
27430 // Now buid the traveral object and call the traversal (preorder) on the project.
27431 CheckInitializerTraversal traversal;
27432 traversal.traverse(node, preorder);
27433 }
27434
27435namespace
27436{
27437 struct DeclaredType : sg::DispatchHandler<SgNamedType*>
27438 {
27439 void setResult(SgNamedType* ty) { res = ty; }
27440 void setResult(SgType*) { /* not a named type */ }
27441
27442 void handle(SgNode& n, SgNode&) { SG_UNEXPECTED_NODE(n); }
27443
27444 template <class SageDeclarationStatement>
27445 void handle(SageDeclarationStatement& n, SgDeclarationStatement&)
27446 {
27447 // SgDeclarationStatement::get_type is not a virtual function
27448 // => find overloaders returning SgNamedType in subclasses
27449 // by using the full type (SageDeclarationStatement).
27450 setResult(n.get_type());
27451 }
27452
27453 template <class SageNode>
27454 void handle(SageNode& n)
27455 {
27456 handle(n, n);
27457 }
27458 };
27459}
27460
27462{
27463 return sg::dispatch(DeclaredType{}, declaration);
27464}
27465
27467 SgGlobal * gsaf = project->get_globalScopeAcrossFiles();
27468 ROSE_ASSERT(gsaf != nullptr);
27469 SgSymbolTable * st = gsaf->get_symbol_table();
27470 ROSE_ASSERT(st != nullptr);
27471 rose_hash_multimap * hmm = st->get_table();
27472 ROSE_ASSERT(hmm != nullptr);
27473 hmm->clear();
27474
27475 st = SgNode::get_globalTypeTable()->get_type_table();
27476 ROSE_ASSERT(st != nullptr);
27477 hmm = st->get_table();
27478 ROSE_ASSERT(hmm != nullptr);
27479 hmm->clear();
27480
27482 ROSE_ASSERT(st != nullptr);
27483 hmm = st->get_table();
27484 ROSE_ASSERT(hmm != nullptr);
27485 hmm->clear();
27486}
27487
27489/*
27490
27491By default, only transformation generated AST nodes will be normalized since this is designed to normalize translator-generated code.
27492
27493--- p_lhs_operand_i ->@0x7ff2fc3f1010 SgArrowExp c_rc-575-out.cpp 16:13
27494 |--- p_lhs_operand_i ->@0x7ff2fc428010 SgAddressOfOp c_rc-575-out.cpp 16:4
27495 | |___ p_operand_i ->@0x7ff2fc582078 SgVarRefExp c_rc-575-out.cpp 16:5 init name@0x7ff2fcf03890 symbol name="table1"
27496 |___ p_rhs_operand_i ->@0x7ff2fc5820e0 SgVarRefExp c_rc-575-out.cpp 16:16 init name@0x7ff2fcf03480 symbol name="item1"
27497
27498
27499TODO: we only handle simplest pattern for now: both leaf operands involved are SgVarRefExp.
27500
27501 * */
27502int SageInterface::normalizeArrowExpWithAddressOfLeftOperand(SgNode* root, bool transformationGeneratedOnly /* =true */)
27503{
27504 int match_count = 0;
27505 ROSE_ASSERT (root);
27506
27507 // find all SgArrowExp, then try to match the expected pattern
27508 // SgArrowExp(SgAddressOfOp(SgVarRefExp:table1),SgVarRefExp:item1)
27509 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgArrowExp);
27510
27511 // The jovial2cpp translator generates two source file ASTs: and they often share the same subtrees.
27512 // So we need to make sure the same subtree is only processed once
27513 boost::unordered::unordered_map <SgNode*, bool> visited;
27514
27515 // reverse iterator is safer to use than forward iterator to support translation
27516 for (Rose_STL_Container<SgNode *>::reverse_iterator i = nodeList.rbegin(); i != nodeList.rend(); i++)
27517 {
27518 // skip a node if it is previously processed.
27519 if (visited.count(*i)==1)
27520 continue;
27521
27522 visited[*i]=true;
27523
27524 SgArrowExp* a_exp = isSgArrowExp(*i);
27525
27526 if (!a_exp)
27527 {
27528 cerr<<"SageInterface::normalizeArrowExpWithAddressOfLeftOperand() expects SgArrowExp while encountering "<<(*i)->class_name()<<"@"<<(*i) <<endl;
27529 ROSE_ASSERT (a_exp);
27530 }
27531
27532 if (transformationGeneratedOnly)
27533 {
27534 if (!(a_exp->get_file_info()->isTransformation()))
27535 continue;
27536 }
27537
27538 if (SgAddressOfOp* address_op = isSgAddressOfOp(a_exp->get_lhs_operand()) )
27539 {
27540 if (SgVarRefExp* left = isSgVarRefExp(address_op->get_operand())) // match left side pattern
27541 {
27542 if (SgVarRefExp* right = isSgVarRefExp (a_exp->get_rhs_operand())) // match right side pattern
27543 {
27544 // do the transformation: copy two operands, making a dot exp instead
27545 SgDotExp* dot_exp = buildDotExp (deepCopy(left), deepCopy(right));
27546 replaceExpression (a_exp, dot_exp);
27547 match_count++;
27548 }
27549 }
27550 }
27551 } // end for
27552
27553 return match_count;
27554}
27555
27556bool
27558 {
27559 class Traversal : public AstSimpleProcessing
27560 {
27561 public:
27562 bool found;
27563 Traversal() : found(false) {}
27564 void visit (SgNode* node)
27565 {
27566 SgCastExp* castExpression = isSgCastExp(node);
27567 if (castExpression != NULL)
27568 {
27569 // SgNode* parent = castExpression->get_parent();
27570 SgInitializer* initializer = isSgInitializer(castExpression->get_parent());
27571 if (initializer == NULL)
27572 {
27573 ROSE_ASSERT(castExpression->get_file_info() != NULL);
27574 if (castExpression->get_file_info()->isTransformation() == true)
27575 {
27576 printf (" --- Found a SgCastExp marked as a transformation: castExpression = %p \n",castExpression);
27577 found = true;
27578#if 0
27579 printf ("Exiting as a test! \n");
27580 ROSE_ASSERT(false);
27581#endif
27582 }
27583 else
27584 {
27585#if 0
27586 printf (" --- SgCastExp (but not marked as a transformation) node = %p = %s \n",node,node->class_name().c_str());
27587#endif
27588 }
27589 }
27590 else
27591 {
27592 // DQ (7/14/2021): This case is less interesting (not the SgCastExp that I was looking for in testing).
27593#if 1
27594 printf (" --- SgCastExp (but from an initializer) node = %p = %s \n",node,node->class_name().c_str());
27595#endif
27596 }
27597 }
27598 else
27599 {
27600#if 0
27601 printf (" --- node = %p = %s \n",node,node->class_name().c_str());
27602#endif
27603 }
27604 }
27605 };
27606
27607#if 1
27608 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s \n",s.c_str());
27609#endif
27610
27611 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27612 Traversal traversal;
27613 traversal.traverse(n, preorder);
27614
27615#if 1
27616 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s traversal.found = %s \n",s.c_str(),traversal.found ? "true" : "false");
27617#endif
27618#if 0
27619 // DQ (7/13/2021): return false so that we can test the execution of the code to generate that backend code.
27620 if (traversal.found == true)
27621 {
27622 printf ("In findFirstSgCastExpMarkedAsTransformation(): returning false \n");
27623 }
27624
27625 return false;
27626#else
27627 return traversal.found;
27628#endif
27629 }
27630
27631// A helper function to check
27632// begin: return 1
27633// middle (#else, #elif): return 2
27634// end directive: return -1
27635// othewise return 0;
27636static int isBeginDirective (PreprocessingInfo* info)
27637{
27638 ROSE_ASSERT (info != NULL);
27639 PreprocessingInfo::DirectiveType dtype= info->getTypeOfDirective();
27640 if (dtype == PreprocessingInfo::CpreprocessorIfdefDeclaration ||
27641 dtype == PreprocessingInfo::CpreprocessorIfndefDeclaration ||
27642 dtype == PreprocessingInfo::CpreprocessorIfDeclaration )
27643 {
27644 return 1;
27645 }
27646 else if (dtype==PreprocessingInfo::CpreprocessorElseDeclaration||
27647 dtype==PreprocessingInfo::CpreprocessorElifDeclaration)
27648 {
27649 return 2;
27650 }
27651 else if (dtype==PreprocessingInfo::CpreprocessorEndifDeclaration)
27652 {
27653 return -1;
27654 }
27655
27656 return 0;
27657}
27658
27659// a helper function to move things, the associated directive in the middle
27660static void moveInofListToNewPlace(AttachedPreprocessingInfoType* infoList, int cidx, set <AttachedPreprocessingInfoType*>& relatedInfoList, SgLocatedNode* lnode, int &retVal)
27661{
27662// AttachedPreprocessingInfoType* infoList = (*ki).first;
27663// int cidx= (*ki).second;
27664
27665 relatedInfoList.insert (infoList);
27666
27667 PreprocessingInfo* info = (*infoList)[cidx];
27668 // rewrite relative position
27669 info->setRelativePosition(PreprocessingInfo::after);
27670
27671 // insert after lnode
27672 lnode->addToAttachedPreprocessingInfo (info);
27673 retVal++;
27674
27675 // zero out from original list
27676 (*infoList)[cidx]= NULL;
27677}
27678
27679// Return the number of NULL PreprocessingInfo* within a subtree of a SgLocatedNode, inclusive
27681{
27682 int retVal=0;
27683 ROSE_ASSERT(lnode);
27684
27685 // collecting NULL entries
27686 RoseAst ast(lnode);
27687 RoseAst::iterator ast_i=ast.begin();
27688
27689 vector < pair< AttachedPreprocessingInfoType*, int> > empty_entries; // preprocessing info. to be erased, list vs. idx/offset
27690 for(;ast_i!=ast.end();++ast_i) {
27691 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27692 if (current ==NULL ) // skip non located nodes
27693 continue;
27694
27695 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27696 if (infoList == NULL) continue;
27697
27698 int commentIndex=0;
27699 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27700 {
27701 // fundamentally, we want to move individual PreprocessingInfo objects
27702 // Or just duplicate them (easier)
27703 PreprocessingInfo * info = *ci;
27704 if (info==NULL)
27705 empty_entries.push_back( make_pair (infoList, commentIndex) );
27706 commentIndex++;
27707 }
27708 }
27709
27710 // using reverse iterator to remove from backwards
27711 for (auto ki = empty_entries.rbegin(); ki != empty_entries.rend(); ki ++)
27712 {
27713 AttachedPreprocessingInfoType* infoList = (*ki).first;
27714 int cidx= (*ki).second;
27715
27716 PreprocessingInfo* info = (*infoList)[cidx];
27717 ROSE_ASSERT (info==NULL);
27718
27719 // erase start+offset
27720 AttachedPreprocessingInfoType::iterator k = infoList->begin();
27721 infoList->erase(k+cidx);
27722// cout<<"debugging: direct erasing: info@"<< infoList<< " idx="<<cidx<<endl;
27723 retVal ++;
27724 }
27725 return retVal;
27726}
27727
27728//TODO: expose this to header file?
27729// We keep all things, including level : starting from 0. Later iteration ignore the level 0 directives.
27730// Should this be maintained by librose or user space code?
27731static std::unordered_map <PreprocessingInfo*, SageInterface::PreprocessingInfoData> infoMap;
27732
27733void SageInterface::preOrderCollectPreprocessingInfo(SgNode* current, vector<PreprocessingInfo*>& infoList, int depth)
27734{
27735 // stop condition
27736 if (current == NULL)
27737 return;
27738
27739 // Three possible locations: before, inside, and after
27740 // immediately add prepression info that is before and inside of current node
27741 // delayed additions of these that are located after the current node
27742 vector<PreprocessingInfo*> afterList;
27743 if (SgLocatedNode* locatedNode = isSgLocatedNode(current))
27744 {
27745 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
27746
27747 if (comments != nullptr)
27748 {
27749 AttachedPreprocessingInfoType::iterator i;
27750 int idx=0;
27751 for (i = comments->begin (); i != comments->end (); i++)
27752 {
27753 PreprocessingInfo* info= *i;
27754
27755 // prepare the data just in case
27757 data.container=comments;
27758 data.index = idx;
27759 data.depth = depth;
27760
27761 // put directives with before location into the infoList
27762 if (info->getRelativePosition () == PreprocessingInfo::before
27763 )
27764 {
27765 infoList.push_back (info);
27766 infoMap[info] = data;
27767 }
27768 // How about inside position?
27769 // why it should be intepreted as the last one after all inner statment's preprocessingInfo?
27770 // because if it should be unparsed before all of them, it should have been attached to the first stmt's before location instead!
27771 else if (info->getRelativePosition () == PreprocessingInfo::after
27772 || info->getRelativePosition () == PreprocessingInfo::inside
27773 )
27774 {
27775 afterList.push_back (info); // if attached to be after, save to afterList
27776 infoMap[info] = data;
27777 }
27778 else
27779 {
27780 mlog[Sawyer::Message::Common::WARN] <<"Warning: unhandled relative position value:" <<info->getRelativePosition () <<endl;
27781 // ROSE_ASSERT (false); // Jovial has end_of
27782 }
27783
27784 idx++;
27785 } // end for
27786 }
27787 } // end if
27788
27789 // handling children nodes
27790 std::vector<SgNode* > children = current->get_traversalSuccessorContainer();
27791 for (auto c: children)
27792 preOrderCollectPreprocessingInfo (c, infoList, depth +1);
27793
27794 // append after locations after recursively handling children nodes.
27795 for (auto fi : afterList)
27796 infoList.push_back(fi);
27797}
27798
27799// This may be expensive to run since it is called anytime replace() is called.
27801// We need to attach them to be after lnode, before we can safely remove lnode. So the inner preprocessing info. can be preserved properly.
27802// This should be done before removing or replace the statement: lnode
27803// TODO: this may need to be a recursive function for multiple levels of nested directives.
27804//
27805// We only care about directives attached to inner nodes, not lnode : TODO: double check this for corner cases
27806//
27808{
27809 int retVal=0;
27810 ROSE_ASSERT(lnode);
27811
27812// algorithm: using a queue (vector to simulate it)
27813// queue <PreProcessingInfo* > q;
27814// start from 2nd node: ignore the first root node
27815// if start preprocessing info: (if, ifndef, ifdef), push to the end of q
27816// if end of preprocessing info. (endif), neturalize possible end p info at the end of q, otherwise push it to the end
27817//
27818// the queue in the end may contain mixed preprocessing info. #endif #endif ... #if #ifndef
27819// They cannot neutralize each other.
27820// They should be attached to be after lnode !
27821 RoseAst ast(lnode);
27822 RoseAst::iterator ast_i=ast.begin();
27823 ++ast_i; // skip the root node itself
27824
27825 // we store both the container and the element's index within the container. so later we can easily remove elements from containers
27826 vector < pair< AttachedPreprocessingInfoType*, int> > keepers; // preprocessing info. to be kept
27827 // for the middle directives like #else or #elif, sometimes their status (balanced or not) is directly associatd with its preceeding begin directive
27828 // it is not always an independent decision.
27829 // Note : the association is between individual preprocessing info. however, to faciliate removing them, the second part uses InfoList vs offset
27830 unordered_map < PreprocessingInfo * , vector< pair<AttachedPreprocessingInfoType*, int>> > associated_directives;
27831
27832 // store the associated middle directives what should be erased in the end
27833 // we have to store this separatedly since the begin diretive pinfo becomes NULL after they have been erased!
27834 // associated_directives[BeginInfo] will not retrieve them!
27835 vector< pair<AttachedPreprocessingInfoType*, int>> associated_erase;
27836
27837 // Two steps here
27838 // Step 1: We build the list first, then go through them to neutralize them
27839 // to simplify the problem: we exclude comments attached to the current located node, only consider things inside
27840 //
27841 // The list must provide the following information
27842 // infoList (container), index of the directive, PreprocessingInfo* itself
27843 vector<PreprocessingInfo*> candidateInfoList;
27844 // recursively search all directives, preserving original order in AST, consider attachment locations: before, inside and after.
27845 preOrderCollectPreprocessingInfo (lnode, candidateInfoList, 0);
27846 // now we have both candidateInfoList and infoMap.
27847
27848 for (auto candidate: candidateInfoList)
27849 {
27850 // fundamentally, we want to move individual PreprocessingInfo objects
27851 // Or just duplicate them (easier)
27852 PreprocessingInfo * info = candidate;
27853
27854 // we skip candidate that is attached to a node with depth of 0 (root node of the subtree)
27855 if (infoMap[info].depth ==0)
27856 continue;
27857
27858 int commentIndex = infoMap[info].index;
27859 AttachedPreprocessingInfoType* infoList = infoMap[info].container;
27860
27861 // begin directives
27862 if ( isBeginDirective(info) == 1)
27863 {
27864 keepers.push_back(make_pair (infoList,commentIndex));
27865 }
27866 // the middle #else, #elif,
27867 else if (isBeginDirective(info) == 2)
27868 {
27869 // two situtations for immediate decision of unbalanced status
27870 //1. empty stack, or
27871 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27872 if (keepers.size()==0)
27873 keepers.push_back(make_pair (infoList, commentIndex));
27874 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27875 {
27876 keepers.push_back(make_pair (infoList,commentIndex));
27877 }
27878 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27879 {
27880 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27881 // we associated this middle directive with the beginning directive
27882 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27883 }
27884 }
27885 // end directive
27886 else if ( isBeginDirective(info) == -1)
27887 {
27888 bool neutralized = false;
27889 // neutralize an internall matched pair, if any
27890 if (keepers.size()>0)
27891 {
27892 AttachedPreprocessingInfoType* comments = keepers.back().first;
27893 int idx = keepers.back().second;
27894
27895 if(isBeginDirective( (*comments)[idx] )==1)
27896 {
27897 keepers.pop_back();
27898 neutralized = true;
27899 }
27900 }
27901
27902 if (!neutralized)
27903 keepers.push_back(make_pair (infoList,commentIndex));
27904 }
27905
27906 }
27907
27908#if 0 // old and wrong linear search of directives
27909
27910 // Then we go through the list, extract keepers, neutralize anything else.
27911 for(;ast_i!=ast.end();++ast_i) {
27912 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27913 if (current ==NULL ) // skip non located nodes
27914 continue;
27915
27916 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27917 if (infoList == NULL) continue;
27918
27919 int commentIndex=0;
27920 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27921 {
27922 ROSE_ASSERT(*ci != NULL);
27923 // fundamentally, we want to move individual PreprocessingInfo objects
27924 // Or just duplicate them (easier)
27925 PreprocessingInfo * info = *ci;
27926
27927 // begin directives
27928 if ( isBeginDirective(info) == 1)
27929 {
27930 keepers.push_back(make_pair (infoList,commentIndex));
27931 }
27932 // the middle #else, #elif,
27933 else if (isBeginDirective(info) == 2)
27934 {
27935 // two situtations for immediate decision of unbalanced status
27936 //1. empty stack, or
27937 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27938 if (keepers.size()==0)
27939 keepers.push_back(make_pair (infoList,commentIndex));
27940 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27941 {
27942 keepers.push_back(make_pair (infoList,commentIndex));
27943 }
27944 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27945 {
27946 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27947 // we associated this middle directive with the beginning directive
27948 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27949 }
27950 }
27951 // end directive
27952 else if ( isBeginDirective(info) == -1)
27953 {
27954 bool neutralized = false;
27955 // neutralize an internall matched pair, if any
27956 if (keepers.size()>0)
27957 {
27958 AttachedPreprocessingInfoType* comments = keepers.back().first;
27959 int idx = keepers.back().second;
27960
27961 if(isBeginDirective( (*comments)[idx] )==1)
27962 {
27963 keepers.pop_back();
27964 neutralized = true;
27965 }
27966 }
27967
27968 if (!neutralized)
27969 keepers.push_back(make_pair (infoList,commentIndex));
27970 }
27971 commentIndex++;
27972 }
27973 }
27974#endif
27975// TODO this variable is not used in the end.
27976 set <AttachedPreprocessingInfoType*> relatedInfoList; // containers with comments to be moved
27977 // 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!
27978 // move from old containers, and add into lnode's after position
27979 for (auto ki = keepers.begin(); ki != keepers.end(); ki ++)
27980 {
27981 AttachedPreprocessingInfoType* infoList = (*ki).first;
27982 int cidx= (*ki).second;
27983 // TODO replace the code block below with moveInofListToNewPlace()
27984 relatedInfoList.insert (infoList);
27985
27986 PreprocessingInfo* info = (*infoList)[cidx];
27987 // rewrite relative position
27988 info->setRelativePosition(PreprocessingInfo::after);
27989
27990 // insert after lnode
27991 lnode->addToAttachedPreprocessingInfo (info);
27992 retVal++;
27993
27994 // we additionally process the associated directives, if any, TODO: reverse processing also??
27995 if (associated_directives.count (info)!=0)
27996 {
27997 vector<pair<AttachedPreprocessingInfoType*,int>> a_list_vec = associated_directives[info];
27998 for (auto vec_i = a_list_vec.rbegin(); vec_i != a_list_vec.rend(); vec_i ++ )
27999 {
28000 AttachedPreprocessingInfoType* a_infoList = (*vec_i).first;
28001 int aidx= (*vec_i).second;
28002 moveInofListToNewPlace (a_infoList, aidx, relatedInfoList, lnode, retVal);
28003 associated_erase.push_back(make_pair (a_infoList, aidx));
28004 }
28005 } // each begin directive may associate multiple other middle directives
28006
28007 // Doing this after the associated directives are processed.
28008 // zero out from original list, Note this element slot is NULL now!
28009 (*infoList)[cidx]= NULL;
28010
28011 }
28013 return retVal;
28014}
to specify a construct using a specifier Can be used alone or with parent handles when relative speci...
virtual void * getNode() const
Get the raw IR node associated with the current abstract node.
Base class for all IR node attribute values.
Attribute Evaluator for synthesized attributes.
SynthesizedAttributeType traverse(SgNode *node)
evaluates attributes on the entire AST
Attribute storing an SgNode.
Class for traversing the AST.
void traverse(SgNode *node, Order treeTraversalOrder)
traverse the entire AST. Order defines preorder (preorder) or postorder (postorder) traversal....
void visit(SgNode *astNode)
this method is called at every traversed node.
void visit(SgNode *astNode)
visitor function for each node to collect non-builtin types' declarations
void visit(SgNode *astNode)
this method is called at every traversed node.
For preprocessing information including source comments, include , if, define, etc.
RelativePositionType
MK: Enum type to store if the directive goes before or after the corresponding line of source code.
AST iterator.
Definition RoseAst.h:54
Interface for iterating over an AST.
Definition RoseAst.h:26
iterator begin()
Iterator positioned at root of subtree.
iterator end()
Iterator positioned at the end of the traversal.
const Digest & digest() override
Return the digest.
void insert(const std::string &x)
Insert data into the digest.
uint64_t make64Bits()
Returns the hash as a 64 bit int.
void visit(SgNode *node)
this method is called at every traversed node.
Interface for creating a statement whose computation writes its answer into a given variable.
A persistent attribute to represent a unique name for an expression.
SgName get_name() const override
Access function for getting name from declarations or types internally.
Base class for binary files.
SgAsmGenericHeaderList *const & get_headers() const
Property: List of all headers in file.
SgAsmGenericHeaderPtrList const & get_headers() const
Property: List of file header nodes.
Base class for container file headers.
SgAsmInterpretationPtrList const & get_interpretations() const
Property: Interpretation list.
Represents an interpretation of a binary container.
This class represents the concept of a C Assembler statement.
This class represents the rhs of a variable declaration which includes an optional assignment (e....
void set_operand(SgExpression *exp)
This sets the rhs expression.
SgExpression * get_operand() const
Returns the rhs.
This class represents the concept of a block (not a basic block from control flow analysis).
const SgStatementPtrList & get_statements() const
Returns a const STL list by reference.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a binary operator. It is derived from a SgExpression because oper...
SgExpression * get_lhs_operand() const
returns SgExpression pointer to the lhs operand associated with this binary operator.
void set_rhs_operand(SgExpression *exp)
This function allows the p_rhs_operand pointer to be set (used internally).
void set_lhs_operand(SgExpression *exp)
This function allows the p_lhs_operand pointer to be set (used internally).
SgExpression * get_rhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
SgExpression * get_lhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
virtual VariantT variantT() const override
returns new style SageIII enum values
SgExpression * get_rhs_operand() const
returns SgExpression pointer to the rhs operand associated with this binary operator.
This class represents a boolean value (expression value).
This class represents the notion of a break statement (typically used in a switch statment).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a C and C++ case option (used within a switch statement).
SgStatement * get_body() const
Returns pointer to a SgBasicBlock object.
void set_key(SgExpression *key)
Access function for pointer to SgExpression object wrapped by SgExpressionRoot in p_key_root.
void set_body(SgStatement *body)
Access function for p_body.
SgExpression * get_key() const
Returns pointer to a SgExpression object wrapped by SgExpressionRoot in p_key_root.
This class represents a cast of one type to another.
SgType * get_type() const override
unparsing support for pragmas
This class represents the concept of a catch within a try-catch construct used in C++ exception handl...
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Access function for p_body.
This class represents the concept of a class declaration statement. It includes the concept of an ins...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgScopeStatement * get_scope() const override
Returns scope of current statement.
This class represents the concept of a class definition in C++.
SgClassDeclaration * get_declaration() const
returns the class declaration associated with this class decinition.
const SgDeclarationStatementPtrList & get_members() const
Returns a const list to the data member declarations.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a C++ expression built from a class name.
SgClassSymbol * get_symbol() const
Returns pointer to SgSymbol.
This class represents the concept of a class name within the compiler.
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
static SgClassType * createType(SgDeclarationStatement *decl=NULL, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgClassType (types whose constructors take par...
This class represents the concept of a C trinary conditional expression (e.g. "test ?...
SgExpression * get_true_exp() const
Access function for p_true_exp.
void set_false_exp(SgExpression *false_exp)
Access function for p_false_exp.
SgExpression * get_conditional_exp() const
Access function for p_conditional_exp.
SgExpression * get_false_exp() const
Access function for p_false_exp.
void set_true_exp(SgExpression *true_exp)
Access function for p_true_exp.
void set_conditional_exp(SgExpression *conditional_exp)
Access function for p_conditional_exp.
This class represents the call of a class constructor to initialize a variable. For example "Foo foo;...
SgType * get_expression_type() const
Access function for p_expression_type, returns pointer to SgType associated with constructor.
This class represents the concept of a C or C++ continue statement.
Supporting class from copy mechanism within ROSE.
Definition sageCopy.h:26
This class represents the concept of a contructor initializer list (used in constructor (member funct...
bool isFriend() const
declaration modifier is friend.
This class represents the concept of a declaration statement.
SgSymbol * search_for_symbol_from_symbol_table() const
User interface for retrieving the associated symbol from the declaration.
void set_definingDeclaration(SgDeclarationStatement *definingDeclaration)
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
void set_firstNondefiningDeclaration(SgDeclarationStatement *firstNondefiningDeclaration)
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
SgDeclarationStatement * get_definingDeclaration() const
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
bool isForward() const
Returns boolean value indicating if this is a forward declaration.
SgDeclarationStatement * get_firstNondefiningDeclaration() const
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool hasAssociatedSymbol() const
Returns boolean value true of this type of declaration has an associated sysmbol.
SgName get_template_name() const
This function returns the template name (taken from the template declaration for the class,...
This class represents the concept of a C or C++ default case within a switch statement.
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Returns pointer to SgBasicBlock.
This class represents a directory within a projects file structure of files and directories.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_condition(SgStatement *condition)
Access function for p_condition.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the notion of an value (expression value).
This class represents the concept of an enum declaration.
SgScopeStatement * get_scope() const override
Access function for p_scope.
SgName get_name() const
Access function for p_name.
void set_scope(SgScopeStatement *scope) override
Access function for p_scope.
const SgInitializedNamePtrList & get_enumerators() const
Access function for p_enumerators.
This class represents the concept of a C and C++ expression list.
int replace_expression(SgExpression *o, SgExpression *n) override
This class represents the base class of all the expressions within this grammar.
This class represents the concept of a C or C++ statement which contains a expression.
This class represents the notion of an expression. Expressions are derived from SgLocatedNodes,...
virtual std::string class_name() const override
returns a string representing the class name
void set_need_paren(bool need_paren)
This function allows the p_need_paren flag to be set (used internally).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgType * get_type() const
unparsing support for pragmas
virtual int replace_expression(SgExpression *oldChild, SgExpression *newChild)
This class represents the base class of all the expressions within this grammar.
virtual const char * sage_class_name() const override
virtual Sg_File_Info * get_file_info(void) const override
Interface function to implement original SAGE interface to SgFile_Info objects.
void set_lvalue(bool lvalue)
This function allows the p_lvalue flag to be set (used internally).
bool get_lvalue() const
Returns a bool value if the current expression is assigned to.
This class represents a source file for a project (which may contian many source files and or directo...
std::string getFileName() const
associated filename
Sg_File_Info * get_file_info() const override
Access function calling get_startOfConstruct(), provided to support older interface.
This class represents the notion of an value (expression value).
This class represents the variable declaration or variable initialization withn a for loop.
const SgStatementPtrList & get_init_stmt() const
Returns const reference to a SgStatementPtrList (typedef to a STL list).
This class represents the concept of a for loop.
SgExpression * get_test_expr() const
Access function for p_test_expr_root.
SgForInitStatement * get_for_init_stmt() const
Access function for p_for_init_stmt.
void set_loop_body(SgStatement *loop_body)
Access function for p_loop_body.
SgStatement * get_loop_body() const
Access function for p_loop_body.
void set_for_init_stmt(SgForInitStatement *for_init_stmt)
Access function for p_for_init_stmt.
This class represents the concept of a C++ function call (which is an expression).
SgFunctionSymbol * getAssociatedFunctionSymbol() const
Returns the associated function symbol, if it can be resolved statically.
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a function declaration statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool isTemplateFunction() const
Determines if function is a template or non-template function.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
virtual std::string class_name() const override
returns a string representing the class name
SgBasicBlock * get_body() const
Access function for p_body.
This class represents the concept of a declaration list.
const SgInitializedNamePtrList & get_args() const
Access function for p_args.
const SgTypePtrList & get_arguments() const
Get a const list of input types (types of the parameters list) to this function type (from a cost fun...
This class represents the function being called and must be assembled in the SgFunctionCall with the ...
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the function type table (stores all function types so that they can be shared i...
SgSymbolTable * get_function_type_table() const
Returns pointer to SgSymbolTable used for function type symbols only.
This class represents a type for all functions.
virtual std::string class_name() const override
returns a string representing the class name
const SgTypePtrList & get_arguments() const
This is a const convience access function to the STL container of types in the child IR node (SgFunct...
virtual SgName get_mangled(void) const override
Mangled name support for unparser support.
This class represents the concept of a namespace definition.
virtual std::string class_name() const override
returns a string representing the class name
const SgDeclarationStatementPtrList & get_declarations() const
Returns a const list to the global scope declarations.
This class represents the concept of a C or C++ goto statement.
SgLabelStatement * get_label() const
Returns pointer to SgLabelStatement where control flow will be transfered during execution.
void set_label(SgLabelStatement *label)
Access function for p_label.
InheritedAttributeType traverse(SgGraphNode *basenode, SgIncidenceDirectedGraph *g, InheritedAttributeType inheritedValue, InheritedAttributeType nullInherit, SgGraphNode *endnode, bool insep=false, bool pcHk=false)
This is the function that is used by the user directly to start the algorithm.
This class represents the concept of an "if" construct.
void set_false_body(SgStatement *false_body)
Access function for p_false_body.
virtual std::string class_name() const override
returns a string representing the class name
void set_true_body(SgStatement *true_body)
Access function for p_true_body.
SgStatement * get_conditional() const
Access function for p_conditional.
SgStatement * get_true_body() const
Access function for p_true_body.
SgStatement * get_false_body() const
Access function for p_false_body.
void set_conditional(SgStatement *conditional)
Access function for p_conditional.
This class represents the notion of a declared variable.
SgName get_qualified_name() const
Returns the name with appropriate qualified names representing nested scopes.
SgSymbol * get_symbol_from_symbol_table() const
Get the associated SgSymbol from the symbol table located in the scope, without considering possible ...
virtual std::string class_name() const override
returns a string representing the class name
SgDeclarationStatement * get_declaration() const
Equal operator : it checks if all the data members are the same or point to the same objects.
This class represents the notion of an initializer for a variable declaration or expression in a func...
This class represents the concept of a C or C++ label statement.
SgName get_label() const
Returns SgName by value.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
label_type_enum
Type of label used (fortran only)
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of an expression or statement which has a position within the source...
virtual std::string class_name() const override
returns a string representing the class name
virtual const char * sage_class_name() const override
Sg_File_Info * get_endOfConstruct() const override
New function interface for Sg_File_Info data stores ending location of contruct (typically the closin...
void setTransformation()
Allow IR nodes (mostly SgLocatedNode) to be marked as a transformation.
virtual void addNewAttribute(std::string s, AstAttribute *a) override
Add a new attribute represented by the named string.
void set_endOfConstruct(Sg_File_Info *endOfConstruct)
This function sets the current source location position of the end of the current construct.
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
void addToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo::RelativePositionType locationInList=PreprocessingInfo::after)
This function adds comment or CPP directives to the current IR node.
virtual AstAttribute * getAttribute(std::string s) const override
Returns attribute of name 's'.
void set_startOfConstruct(Sg_File_Info *startOfConstruct)
This function sets the current source location position of the start of the current construct.
bool isCompilerGenerated() const
Simple test for if this is a compiler generated node.
void insertToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo *anchorInfoPtr, bool insertAfter=true)
Insert prepInfo After (or before if last parameter is false) an anchor info ptr in the list of prepro...
virtual VariantT variantT() const override
returns new style SageIII enum values
void setOutputInCodeGeneration()
Allow IR nodes (mostly SgLocatedNode) to be marked as to when the information was unavilable in the f...
virtual Sg_File_Info * get_file_info() const override
Interface function to implement original SAGE interface to SgFile_Info objects.
bool isTransformation() const
Simple test for if this is a part of a transformation.
AttachedPreprocessingInfoType *& getAttachedPreprocessingInfo(void)
Computes the number of nodes in the defined subtree of the AST.
This class represents the notion of an value (expression value).
This class represents the concept of a member function declaration statement.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the member function being called and must be assembled in the SgFunctionCall wi...
SgMemberFunctionDeclaration * getAssociatedMemberFunctionDeclaration() const
This is helpful in chasing down the associated declaration to this member function reference.
SgName get_name() const override
Access function for getting name from declarations or types internally.
SgTypeModifier & get_typeModifier()
Access function for modifier.
This class represents strings within the IR nodes.
virtual SgName get_name() const
Gets name of the type (useful for debugging, unparsing, etc.)
SgName get_qualified_name() const
Used for the SgNamedType object (base class for the SgClassType, SgTypedefType and the SgEnumType obj...
This class represents the concept of a C++ namespace alias declaration statement.
SgName get_name() const
Access function for p_name.
SgNamespaceDeclarationStatement * get_namespaceDeclaration() const
Access function for p_namespaceDeclaration.
This class represents the concept of a C++ namespace declaration.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgName get_name() const
Access function for p_name.
SgNamespaceDefinitionStatement * get_definition() const
Returns pointer to SgNamespaceDefinitionStatement.
This class represents the concept of a namespace definition.
This class represents the concept of a namespace name within the compiler.
This class represents the base class for all IR nodes within Sage III.
static SgTypeTable * get_globalTypeTable()
Access function for symbol table specific to non-function types.
virtual std::vector< std::string > get_traversalSuccessorNamesContainer() const
container of names of variables or container indices used used in the traversal to access AST success...
SgNode * get_parent() const
Access function for parent node.
void set_isModified(bool isModified)
All nodes in the AST contain a isModified flag used to track changes to the AST.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() const
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
virtual VariantT variantT() const
returns new style SageIII enum values
void set_parent(SgNode *parent)
All nodes in the AST contain a reference to a parent node.
virtual std::string unparseToString(SgUnparse_Info *info) const
This function unparses the AST node (excluding comments and unnecessary white space)
virtual std::string class_name() const
returns a string representing the class name
static std::map< SgNode *, std::string > & get_globalMangledNameMap()
Access function for performance optimizing global mangled name map.
virtual void checkDataMemberPointersIfInMemoryPool()
FOR INTERNAL USE This is used in internal tests to verify that all IR nodes are allocated from the he...
virtual AstAttribute * getAttribute(std::string s) const
Returns attribute of name 's'.
static SgFunctionTypeTable * get_globalFunctionTypeTable()
Access function for symbol table specific to function types.
virtual Sg_File_Info * get_file_info(void) const
File information containing filename, line number, column number, and if the SgNode is a part of a ne...
virtual bool attributeExists(std::string s) const
Tests if attribute of name 's' is present.
virtual std::vector< std::pair< SgNode *, std::string > > returnDataMemberPointers() const
FOR INTERNAL USE Returns STL vector of pairs of SgNode* and strings for use in AST tools
virtual void addNewAttribute(std::string s, AstAttribute *a)
Add a new attribute represented by the named string.
static std::map< std::string, uint64_t > & get_shortMangledNameCache()
Access function for lower level optimizing of global mangled name map.
bool get_isModified() const
Acess function for isModified flag.
SgName get_name() const override
Support for some classes which have pure virtual function in base classes.
This class represents the concept of a C Assembler statement (untested).
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents a source project, with a list of SgFile objects and global information about th...
std::vector< std::string > getAbsolutePathFileNames() const
This function generates a list of files resolved to absolute paths (symbolic links should not be reso...
static void visitRepresentativeNode(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for type-based traversal.
static int get_verbose(void)
DQ: Modified to accept a value on the command line (no longer a boolean variable) value of 0 means qu...
This class represents a OLD concept of the structure require for qualified names when they were in th...
This class represents the concept of a C Assembler statement (untested).
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
bool supportsDefiningFunctionDeclaration()
Reports if scope can support defining function declarations. Not all scopes permit function declarati...
const SgStatementPtrList generateStatementList() const
Generate s list of statements from either the existing list of statements or the list of declarations...
bool isNamedScope()
Some scopes have associated names for purposed of name qualification. This returns true if the scope ...
SgSymbolTable * get_symbol_table() const
Returns a pointer to the locally strored SgSymbolTable.
virtual const char * sage_class_name() const override
SgDeclarationStatementPtrList & getDeclarationList()
Gets reference to internal STL list of pointers to SgDeclarationStatement objects (only defined for s...
SgStatementPtrList & getStatementList()
Gets reference to internal STL list of pointers to SgStatement objects (only defined for scopes conta...
void append_statement(SgStatement *stmt)
Higher level function to handle statements and declarations is scopes.
void set_symbol_table(SgSymbolTable *symbol_table)
Sets the pointer to the locally strored SgSymbolTable.
virtual std::string class_name() const override
returns a string representing the class name
bool statementExistsInScope(SgStatement *statement)
Test for existence of statement is scope.
bool containsOnlyDeclarations() const
This function is used to indicate if either the getDeclarationList() or getStatementList() can be cal...
void insert_symbol(const SgName &n, SgSymbol *s)
Puts a SgSymbol object into the local symbol table.
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgName get_qualified_name() const
Returns SgName (a string) representing the name of the current scope.
This class represents the "sizeof()" operator (applied to any type).
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a statement.
virtual std::string class_name() const override
returns a string representing the class name
void insert_statement(SgStatement *target, SgStatement *newstmt, bool inFront=true)
This function inserts a single statement at the position indicated by target.
virtual void set_scope(SgScopeStatement *newScope)
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual bool hasExplicitScope() const
Support for where the scope is explicitly required.
virtual SgSymbol * get_symbol_from_symbol_table() const
Get the associated symbol from the symbol table in the stored scope.
virtual SgScopeStatement * get_scope(void) const
Returns scope of current statement.
void remove_statement(SgStatement *)
This function removes the target statement from the AST.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() const override
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
void replace_statement(SgStatement *target, SgStatement *newstmt)
This function replaces the target statement with a single statement.
virtual VariantT variantT() const override
returns new style SageIII enum values
bool isStatic() const
Storage modifier is static (always false for the SgStorageModifier in the SgInitializedName).
This class represents the base class of a numbr of IR nodes that don't otherwise fit into the existin...
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a switch.
void set_item_selector(SgStatement *item_selector)
Access function for p_item_selector.
SgStatement * get_body() const
Access function for p_body.
SgStatement * get_item_selector() const
Access function for p_item_selector_root.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the symbol tables used in both SgScopeStatement and the SgFunctionTypeSymbolTab...
std::set< SgNode * > get_symbols() const
Complexity O(n)
void print(std::string label, VariantT nodeType=V_SgSymbol)
Outputs symbol table information (useful for debugging)
int size() const
Computes the number of symbols in the symbol table (forced to count them, I think,...
void remove(const SgSymbol *symbol)
Complexity O(n)
This class represents the concept of a name within the compiler.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgName get_name() const =0
Access function for getting name from declarations or types internally.
virtual SgType * get_type() const =0
This function returns the type associated with the named entity.
This class represents template argument within the use of a template to build an instantiation.
SgExpression * get_expression() const
This function returns argumentExpression.
SgType * get_type() const
This function returns argumentType.
SgTemplateArgument::template_argument_enum get_argumentType() const
This function returns argumentType.
This class represents the concept of a template declaration.
SgName get_string() const
Returns stringified template declaration.
virtual std::string class_name() const override
returns a string representing the class name
SgName get_name() const
Returns name of template declaration.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of an instantiated class template.
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgName get_templateName() const
Returns name of class template, the name excludes template arguments.
SgTemplateClassDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
This class represents the concept of a class definition in C++.
This class represents the concept of a C++ template instantiation directive.
SgDeclarationStatement * get_declaration() const
Returns pointer to SgDeclarationStatement.
This class represents the concept of an instantiation of function template.
virtual std::string class_name() const override
returns a string representing the class name
const SgTemplateArgumentPtrList & get_templateArguments() const
Returns pointer to STL list of pointers to SgTemplateArgument objects.
SgTemplateFunctionDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
SgName get_templateName() const
Returns name of instantiated function template, name includes template arguments.
This class represents the concept of an instantiation of member function template or a member functio...
virtual std::string class_name() const override
returns a string representing the class name
const SgTemplateArgumentPtrList & get_templateArguments() const
Returns pointer to STL list of pointers to SgTemplateArgument objects.
SgName get_templateName() const
Returns name of instantiated function template, name includes template arguments.
SgTemplateMemberFunctionDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the "this" operator (can be applied to any member data).
Supporting class for "Deep" copies of the AST.
Definition sageCopy.h:86
static SgTypeBool * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
static SgTypeInt * createType(int sz=0, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgTypeInt (types whose constructors take param...
static SgTypeUnknown * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
static SgTypeVoid * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
This class represents the base class for all types.
std::vector< SgType * > getInternalTypes() const
Generate a container of types hidden in the input type.
SgType * stripType(unsigned char bit_array=STRIP_MODIFIER_TYPE|STRIP_REFERENCE_TYPE|STRIP_RVALUE_REFERENCE_TYPE|STRIP_POINTER_TYPE|STRIP_ARRAY_TYPE|STRIP_TYPEDEF_TYPE|STRIP_POINTER_MEMBER_TYPE) const
Returns hidden type beneath layers of typedefs, pointers, references, modifiers, array representation...
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of a typedef declaration.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgDeclarationStatement * get_baseTypeDefiningDeclaration() const
Returns the defining declaration if get_typedefBaseTypeContainsDefiningDeclaration() is true,...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
SgType * get_base_type() const
This is used in the SgTypedefType object (is not associated with a base_type data field)
void set_operand_i(SgExpression *operand_i)
This function allows the p_operand_i pointer to be set (used internally).
SgExpression * get_operand() const
returns SgExpression pointer to the operand associated with this unary operator.
This class represents the concept of a C++ using declaration.
SgDeclarationStatement * get_declaration() const
Access function for p_declaration.
SgInitializedName * get_initializedName() const
Access function for p_initializedName.
This class represents the concept of a C++ using directive.
SgNamespaceDeclarationStatement * get_namespaceDeclaration() const
Access function for p_namespaceDeclaration.
This class represents the notion of an value (expression value).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
This class represents the variable refernece in expressions.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the concept of a C or C++ variable declaration.
const SgInitializedNamePtrList & get_variables() const
Access function for p_variables.
SgDeclarationStatement * get_baseTypeDefiningDeclaration() const
Returns the defining declaration if get_variableDeclarationContainsBaseTypeDefiningDeclaration() is t...
bool get_variableDeclarationContainsBaseTypeDefiningDeclaration() const
Access function for p_variableDeclarationContainsBaseTypeDefiningDeclaration.
This class represents the definition (initialization) of a variable.
SgInitializedName * get_vardefn() const
Access function for SgInitializedName stored in p_vardefn.
This class represents the concept of a variable name within the compiler (a shared container for the ...
virtual std::string class_name() const override
returns a string representing the class name
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
void set_condition(SgStatement *condition)
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the location of the code associated with the IR node in the original source cod...
void setTransformation()
Marks an IR node to be a transformation if it is not one already.
const char * get_filename() const
Returns filename of source code associated with IR node.
bool isOutputInCodeGeneration() const
Returns true only if required to be unparsed in generated code.
int get_line() const
Returns the line number of the associated code for this IR node.
bool isCompilerGenerated() const
Returns true only if compiler generated (either by the front-end or by ROSE).
int get_col() const
Returns the column number of the associated code for this IR node.
static Sg_File_Info * generateDefaultFileInfoForTransformationNode()
Static function to return new Sg_File_Info object set to default values appropriate for transformatio...
bool isTransformation() const
Access function for classification bit field.
bool isShared() const
Returns true only if shared internally (either by the front-end or by ROSE).
static Sg_File_Info * generateDefaultFileInfo()
Static function to return new Sg_File_Info object set to default values.
void setOutputInCodeGeneration()
Marks IR node as compiler generated but required in the generated source (e.g. requied templates).
Hash table support for symbol tables within ROSE.
ROSE_DLL_API abstract_handle * buildAbstractHandle(SgNode *snode)
A default builder function handles all details: file use name, others use numbering
ROSE_DLL_API std::vector< std::string > generateSourceFilenames(std::vector< std::string > argList, bool binaryMode)
Build the list of isolated file names from the command line.
ROSE_UTIL_API void removeAllFileNamesExcept(std::vector< std::string > &argv, std::vector< std::string > filenameList, std::string exceptFilename)
Remove file names specified in filenameList from argv, except for 'exceptFilename'.
void edgePointerReplacement(replacement_map_t const &)
For all nodes in the memory pool, it looks for the edges in the replacement map. If a match is found ...
ROSE_DLL_API std::string toBase62String(uint64_t num)
Converts a 64 bit in to base 62 (All letters and numbers).
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
Definition sageBuilder.C:58
void serialize(std::ostream &output, Graph &graph)
Serialize a graph into a stream of bytes.
ROSE_UTIL_API std::string stripFileSuffixFromFileName(const std::string &fileNameWithSuffix)
Get the file name without the ".suffix".
ROSE_UTIL_API std::string numberToString(long long)
Convert an integer to a string.
ROSE_UTIL_API std::string copyEdit(const std::string &inputString, const std::string &oldToken, const std::string &newToken)
Replace all occurrences of a string with another string.
ROSE_UTIL_API std::string stripPathFromFileName(const std::string &fileNameWithPath)
Returns the last component of a path in a filesystem.
The ROSE library.
SgStatement * getPreviousStatement(SgStatement *targetStatement, bool climbOutScope=true)
Functions to move to SgStatement object in SAGE III later.
Functions that build an AST.
Definition sageBuilder.h:32
ROSE_DLL_API SgAddOp * buildAddOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgFunctionDeclaration * buildNondefiningFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope=NULL, SgExprListExp *decoratorList=NULL, bool buildTemplateInstantiation=false, SgTemplateArgumentPtrList *templateArgumentsList=NULL, SgStorageModifier::storage_modifier_enum sm=SgStorageModifier::e_default)
Build a prototype for a function, handle function type, symbol etc transparently.
SourcePositionClassification
intended to be a private member, don't access it directly. could be changed any time
@ e_sourcePosition_last
Specify as source position to be filled in as part of AST construction in the front-end.
@ e_sourcePositionNullPointers
Classify as compiler generated code (e.g. template instantiation).
@ e_sourcePositionCompilerGenerated
Classify as a transformation.
@ e_sourcePositionFrontendConstruction
Set pointers to Sg_File_Info objects to NULL.
@ e_sourcePositionDefault
Error value for enum.
@ e_sourcePositionTransformation
Default source position.
ROSE_DLL_API SgPragma * buildPragma(const std::string &name)
Build SgPragma.
ROSE_DLL_API SourcePositionClassification getSourcePositionClassificationMode()
Get the current source position classification (defines how IR nodes built by the SageBuilder interfa...
ROSE_DLL_API SgEqualityOp * buildEqualityOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgTemplateMemberFunctionDeclaration * buildNondefiningTemplateMemberFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope, SgExprListExp *decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList *templateParameterList)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgLabelStatement * buildLabelStatement(const SgName &name, SgStatement *stmt=NULL, SgScopeStatement *scope=NULL)
Build a label statement, name is the label's name. Handling label symbol and scope internally.
ROSE_DLL_API SgAddressOfOp * buildAddressOfOp(SgExpression *op=NULL)
ROSE_DLL_API SgTemplateFunctionDeclaration * buildNondefiningTemplateFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope=NULL, SgExprListExp *decoratorList=NULL, SgTemplateParameterPtrList *templateParameterList=NULL)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgMultiplyOp * buildMultiplyOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgGotoStatement * buildGotoStatement(SgLabelStatement *label=NULL)
Build a goto statement.
ROSE_DLL_API std::string display(SourcePositionClassification &scp)
display function for debugging
ROSE_DLL_API SgLabelRefExp * buildLabelRefExp(SgLabelSymbol *s)
Build a Fortran numeric label ref exp.
ROSE_DLL_API SgLessOrEqualOp * buildLessOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgSubtractOp * buildSubtractOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgMemberFunctionType * buildMemberFunctionType(SgType *return_type, SgFunctionParameterTypeList *typeList, SgScopeStatement *struct_name, unsigned int mfunc_specifier)
Built in simple types.
ROSE_DLL_API SgWhileStmt * buildWhileStmt(SgStatement *condition, SgStatement *body, SgStatement *else_body=NULL)
Build while statement.
ROSE_DLL_API SgForStatement * buildForStatement(SgStatement *initialize_stmt, SgStatement *test, SgExpression *increment, SgStatement *loop_body, SgStatement *else_body=NULL)
Build a for statement, assume none of the arguments is NULL.
ROSE_DLL_API SgEmptyDeclaration * buildEmptyDeclaration()
Build an empty declaration (useful for adding precission to comments and CPP handling under token-bas...
ROSE_DLL_API SgConditionalExp * buildConditionalExp(SgExpression *test=NULL, SgExpression *a=NULL, SgExpression *b=NULL)
Build a conditional expression ?:
ROSE_DLL_API SgTypeInt * buildIntType()
Built in simple types.
SourcePositionClassification SourcePositionClassificationMode
C++ SageBuilder namespace specific state for storage of the source code position state (used to contr...
ROSE_DLL_API SgMinusOp * buildMinusOp(SgExpression *op=NULL)
ROSE_DLL_API SgExprListExp * buildExprListExp(SgExpression *expr1=NULL, SgExpression *expr2=NULL, SgExpression *expr3=NULL, SgExpression *expr4=NULL, SgExpression *expr5=NULL, SgExpression *expr6=NULL, SgExpression *expr7=NULL, SgExpression *expr8=NULL, SgExpression *expr9=NULL, SgExpression *expr10=NULL)
Build a SgExprListExp, used for function call parameter list etc.
ROSE_DLL_API SgPlusAssignOp * buildPlusAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgVarRefExp * buildVarRefExp(const SgName &name, SgScopeStatement *scope=NULL)
Build SgVarRefExp based on a variable's Sage name. It will lookup the name in the symbol table intern...
bool symbol_table_case_insensitive_semantics
Support for construction of case sensitive/insensitive symbol table handling in scopes.
ROSE_DLL_API SgDotExp * buildDotExp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgAssignInitializer * buildAssignInitializer(SgExpression *operand_i=NULL, SgType *expression_type=NULL)
Build the rhs of a variable declaration which includes an assignment.
ROSE_DLL_API SgArrayType * getUniqueJavaArrayType(SgType *, int)
Build a SgFile node and attach it to SgProject.
ROSE_DLL_API SgVariableDeclaration * buildVariableDeclaration(const SgName &name, SgType *type, SgInitializer *varInit=NULL, SgScopeStatement *scope=NULL)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgScopeStatement * topScopeStack()
intended to be a private member, don't access it directly. could be changed any time
ROSE_DLL_API SgNullExpression * buildNullExpression()
Build a null expression, set file info as the default one.
ROSE_DLL_API SgGreaterOrEqualOp * buildGreaterOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgReferenceType * buildReferenceType(SgType *base_type=nullptr)
Build a reference type.
ROSE_DLL_API SgExprStatement * buildExprStatement(SgExpression *exp=NULL)
Build a SgExprStatement, set File_Info automatically.
ROSE_DLL_API SgIfStmt * buildIfStmt(SgStatement *conditional, SgStatement *true_body, SgStatement *false_body)
Build if statement.
ROSE_DLL_API SgFunctionParameterList * buildFunctionParameterList(SgInitializedName *in1=NULL, SgInitializedName *in2=NULL, SgInitializedName *in3=NULL, SgInitializedName *in4=NULL, SgInitializedName *in5=NULL, SgInitializedName *in6=NULL, SgInitializedName *in7=NULL, SgInitializedName *in8=NULL, SgInitializedName *in9=NULL, SgInitializedName *in10=NULL)
Build an empty SgFunctionParameterList, possibly with some initialized names filled in.
ROSE_DLL_API SgPointerDerefExp * buildPointerDerefExp(SgExpression *op=NULL)
ROSE_DLL_API SgTypeBool * buildBoolType()
Built in simple types.
ROSE_DLL_API SgAssignOp * buildAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgPointerType * buildPointerType(SgType *base_type=nullptr)
Build a pointer type.
ROSE_DLL_API SgBoolValExp * buildBoolValExp(int value=0)
Build a bool value expression, the name convention of SgBoolValExp is little different from others fo...
ROSE_DLL_API SgName appendTemplateArgumentsToName(const SgName &name, const SgTemplateArgumentPtrList &templateArgumentsList)
DQ (7/27/2012): changed semantics from removing the template arguments in names to adding the templat...
ROSE_DLL_API SgFunctionParameterTypeList * buildFunctionParameterTypeList(SgFunctionParameterList *paralist)
Build SgFunctionParameterTypeList from SgFunctionParameterList.
ROSE_DLL_API SgLessThanOp * buildLessThanOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgCastExp * buildCastExp(SgExpression *operand_i=NULL, SgType *expression_type=NULL, SgCastExp::cast_type_enum cast_type=SgCastExp::e_C_style_cast)
Build a type casting expression.
ROSE_DLL_API SgMinusAssignOp * buildMinusAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgDivideOp * buildDivideOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgBasicBlock * buildBasicBlock(SgStatement *stmt1=NULL, SgStatement *stmt2=NULL, SgStatement *stmt3=NULL, SgStatement *stmt4=NULL, SgStatement *stmt5=NULL, SgStatement *stmt6=NULL, SgStatement *stmt7=NULL, SgStatement *stmt8=NULL, SgStatement *stmt9=NULL, SgStatement *stmt10=NULL)
Build a SgBasicBlock, setting file info internally.
ROSE_DLL_API SgModOp * buildModOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgExprStatement * buildAssignStatement(SgExpression *lhs, SgExpression *rhs)
Build an assignment statement from lefthand operand and right hand operand.
ROSE_DLL_API SgMemberFunctionDeclaration * buildNondefiningMemberFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope, SgExprListExp *decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList *templateArgumentsList)
Build a prototype member function declaration.
ROSE_DLL_API SgMemberFunctionDeclaration * buildDefaultConstructor(SgClassType *classType)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgCommaOpExp * buildCommaOpExp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgIntVal * buildIntVal(int value=0)
Build an integer value expression.
SgDeclarationStatement * associatedDeclaration(const SgSymbol &n)
returns the associated declaration for symbol n or nullptr if there is none.
Functions that are useful when operating on the AST.
Definition sageBuilder.h:25
ROSE_DLL_API void checkSgNodePointers()
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool isLastStatement(SgStatement *stmt)
Check if a statement is the last statement within its closed scope.
ROSE_DLL_API bool isUnionDeclaration(SgNode *node)
Check if a SgNode is a declaration for a union.
ROSE_DLL_API void translateScopeToUseCppDeclarations(SgScopeStatement *scope)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
void initializeIfStmt(SgIfStmt *ifstmt, SgStatement *conditional, SgStatement *true_body, SgStatement *false_body)
Support function used for variable declarations in conditionals.
ROSE_DLL_API void deepDelete(SgNode *root)
Deep delete a sub AST tree. It uses postorder traversal to delete each child node....
void annotateExpressionsWithUniqueNames(SgProject *project)
Generate unique names for expressions and attach the names as persistent attributes ("UniqueNameAttri...
ROSE_DLL_API bool hasMultipleInitStatmentsOrExpressions(SgForStatement *for_loop)
Check if a for loop uses C99 style initialization statement with multiple expressions like for (int i...
ROSE_DLL_API void fixNamespaceDeclaration(SgNamespaceDeclarationStatement *structDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
void serialize(SgNode *node, std::string &prefix, bool hasRemaining, std::ostringstream &out, std::string &edgeLabel)
we have two serialize() functions, one for a single node, the other for a list of pointers
ROSE_DLL_API void deleteExpressionTreeWithOriginalExpressionSubtrees(SgNode *root)
Special purpose function for deleting AST expression tress containing valid original expression trees...
void setSourcePositionAsTransformation(SgNode *node)
DQ (5/1/2012): New function with improved name.
ROSE_DLL_API void insertStatementList(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmts, bool insertBefore=true)
Insert a list of statements before or after the target statement within the.
void whereAmI(SgNode *node)
Diagnostic function for tracing back through the parent list to understand at runtime where in the AS...
ROSE_DLL_API SgStatement * getLastStatement(SgScopeStatement *scope)
get the last statement within a scope, return NULL if it does not exit
ROSE_DLL_API void addStepToLoopBody(SgScopeStatement *loopStmt, SgStatement *step)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API bool is_UPC_dynamic_threads()
ROSE_DLL_API SgFunctionDeclaration * getFunctionDeclaration(SgFunctionCallExp *functionCallExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_mixed_Fortran_and_C_language()
ROSE_DLL_API void addTextForUnparser(SgNode *astNode, std::string s, AstUnparseAttribute::RelativePositionType inputlocation)
Add a string to be unparsed to support code generation for back-end specific tools or compilers.
ROSE_DLL_API std::string getTempDirectory(SgProject *project)
Create a temporary directory if it does not yet exist and return its name.
ROSE_DLL_API void displayScope(SgScopeStatement *scope)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_Jovial_language()
ROSE_DLL_API SgMemberFunctionDeclaration * findJavaMain(SgClassDefinition *)
Find a main method in a Java class.
ROSE_DLL_API bool is_Cxx_language()
void resetScopeNumbers(SgFunctionDefinition *functionDeclaration)
Assigns unique numbers to each SgScopeStatement of a function.
ROSE_DLL_API SgFunctionDeclaration * replaceDefiningFunctionDeclarationWithFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool hasSameGlobalScope(SgStatement *statement_1, SgStatement *statement_2)
This is supporting the recognition of functions in header files from two different ASTs.
SgCommaOpExp * insertBeforeUsingCommaOp(SgExpression *new_exp, SgExpression *anchor_exp)
Insert an expression (new_exp )before another expression (anchor_exp) has possible side effects,...
ROSE_DLL_API void fixFunctionDeclaration(SgFunctionDeclaration *stmt, SgScopeStatement *scope)
Fix the symbol table and set scope (only if scope in declaration is not already set).
ROSE_DLL_API std::string preprocessImport(SgProject *, std::string)
Using the import_string parameter, create a file with the relevant import statement; translate the fi...
ROSE_DLL_API bool collectReadWriteRefs(SgStatement *stmt, std::vector< SgNode * > &readRefs, std::vector< SgNode * > &writeRefs, bool useCachedDefUse=false)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void prependStatementList(const std::vector< SgStatement * > &stmt, SgScopeStatement *scope=NULL)
prepend a list of statements to the beginning of the current scope, handling side effects as appropri...
ROSE_DLL_API SgInitializer * getInitializerOfExpression(SgExpression *n)
Get the initializer containing an expression if it is within an initializer.
ROSE_DLL_API std::vector< SgInitializedName * > getInParameters(const SgInitializedNamePtrList &params)
Get a vector of Jovial input parameters from the function parameter list (may work for Fortran in the...
ROSE_DLL_API bool language_may_contain_nondeclarations_in_scope()
ROSE_DLL_API std::set< SgStatement * > collectTransformedStatements(SgNode *node)
This collects the statements that are marked as transformed (useful in debugging).
ROSE_DLL_API void cleanupNontransformedBasicBlockNode()
Remove unused basic block IR nodes added as part of normalization.
ROSE_DLL_API bool skipTranslateToUseCppDeclaration(PreprocessingInfo *currentPreprocessingInfo)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API AbstractHandle::abstract_handle * buildAbstractHandle(SgNode *)
Build an abstract handle from an AST node, reuse previously built handle when possible.
ROSE_DLL_API void insertStatementListBefore(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmts)
Insert a list of statements before a target statement.
ROSE_DLL_API void fixStructDeclaration(SgClassDeclaration *structDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
void recursivePrintCurrentAndParent(SgNode *n)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void appendExpressionList(SgExprListExp *, const std::vector< SgExpression * > &)
Append an expression list to a SgExprListExp, set the parent pointers also.
ROSE_DLL_API void collectReadOnlySymbols(SgStatement *stmt, std::set< SgVariableSymbol * > &readOnlySymbols, bool coarseGrain=true)
Collect read only variable symbols within a statement. The statement can be either of a function,...
bool isOverloaded(SgFunctionDeclaration *functionDeclaration)
Return true if function is overloaded.
ROSE_DLL_API int set_name(SgInitializedName *initializedNameNode, SgName new_name)
set_name of symbol in symbol table.
ROSE_DLL_API SgClassDefinition * findOrInsertJavaPackage(SgProject *, std::string, bool create_directory=false)
Process a qualified package name, if needed, and return its package definition.
ROSE_DLL_API SgClassDeclaration * findOrImportJavaClass(SgProject *, SgClassDefinition *package_definition, std::string)
If the class_name already exists in the scope, return it.
ROSE_DLL_API SgVariableSymbol * getFirstVarSym(SgVariableDeclaration *decl)
Get the variable symbol for the first initialized name of a declaration stmt.
ROSE_DLL_API bool templateArgumentEquivalence(SgTemplateArgument *arg1, SgTemplateArgument *arg2)
Verify that 2 SgTemplateArgument are equivalent (same type, same expression, or same template declara...
ROSE_DLL_API SgFunctionDeclaration * findFirstDefiningFunctionDecl(SgScopeStatement *scope)
Find the first defining function declaration statement in a scope.
ROSE_DLL_API bool is_Jvm_language()
void addMessageStatement(SgStatement *stmt, std::string message)
Function to add "C" style comment to statement.
ROSE_DLL_API bool isLoopIndexVariable(SgInitializedName *ivar, SgNode *subtree_root)
Check if a SgInitializedName is used as a loop index within a AST subtree This function will use a bo...
SgInitializedName & getFirstVariable(SgVariableDeclaration &vardecl)
convenience function that returns the first initialized name in a list of variable declarations.
void initializeSwitchStatement(SgSwitchStatement *switchStatement, SgStatement *item_selector, SgStatement *body)
Support function used for variable declarations in conditionals.
SgExprListExp * loopCollapsing(SgForStatement *target_loop, size_t collapsing_factor)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API void fixStatement(SgStatement *stmt, SgScopeStatement *scope)
A wrapper containing fixes (fixVariableDeclaration(),fixStructDeclaration(), fixLabelStatement(),...
ROSE_DLL_API SgStatement * copyStatement(SgStatement *s)
Deep copy a statement.
ROSE_DLL_API int eraseNullPreprocessingInfo(SgLocatedNode *lnode)
Dumps a located node's preprocessing information.
ROSE_DLL_API bool isCanonicalDoLoop(SgFortranDo *loop, SgInitializedName **ivar, SgExpression **lb, SgExpression **ub, SgExpression **step, SgStatement **body, bool *hasIncrementalIterationSpace, bool *isInclusiveUpperBound)
Check if a Fortran Do loop has a complete canonical form: Do I=1, 10, 1.
SgCommaOpExp * insertAfterUsingCommaOp(SgExpression *new_exp, SgExpression *anchor_exp, SgStatement **temp_decl=NULL, SgVarRefExp **temp_ref=NULL)
Insert an expression (new_exp ) after another expression (anchor_exp) has possible side effects,...
ROSE_DLL_API SgTemplateVariableSymbol * lookupTemplateVariableSymbolInParentScopes(const SgName &name, SgTemplateParameterPtrList *tplparams, SgTemplateArgumentPtrList *tplargs, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void moveUpPreprocessingInfo(SgStatement *stmt_dst, SgStatement *stmt_src, PreprocessingInfo::RelativePositionType src_position=PreprocessingInfo::undef, PreprocessingInfo::RelativePositionType dst_position=PreprocessingInfo::undef, bool usePrepend=false)
Identical to movePreprocessingInfo(), except for the stale name and confusing order of parameters....
ROSE_DLL_API SgStatement * lastStatementOfScopeWithTokenInfo(SgScopeStatement *scope, std::map< SgNode *, TokenStreamSequenceToNodeMapping * > &tokenStreamSequenceMap)
Used to support token unparsing (when the output the trailing token sequence).
ROSE_DLL_API void cutPreprocessingInfo(SgLocatedNode *src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType &save_buf)
Cut preprocessing information from a source node and save it into a buffer. Used in combination of pa...
ROSE_DLL_API bool normalizeForLoopTest(SgForStatement *loop)
Normalize a for loop's test expression i<x is normalized to i<= (x-1) and i>x is normalized to i>= (x...
bool declarationPreceedsDefinition(SgDeclarationStatement *nonDefiningDeclaration, SgDeclarationStatement *definingDeclaration)
Check if a defining declaration comes before of after the non-defining declaration.
ROSE_DLL_API bool isSameFunction(SgFunctionDeclaration *func1, SgFunctionDeclaration *func2)
Check if two function declarations refer to the same one. Two function declarations are the same when...
std::vector< SgVariableSymbol * > getSymbolsUsedInExpression(SgExpression *expr)
Find referenced symbols within an expression.
ROSE_DLL_API bool isStructDeclaration(SgNode *node)
Check if a SgNode is a declaration for a structure.
ROSE_DLL_API void moveVariableDeclaration(SgVariableDeclaration *decl, SgScopeStatement *target_scope)
Move a variable declaration to a new scope, handle symbol, special scopes like For loop,...
ROSE_DLL_API std::string preprocessPackage(SgProject *, std::string)
Using the package_name, create a file with a package statement, translate it in order to load the pac...
ROSE_DLL_API void setOneSourcePositionForTransformation(SgNode *root)
Set current node's source position as transformation generated.
NodeType * deepCopy(const NodeType *subtree)
A template function for deep copying a subtree. It is also used to create deepcopy functions with spe...
void clearMangledNameCache(SgGlobal *globalScope)
Support for faster mangled name generation (caching avoids recomputation).
std::vector< SgStatement * > getSwitchCases(SgSwitchStatement *sw)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
ROSE_DLL_API bool isScalarType(SgType *t)
Is this a scalar type?
ROSE_DLL_API void changeBreakStatementsToGotos(SgStatement *loopOrSwitch)
If the given statement contains any break statements in its body, add a new label below the statement...
ROSE_DLL_API SgFunctionDefinition * getEnclosingFunctionDefinition(SgNode *astNode, const bool includingSelf=false)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_CAF_language()
ROSE_DLL_API void printOutComments(SgLocatedNode *locatedNode)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void ReductionRecognition(SgForStatement *loop, std::set< std::pair< SgInitializedName *, OmpSupport::omp_construct_enum > > &results)
Recognize and collect reduction variables and operations within a C/C++ loop, following OpenMP 3....
ROSE_DLL_API bool loopUnrolling(SgForStatement *loop, size_t unrolling_factor)
Unroll a target loop with a specified unrolling factor. It handles steps larger than 1 and adds a fri...
ROSE_DLL_API void setLoopCondition(SgScopeStatement *loop, SgStatement *cond)
Set the condition statement of a loop, including While-loop, For-loop, and Do-While-loop.
bool ROSE_DLL_API isStatic(SgDeclarationStatement *stmt)
Check if a declaration has a "static' modifier.
PreprocessingInfo * attachComment(SgSourceFile *source_file, const std::string &content, PreprocessingInfo::DirectiveType directive_type=PreprocessingInfo::C_StyleComment, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before)
Build and attach comment onto the global scope of a source file.
ROSE_DLL_API SgClassDefinition * getEnclosingClassDefinition(SgNode *astnode, const bool includingSelf=false)
Get the closest class definition enclosing the specified AST node,.
ROSE_DLL_API bool mergeDeclarationAndAssignment(SgVariableDeclaration *decl, SgExprStatement *assign_stmt, bool removeAssignStmt=true)
Merge a variable assignment statement into a matching variable declaration statement....
ROSE_DLL_API void checkAccessPermissions(SgNode *)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API std::vector< SgFunctionDeclaration * > generateFunctionDefinitionsList(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API void replaceMacroCallsWithExpandedStrings(SgPragmaDeclaration *target)
Check if a pragma declaration node has macro calls attached, if yes, replace macro calls within the p...
std::string generateUniqueNameForUseAsIdentifier(SgDeclarationStatement *declaration)
Generate a useful name to support construction of identifiers from declarations.
ROSE_DLL_API bool isRestrictType(SgType *t)
Is this a restrict type?
ROSE_DLL_API std::string generateProjectName(const SgProject *project, bool supressSuffix=false)
Added mechanism to generate project name from list of file names.
ROSE_DLL_API void resetInternalMapsForTargetStatement(SgStatement *sourceStatement)
Reset internal data structures used for token-based unparsing and macro summaries based on modificati...
ROSE_DLL_API bool is_Cuda_language()
ROSE_DLL_API bool isLambdaCapturedVariable(SgVarRefExp *varRef)
check if a variable reference is this->a[i] inside of a lambda function
ROSE_DLL_API int instrumentEndOfFunction(SgFunctionDeclaration *func, SgStatement *s)
Instrument(Add a statement, often a function call) into a function right before the return points,...
ROSE_DLL_API SgInitializedName * getFirstInitializedName(SgVariableDeclaration *decl)
Get the first initialized name of a declaration statement.
void setSourcePositionPointersToNull(SgNode *node)
Set the source code positon for the current (input) node.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfDoWhile(SgDoWhileStmt *ws)
Check if the body of a 'do .. while' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void reportModifiedStatements(const std::string &label, SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API std::vector< SgInitializedName * > getOutParameters(const SgInitializedNamePtrList &params)
Get a vector of Jovial output parameters from the function parameter list (may work for Fortran in th...
ROSE_DLL_API void setSourcePositionForTransformation(SgNode *root)
Recursively set source position info(Sg_File_Info) as transformation generated.
ROSE_DLL_API SgGlobal * getGlobalScope(const SgNode *astNode)
Traverse back through a node's parents to find the enclosing global scope.
ROSE_DLL_API void insertStatementListAfter(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmt)
Insert a list of statements after a target statement.
ROSE_DLL_API bool isMain(const SgNode *node)
Check if a SgNode is a main() function declaration.
std::map< std::string, int > local_name_collision_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API void fixClassDeclaration(SgClassDeclaration *classDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
ROSE_DLL_API int collectVariableReferencesInArrayTypes(SgLocatedNode *root, Rose_STL_Container< SgNode * > &currentVarRefList)
Collect variable references in array types. The default NodeQuery::querySubTree() will miss variables...
SgBasicBlock * ensureBasicBlockAsBodyOfCaseOption(SgCaseOptionStmt *cs)
Check if the body of a 'case option' statement is a SgBasicBlock, create one if not.
void checkForInitializers(SgNode *node)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void removeUnusedLabels(SgNode *top, bool keepChild=false)
Remove labels which are not targets of any goto statements: its child statement is also removed by de...
ROSE_DLL_API SgProject * getProject()
Get the current SgProject IR Node.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfUpcForAll(SgUpcForAllStatement *fs)
Check if the body of a 'upc_forall' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API SgClassDeclaration * getEnclosingClassDeclaration(SgNode *astNode)
Get the closest class declaration enclosing the specified AST node,.
ROSE_DLL_API void insertStatement(SgStatement *targetStmt, SgStatement *newStmt, bool insertBefore=true, bool autoMovePreprocessingInfo=true)
Insert a statement before or after the target statement within the target's scope....
ROSE_DLL_API void listHeaderFiles(SgIncludeFile *includeFile)
return path prefix for subtree of include files.
ROSE_DLL_API void markSubtreeToBeUnparsedTreeTraversal(SgNode *root, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
void saveToPDF(SgNode *node, std::string filename)
Save AST into a pdf file. Start from a node to find its enclosing file node. The entire file's AST wi...
ROSE_DLL_API bool normalizeForLoopInitDeclaration(SgForStatement *loop)
Normalize loop init stmt by promoting the single variable declaration statement outside of the for lo...
void detectCycleInType(SgType *type, const std::string &from)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void deleteAST(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool statementCanBeTransformed(SgStatement *stmt)
If header file unparsing and token-based unparsing are used, then some statements in header files use...
ROSE_DLL_API SgStatement * getNextStatement(SgStatement *currentStmt)
Get next statement within the same scope of current statement.
ROSE_DLL_API std::set< SgLabelStatement * > findUnusedLabels(SgNode *top)
Find unused labels which are not targets of any goto statements.
ROSE_DLL_API void setExtern(SgDeclarationStatement *stmt)
Set a declaration as extern.
ROSE_DLL_API void deleteAllNodes()
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool templateArgumentListEquivalence(const SgTemplateArgumentPtrList &list1, const SgTemplateArgumentPtrList &list2)
Verify that 2 SgTemplateArgumentPtrList are equivalent.
ROSE_DLL_API LivenessAnalysis * call_liveness_analysis(SgProject *project, bool debug=false)
Call liveness analysis on an entire project.
ROSE_DLL_API void reportModifiedLocatedNodes(const std::string &label, SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void fixTemplateDeclaration(SgTemplateDeclaration *stmt, SgScopeStatement *scope)
Fix the symbol table and set scope (only if scope in declaration is not already set).
SgType * getBoolType(SgNode *n)
Get the right bool type according to C or C++ language input.
void clearSharedGlobalScopes(SgProject *project)
Collect all read and write references within stmt, which can be a function, a scope statement,...
void initializeWhileStatement(SgWhileStmt *whileStatement, SgStatement *condition, SgStatement *body, SgStatement *else_body)
Support function used for variable declarations in conditionals.
ROSE_DLL_API void setSourcePosition(SgNode *node)
Set the source code positon for the current (input) node.
ROSE_DLL_API void setPragma(SgPragmaDeclaration *decl, SgPragma *pragma)
Set a pragma of a pragma declaration. handle memory release for preexisting pragma,...
ROSE_DLL_API void insertStatementListBeforeFirstNonDeclaration(const std::vector< SgStatement * > &newStmts, SgScopeStatement *scope)
Insert statements before the first non-declaration statement in a scope. If the scope has no non-decl...
ROSE_DLL_API bool isPostfixOperator(SgExpression *exp)
Is an overloaded operator a postfix operator. (e.g. ).
ROSE_DLL_API SgStatement * findSurroundingStatementFromSameFile(SgStatement *targetStmt, bool &surroundingStatementPreceedsTargetStatement)
Supporting function to comment relocation in insertStatement() and removeStatement().
SgNamespaceDefinitionStatement * enclosingNamespaceScope(SgDeclarationStatement *declaration)
Find the enclosing namespace of a declaration.
ROSE_DLL_API SgStatement * getLoopBody(SgScopeStatement *loop)
Routines to get and set the body of a loop.
ROSE_DLL_API bool is_mixed_C_and_Cxx_language()
bool isStructurallyEquivalentAST(SgNode *tree1, SgNode *tree2)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API PreprocessingInfo * insertHeader(SgSourceFile *source_file, const std::string &header_file_name, bool isSystemHeader, bool asLastHeader)
Insert #include "filename" or #include <filename> (system header) onto the global scope of a source f...
void printAST2TextFile(SgNode *node, const char *filename, bool printType=true)
Pretty print AST horizontally, output to a specified text file. If printType is set to false,...
ROSE_DLL_API SgFunctionSymbol * lookupTemplateFunctionSymbolInParentScopes(const SgName &functionName, SgFunctionType *ftype, SgTemplateParameterPtrList *tplparams, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool is_language_case_insensitive()
ROSE_DLL_API void replaceStatement(SgStatement *oldStmt, SgStatement *newStmt, bool movePreprocessinInfo=false)
Replace a statement with another. Move preprocessing information from oldStmt to newStmt if requested...
ROSE_DLL_API void recordNormalizations(SgStatement *s)
Record where normalization have been done so that we can preform denormalizations as required for the...
ROSE_DLL_API bool loopInterchange(SgForStatement *loop, size_t depth, size_t lexicoOrder)
Interchange/permutate a n-level perfectly-nested loop rooted at 'loop' using a lexicographical order ...
void printAST(SgNode *node)
Pretty print AST horizontally, output to std output.
ROSE_DLL_API SgFunctionSymbol * lookupTemplateMemberFunctionSymbolInParentScopes(const SgName &functionName, SgFunctionType *ftype, SgTemplateParameterPtrList *tplparams, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool is_PHP_language()
ROSE_DLL_API bool isEqualToIntConst(SgExpression *e, int value)
Check if a SgIntVal node has a given value.
ROSE_DLL_API void insertStatementBeforeFirstNonDeclaration(SgStatement *newStmt, SgScopeStatement *scope, bool movePreprocessingInfo=true)
Insert a statement before the first non-declaration statement in a scope. If the scope has no non-dec...
ROSE_DLL_API SgFunctionSymbol * lookupFunctionSymbolInParentScopes(const SgName &functionName, SgScopeStatement *currentScope=NULL)
look up the first matched function symbol in parent scopes given only a function name,...
ROSE_DLL_API void appendStatementWithDependentDeclaration(SgDeclarationStatement *decl, SgGlobal *scope, SgStatement *original_statement, bool excludeHeaderFiles)
Append a copy ('decl') of a function ('original_statement') into a 'scope', include any referenced de...
ROSE_DLL_API bool insideHeader(SgLocatedNode *node)
Check if a node is from a header file.
ROSE_DLL_API void markSubtreeToBeUnparsed(SgNode *root, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isDataMemberReference(SgVarRefExp *varRefExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool collectReadWriteVariables(SgStatement *stmt, std::set< SgInitializedName * > &readVars, std::set< SgInitializedName * > &writeVars, bool coarseGrain=true)
Collect unique variables which are read or written within a statement. Note that a variable can be bo...
ROSE_DLL_API void constantFolding(SgNode *r)
Constant folding an AST subtree rooted at 'r' (replacing its children with their constant values,...
std::vector< SgBreakStmt * > findBreakStmts(SgStatement *code, const std::string &fortranLabel="")
Find break statements inside a particular statement, stopping at nested loops or switches.
ROSE_DLL_API SgFile * getEnclosingFileNode(SgNode *astNode)
get the SgFile node from current node
ROSE_DLL_API void setStatic(SgDeclarationStatement *stmt)
Set a declaration as static.
ROSE_DLL_API bool doLoopNormalization(SgFortranDo *loop)
Normalize a Fortran Do loop. Make the default increment expression (1) explicit.
ROSE_DLL_API SgFile * preprocessCompilationUnit(SgProject *, std::string, std::string, bool unparse=true)
Using the file_content string, create a file with the content in question; build its AST and add it t...
ROSE_DLL_API void removeLabeledGotos(SgNode *top)
Remove labeled goto statements.
std::map< SgNode *, std::string > local_node_to_name_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
std::vector< SgGotoStatement * > findGotoStmts(SgStatement *scope, SgLabelStatement *l)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
ROSE_DLL_API bool mergeDeclarationWithAssignment(SgVariableDeclaration *decl, SgExprStatement *assign_stmt)
Merge a declaration statement into a matching followed variable assignment. Callers should make sure ...
ROSE_DLL_API bool isAssignmentStatement(SgNode *_s, SgExpression **lhs=NULL, SgExpression **rhs=NULL, bool *readlhs=NULL)
Check if a SgNode _s is an assignment statement (any of =,+=,-=,&=,/=, ^=, etc)
ROSE_DLL_API void outputSharedNodes(SgNode *node)
Find a node by type using upward traversal.
bool ROSE_DLL_API isAncestor(SgNode *node1, SgNode *node2)
check if node1 is a strict ancestor of node 2. (a node is not considered its own ancestor)
ROSE_DLL_API SgScopeStatement * getEnclosingScope(SgNode *n, const bool includingSelf=false)
Get the enclosing scope from a node n.
ROSE_DLL_API SgNonrealSymbol * lookupNonrealSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API SgSwitchStatement * findEnclosingSwitch(SgStatement *s)
Find the closest switch outside a given statement (normally used for case and default statements)
ROSE_DLL_API void removeAllOriginalExpressionTrees(SgNode *top)
Set original expression trees to NULL for SgValueExp or SgCastExp expressions, so you can change the ...
ROSE_DLL_API std::vector< SgNode * > astIntersection(SgNode *original, SgNode *copy, SgCopyHelp *help=NULL)
Compute the intersection set for two ASTs.
ROSE_DLL_API bool isPrefixOperator(SgExpression *exp)
Is an overloaded operator a prefix operator (e.g. address operator X * operator&(),...
ROSE_DLL_API void setLhsOperand(SgExpression *target, SgExpression *lhs)
set left hand operand for binary expressions, transparently downcasting target expressions when neces...
ROSE_DLL_API std::vector< SgC_PreprocessorDirectiveStatement * > translateStatementToUseCppDeclarations(SgStatement *statement, SgScopeStatement *scope)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API int suggestNextNumericLabel(SgFunctionDefinition *func_def)
Suggest next usable (non-conflicting) numeric label value for a Fortran function definition scope.
ROSE_DLL_API std::set< SgStatement * > collectModifiedStatements(SgNode *node)
This collects the statements that are marked as modified (a flag automatically set by all set_* gener...
ROSE_DLL_API SgFunctionDeclaration * getEnclosingFunctionDeclaration(SgNode *astNode, const bool includingSelf=false)
Find the enclosing function declaration, including its derived instances like isSgProcedureHeaderStat...
SgFunctionDeclaration * findFunctionDeclaration(SgNode *root, std::string name, SgScopeStatement *scope, bool isDefining)
Topdown traverse a subtree from root to find the first function declaration matching the given name,...
ROSE_DLL_API bool isPrefixOperatorName(const SgName &functionName)
Check for proper names of possible prefix operators (used in isPrefixOperator()).
ROSE_DLL_API void setLoopStride(SgNode *loop, SgExpression *stride)
Set the stride(step) of a loop 's incremental expression, regardless the expression types (i+=s; i= i...
ROSE_DLL_API bool isInSubTree(SgExpression *subtree, SgExpression *exp)
Find a node by type using upward traversal.
ROSE_DLL_API bool forLoopNormalization(SgForStatement *loop, bool foldConstant=true)
Normalize a for loop, return true if successful.
unsigned long long getIntegerConstantValue(SgValueExp *expr)
Get the constant value from a constant integer expression; abort on everything else.
ROSE_DLL_API bool is_UPC_language()
ROSE_DLL_API void checkSymbolTables(SgNode *)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void updateDefiningNondefiningLinks(SgFunctionDeclaration *func, SgScopeStatement *scope)
Update defining and nondefining links due to a newly introduced function declaration....
ROSE_DLL_API SgNode * deepCopyNode(const SgNode *subtree)
Deep copy an arbitrary subtree.
SgBasicBlock * ensureBasicBlockAsBodyOfDefaultOption(SgDefaultOptionStmt *cs)
Check if the body of a 'default option' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void getLiveVariables(LivenessAnalysis *liv, SgForStatement *loop, std::set< SgInitializedName * > &liveIns, std::set< SgInitializedName * > &liveOuts)
get liveIn and liveOut variables for a for loop from liveness analysis result liv.
ROSE_DLL_API void resetModifiedLocatedNodes(const std::set< SgLocatedNode * > &modifiedNodeSet)
Use the set of IR nodes and set the isModified flag in each IR node to true.
ROSE_DLL_API SgNode * replaceWithPattern(SgNode *anchor, SgNode *new_pattern)
Replace an anchor node with a specified pattern subtree with optional SgVariantExpression....
ROSE_DLL_API bool ROSE_DLL_API isJovialOutParam(SgInitializedName *name)
True if a parameter name is a Jovial output parameter.
ROSE_DLL_API void moveForStatementIncrementIntoBody(SgForStatement *f)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfOmpBodyStmt(SgOmpBodyStatement *ompbodyStmt)
Check if the body of a SgOmpBodyStatement is a SgBasicBlock, create one if not.
ROSE_DLL_API bool is_Python_language()
ROSE_DLL_API bool is_mixed_Fortran_and_Cxx_language()
ROSE_DLL_API SgStatement * getLoopCondition(SgScopeStatement *loop)
Routines to get the condition of a loop. It recognize While-loop, For-loop, and Do-While-loop.
ROSE_DLL_API SgEnumSymbol * lookupEnumSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
std::pair< SgVariableDeclaration *, SgExpression * > createTempVariableAndReferenceForExpression(SgExpression *expression, SgScopeStatement *scope)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API SgTypedefSymbol * lookupTypedefSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfWhile(SgWhileStmt *ws)
Check if the body of a 'while' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfFor(SgForStatement *fs)
Check if the body of a 'for' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API PreprocessingInfo * attachArbitraryText(SgLocatedNode *target, const std::string &text, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before)
Attach an arbitrary string to a located node. A workaround to insert irregular statements or vendor-s...
ROSE_DLL_API void markNodeToBeUnparsed(SgNode *node, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isConstantTrue(SgExpression *e)
Check if a bool or int constant expression evaluates to be a true value.
std::map< std::string, SgNode * > local_name_to_node_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API bool is_binary_executable()
void changeAllBodiesToBlocks(SgNode *top, bool createEmptyBody=true)
Fix up ifs, loops, while, switch, Catch, OmpBodyStatement, etc. to have blocks as body components....
void dumpPreprocInfo(SgLocatedNode *locatedNode)
Dumps a located node's preprocessing information.
void fixupReferencesToSymbols(const SgScopeStatement *this_scope, SgScopeStatement *copy_scope, SgCopyHelp &help)
All the symbol table references in the copied AST need to be reset after rebuilding the copied scope'...
ROSE_DLL_API void moveDeclarationToAssociatedNamespace(SgDeclarationStatement *declarationStatement)
Relocate the declaration to be explicitly represented in its associated namespace (required for some ...
ROSE_DLL_API bool isCanonicalForLoop(SgNode *loop, SgInitializedName **ivar=NULL, SgExpression **lb=NULL, SgExpression **ub=NULL, SgExpression **step=NULL, SgStatement **body=NULL, bool *hasIncrementalIterationSpace=NULL, bool *isInclusiveUpperBound=NULL)
Check if a for-loop has a canonical form, return loop index, bounds, step, and body if requested.
ROSE_DLL_API bool isArrayReference(SgExpression *ref, SgExpression **arrayNameExp=NULL, std::vector< SgExpression * > **subscripts=NULL)
Check if an expression is an array access (SgPntrArrRefExp). If so, return its name expression and su...
ROSE_DLL_API void insertStatementAfterLastDeclaration(SgStatement *stmt, SgScopeStatement *scope)
Insert a statement after the last declaration within a scope. The statement will be prepended to the ...
ROSE_DLL_API void destroyTempDirectory(std::string)
Use the system command to remove a temporary directory and all its containing files.
void serialize_list(T &plist, std::string T_name, std::string &prefix, bool hasRemaining, std::ostringstream &out, std::string &edgeLabel)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
void resetMangledNameCache(SgGlobal *globalScope)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API SgTemplateInstantiationMemberFunctionDecl * buildForwardFunctionDeclaration(SgTemplateInstantiationMemberFunctionDecl *memberFunctionInstantiation)
Generate a non-defining (forward) declaration from a defining function declaration.
ROSE_DLL_API bool is_Fortran_language()
ROSE_DLL_API SgVariableSymbol * lookupVariableSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void outputFileIds(SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API SgExprStatement * splitVariableDeclaration(SgVariableDeclaration *decl)
Split a variable declaration with an rhs assignment into two statements: a declaration and an assignm...
ROSE_DLL_API SgStatement * getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated=false)
Get the first statement within a scope, return NULL if it does not exist. Skip compiler-generated sta...
ROSE_DLL_API SgNamespaceSymbol * lookupNamespaceSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool isExtern(SgDeclarationStatement *stmt)
Check if a declaration has an "extern" modifier.
std::string extractPragmaKeyword(const SgPragmaDeclaration *)
Extract a SgPragmaDeclaration's leading keyword . For example "#pragma omp parallel" has a keyword of...
ROSE_DLL_API SgTemplateClassSymbol * lookupTemplateClassSymbolInParentScopes(const SgName &name, SgTemplateParameterPtrList *templateParameterList, SgTemplateArgumentPtrList *templateArgumentList, SgScopeStatement *cscope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool isEquivalentFunctionType(const SgFunctionType *lhs, const SgFunctionType *rhs)
Test if two types are equivalent SgFunctionType nodes.
ROSE_DLL_API void setLoopLowerBound(SgNode *loop, SgExpression *lb)
Set the lower bound of a loop header for (i=lb; ...)
void guardNode(SgLocatedNode *target, std::string guard)
Add preproccessor guard around a given node.
bool checkTypesAreEqual(SgType *typeA, SgType *typeB)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API bool isReferenceType(SgType *t)
Is this type a const or non-const reference type? (Handles typedefs correctly)
ROSE_DLL_API void moveCommentsToNewStatement(SgStatement *sourceStatement, const std::vector< int > &indexList, SgStatement *destinationStatement, bool destinationStatementPreceedsSourceStatement)
Relocate comments and CPP directives from one statement to another.
ROSE_DLL_API SgStatement * getEnclosingStatement(SgNode *n)
Find the closest enclosing statement, including the given node.
ROSE_DLL_API void translateToUseCppDeclarations(SgNode *n)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void changeContinuesToGotos(SgStatement *stmt, SgLabelStatement *label)
Change continue statements in a given block of code to gotos to a label.
void outputGlobalFunctionTypeSymbolTable()
Output function type symbols in global function type symbol table.
ROSE_DLL_API SgScopeStatement * findEnclosingLoop(SgStatement *s, const std::string &fortranLabel="", bool stopOnSwitches=false)
Find the closest loop outside the given statement; if fortranLabel is not empty, the Fortran label of...
std::pair< SgVariableDeclaration *, SgExpression * > createTempVariableForExpression(SgExpression *expression, SgScopeStatement *scope, bool initializeInDeclaration, SgAssignOp **reEvaluate=NULL)
Given an expression, generates a temporary variable whose initializer optionally evaluates that expre...
bool isBodyStatement(SgStatement *s)
Check if a statement is a (true or false) body of a container-like parent, such as For,...
bool functionCallExpressionPreceedsDeclarationWhichAssociatesScope(SgFunctionCallExp *functionCall)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void convertAllForsToWhiles(SgNode *top)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API bool isConstantFalse(SgExpression *e)
Check if a bool or int constant expression evaluates to be a false value.
ROSE_DLL_API void outputLocalSymbolTables(SgNode *node)
Output the local symbol tables.
ROSE_DLL_API void preOrderCollectPreprocessingInfo(SgNode *current, std::vector< PreprocessingInfo * > &infoList, int depth)
Dumps a located node's preprocessing information.
ROSE_DLL_API SgMemberFunctionDeclaration * getDefaultDestructor(SgClassDeclaration *classDeclaration)
Get the default destructor from the class declaration.
void collectVarRefs(SgLocatedNode *root, std::vector< SgVarRefExp * > &result)
Collect all variable references in a subtree.
ROSE_DLL_API void setOperand(SgExpression *target, SgExpression *operand)
Set operands for expressions with single operand, such as unary expressions. handle file info,...
ROSE_DLL_API SgMemberFunctionDeclaration * getDefaultConstructor(SgClassDeclaration *classDeclaration)
Get the default constructor from the class declaration.
ROSE_DLL_API SgInitializedName * getLoopIndexVariable(SgNode *loop)
Return the loop index variable for a for loop.
ROSE_DLL_API SgAssignInitializer * splitExpression(SgExpression *from, std::string newName="")
Replace an expression with a temporary variable and an assignment statement.
ROSE_DLL_API void replaceVariableReferences(SgVariableSymbol *old_sym, SgVariableSymbol *new_sym, SgScopeStatement *scope)
Replace all variable references to an old symbol in a scope to being references to a new symbol.
ROSE_DLL_API bool is_OpenCL_language()
ROSE_DLL_API bool normalizeForLoopIncrement(SgForStatement *loop)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API SgVariableSymbol * appendArg(SgFunctionParameterList *, SgInitializedName *)
Append an argument to SgFunctionParameterList, transparently set parent,scope, and symbols for argume...
ROSE_DLL_API bool unnormalizeForLoopInitDeclaration(SgForStatement *loop)
Undo the normalization of for loop's C99 init declaration. Previous record of normalization is used t...
ROSE_DLL_API SgStatement * getPreviousStatement(SgStatement *currentStmt, bool climbOutScope=true)
Get previous statement of the current statement. It may return a previous statement of a parent scope...
ROSE_DLL_API void removeJumpsToNextStatement(SgNode *)
Remove jumps whose label is immediately after the jump. Used to clean up inlined code fragments.
bool isPrototypeInScope(SgScopeStatement *scope, SgFunctionDeclaration *functionDeclaration, SgDeclarationStatement *startingAtDeclaration)
Assigns unique numbers to each SgScopeStatement of a function.
ROSE_DLL_API int moveUpInnerDanglingIfEndifDirective(SgLocatedNode *lnode)
Extract sequences like " #endif #endif ... #if | #ifdef| #ifndef" buried inside subtree of lnode.
SgDeclarationStatement * getNonInstantiatonDeclarationForClass(SgTemplateInstantiationMemberFunctionDecl *memberFunctionInstantiation)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isConstType(SgType *t)
Is this a const type?
SgFunctionDeclaration * getDeclarationOfNamedFunction(SgExpression *func)
Given a SgExpression that represents a named function (or bound member function), return the mentione...
ROSE_DLL_API bool is_C99_language()
ROSE_DLL_API bool addDefaultConstructorIfRequired(SgClassType *classType, int physical_file_id=Sg_File_Info::TRANSFORMATION_FILE_ID)
Get the default destructor from the class declaration.
ROSE_DLL_API void movePreprocessingInfo(SgStatement *stmt_src, SgStatement *stmt_dst, PreprocessingInfo::RelativePositionType src_position=PreprocessingInfo::undef, PreprocessingInfo::RelativePositionType dst_position=PreprocessingInfo::undef, bool usePrepend=false)
Move preprocessing information of stmt_src to stmt_dst, Only move preprocessing information from the ...
ROSE_DLL_API int fixVariableReferences(SgNode *root, bool cleanUnusedSymbol=true)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API bool isUseByAddressVariableRef(SgVarRefExp *ref)
Check if a variable reference is used by its address: including &a expression and foo(a) when type2 f...
struct const_int_expr_t evaluateConstIntegerExpression(SgExpression *expr)
The function tries to evaluate const integer expressions (such as are used in array dimension sizes)....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsTrueBodyOfIf(SgIfStmt *ifs)
Check if the true body of a 'if' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void replaceExpression(SgExpression *oldExp, SgExpression *newExp, bool keepOldExp=false)
Replace an expression with another, used for variable reference substitution and others....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsFalseBodyOfIf(SgIfStmt *ifs, bool createEmptyBody=true)
Check if the false body of a 'if' statement is a SgBasicBlock, create one if not when the flag is tru...
ROSE_DLL_API SgExprListExp * getEnclosingExprListExp(SgNode *astNode, const bool includingSelf=false)
Get the enclosing SgExprListExp (used as part of function argument index evaluation in subexpressions...
ROSE_DLL_API void appendStatement(SgStatement *stmt, SgScopeStatement *scope=NULL)
Append a statement to the end of the current scope, handle side effect of appending statements,...
ROSE_DLL_API SgFunctionDeclaration * buildFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
void addVarRefExpFromArrayDimInfo(SgNode *astNode, Rose_STL_Container< SgNode * > &NodeList_t)
Find all SgPntrArrRefExp under astNode, then add SgVarRefExp (if any) of SgPntrArrRefExp's dim_info i...
ROSE_DLL_API bool loopTiling(SgForStatement *loopNest, size_t targetLevel, size_t tileSize)
Tile the n-level (starting from 1) loop of a perfectly nested loop nest using tiling size s.
std::string generateUniqueName(const SgNode *node, bool ignoreDifferenceBetweenDefiningAndNondefiningDeclarations)
Generate unique name from C and C++ constructs. The name may contain space.
ROSE_DLL_API SgGlobal * getFirstGlobalScope(SgProject *project)
return the first global scope under current project
ROSE_DLL_API void setOneSourcePositionNull(SgNode *node)
Set current node's source position as NULL.
ROSE_DLL_API void setRhsOperand(SgExpression *target, SgExpression *rhs)
set left hand operand for binary expression
std::pair< SgStatement *, SgInitializedName * > wrapFunction(SgFunctionDeclaration &definingDeclaration, SgName newName)
moves the body of a function f to a new function f; f's body is replaced with code that forwards the ...
ROSE_DLL_API bool is_mixed_Fortran_and_C_and_Cxx_language()
ROSE_DLL_API bool isVolatileType(SgType *t)
Is this a volatile type?
void clearUnusedVariableSymbols(SgNode *root=NULL)
Clear those variable symbols with unknown type (together with initialized names) which are also not r...
ROSE_DLL_API void fixVariableDeclaration(SgVariableDeclaration *varDecl, SgScopeStatement *scope)
Patch up symbol, scope, and parent information when a SgVariableDeclaration's scope is known.
ROSE_DLL_API SgSymbol * lookupSymbolInParentScopesIgnoringAliasSymbols(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
std::string generateUniqueVariableName(SgScopeStatement *scope, std::string baseName="temp")
Generate a name like temp# that is unique in the current scope and any parent and children scopes.
ROSE_DLL_API int gensym_counter
An internal counter for generating unique SgName.
ROSE_DLL_API void splitExpressionIntoBasicBlock(SgExpression *expr)
Split long expressions into blocks of statements.
void reset_name_collision_map()
Reset map variables used to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API SgFunctionDefinition * getEnclosingProcedure(SgNode *n, const bool includingSelf=false)
Find the function definition.
std::vector< SgExpression * > get_C_array_dimensions(const SgArrayType &arrtype)
returns the array dimensions in an array as defined for arrtype
ROSE_DLL_API void replaceSubexpressionWithStatement(SgExpression *from, SageInterface::StatementGenerator *to)
Similar to replaceExpressionWithStatement, but with more restrictions.
ROSE_DLL_API void wrapAllTemplateInstantiationsInAssociatedNamespaces(SgProject *root)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
std::string get_name(const SgNode *node)
Generate a useful name to describe the SgNode.
ROSE_DLL_API void setLoopUpperBound(SgNode *loop, SgExpression *ub)
Set the upper bound of a loop header,regardless the condition expression type. for (i=lb; i op up,...
ROSE_DLL_API bool isMemberFunctionMemberReference(SgMemberFunctionRefExp *memberFunctionRefExp)
Find a node by type using upward traversal.
ROSE_DLL_API SgClassDefinition * findJavaPackage(SgScopeStatement *, std::string)
Look for a qualified package name in the given scope and return its package definition.
ROSE_DLL_API bool isOmpStatement(SgNode *)
Check if a node is SgOmp*Statement.
ROSE_DLL_API bool is_Ada_language()
std::string addMangledNameToCache(SgNode *astNode, const std::string &mangledName)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool is_C_language()
ROSE_DLL_API std::list< SgClassType * > getClassTypeChainForMemberReference(SgExpression *refExp)
Find a node by type using upward traversal.
ROSE_DLL_API void collectUseByAddressVariableRefs(const SgStatement *s, std::set< SgVarRefExp * > &varSetB)
Collect variable references involving use by address: including &a expression and foo(a) when type2 f...
std::vector< SgContinueStmt * > findContinueStmts(SgStatement *code, const std::string &fortranLabel="")
Find all continue statements inside a particular statement, stopping at nested loops.
std::string getMangledNameFromCache(SgNode *astNode)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API std::vector< SgDeclarationStatement * > sortSgNodeListBasedOnAppearanceOrderInSource(const std::vector< SgDeclarationStatement * > &nodevec)
Reorder a list of declaration statements based on their appearance order in source files.
ROSE_DLL_API std::set< SgLocatedNode * > collectModifiedLocatedNodes(SgNode *node)
This collects the SgLocatedNodes that are marked as modified (a flag automatically set by all set_* g...
SgExpression * forallMaskExpression(SgForAllStatement *stmt)
Get the mask expression from the header of a SgForAllStatement.
void clearScopeNumbers(SgFunctionDefinition *functionDefinition)
Clears the cache of scope,integer pairs for the input function.
ROSE_DLL_API SgInitializedName * convertRefToInitializedName(SgNode *current, bool coarseGrain=true)
Variable references can be introduced by SgVarRef, SgPntrArrRefExp, SgInitializedName,...
ROSE_DLL_API SgNode * getSgNodeFromAbstractHandleString(const std::string &input_string)
Obtain a matching SgNode from an abstract handle string.
ROSE_DLL_API void moveStatementsBetweenBlocks(SgBasicBlock *sourceBlock, SgBasicBlock *targetBlock)
Move statements in first block to the second block (preserves order and rebuilds the symbol table).
ROSE_DLL_API bool templateDefinitionIsInClass(SgTemplateInstantiationMemberFunctionDecl *memberFunctionDeclaration)
Return true if template definition is in the class, false if outside of class.
ROSE_DLL_API void fixLabelStatement(SgLabelStatement *label_stmt, SgScopeStatement *scope)
Fix symbol table for SgLabelStatement. Used Internally when the label is built without knowing its ta...
ROSE_DLL_API void replaceExpressionWithStatement(SgExpression *from, SageInterface::StatementGenerator *to)
Replace a given expression with a list of statements produced by a generator.
ROSE_DLL_API void convertForToWhile(SgForStatement *f)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API void insertStatementBefore(SgStatement *targetStmt, SgStatement *newStmt, bool autoMovePreprocessingInfo=true)
Insert a statement before a target statement.
ROSE_DLL_API bool findFirstSgCastExpMarkedAsTransformation(SgNode *n, const std::string &s)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void dumpInfo(SgNode *node, std::string desc="")
Dump information about a SgNode for debugging.
ROSE_DLL_API void convertFunctionDefinitionsToFunctionPrototypes(SgNode *node)
XXX This function operates on the new file used to support outlined function definitions....
ROSE_DLL_API void appendStatementList(const std::vector< SgStatement * > &stmt, SgScopeStatement *scope=NULL)
Append a list of statements to the end of the current scope, handle side effect of appending statemen...
SgNamedType * getDeclaredType(const SgDeclarationStatement *declaration)
Returns the type introduced by a declaration.
ROSE_DLL_API bool isIndexOperator(SgExpression *exp)
Is an overloaded operator an index operator (also referred to as call or subscript operators)....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfCatch(SgCatchOptionStmt *cos)
Check if the body of a 'catch' statement is a SgBasicBlock, create one if not.
std::vector< SgFile * > generateFileList()
Returns STL vector of SgFile IR node pointers.
ROSE_DLL_API int normalizeArrowExpWithAddressOfLeftOperand(SgNode *root, bool transformationGeneratedOnly=true)
Convert all code within root matching the patern of (&left)->right, and translate them into left....
bool hasTemplateSyntax(const SgName &name)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void moveToSubdirectory(std::string directoryName, SgFile *file)
Move file to be generated in a subdirectory (will be generated by the unparser).
ROSE_DLL_API bool isAddressTaken(SgExpression *refExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool hasSimpleChildrenList(SgScopeStatement *scope)
Check if a scope statement has a simple children statement list so insert additional statements under...
ROSE_DLL_API SgFunctionDeclaration * findMain(SgNode *currentNode)
top-down traversal from current node to find the main() function declaration
ROSE_DLL_API SgClassSymbol * lookupClassSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void removeConsecutiveLabels(SgNode *top)
Remove consecutive labels.
ROSE_DLL_API void setLoopBody(SgScopeStatement *loop, SgStatement *body)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
bool getForLoopInformations(SgForStatement *for_loop, SgVariableSymbol *&iterator, SgExpression *&lower_bound, SgExpression *&upper_bound, SgExpression *&stride)
ROSE_DLL_API void appendExpression(SgExprListExp *, SgExpression *)
Append an expression to a SgExprListExp, set the parent pointer also.
ROSE_DLL_API bool isLambdaFunction(SgFunctionDeclaration *func)
Check if a function declaration is a C++11 lambda function.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfSwitch(SgSwitchStatement *ws)
Check if the body of a 'switch' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void prependStatement(SgStatement *stmt, SgScopeStatement *scope=NULL)
Prepend a statement to the beginning of the current scope, handling side effects as appropriate.
ROSE_DLL_API bool isCallToParticularFunction(SgFunctionDeclaration *decl, SgExpression *e)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool ROSE_DLL_API isMutable(SgInitializedName *name)
True if an SgInitializedName is "mutable' (has storage modifier set)
ROSE_DLL_API bool isCopyConstructible(SgType *type)
Is a type copy constructible? This may not quite work properly.
ROSE_DLL_API SgVariableSymbol * prependArg(SgFunctionParameterList *, SgInitializedName *)
Prepend an argument to SgFunctionParameterList.
ROSE_DLL_API void setSourcePositionAtRootAndAllChildren(SgNode *root)
Set the source code positon for the subtree (including the root).
ROSE_DLL_API SgExpression * copyExpression(SgExpression *e)
Deep copy an expression.
void setParameterList(actualFunction *func, SgFunctionParameterList *paralist)
Set parameter list for a function declaration, considering existing parameter list etc.
SgStatement * findLastDeclarationStatement(SgScopeStatement *scope, bool includePragma=false)
Find the last declaration statement within a scope (if any). This is often useful to decide where to ...
ROSE_DLL_API bool insideSystemHeader(SgLocatedNode *node)
Set source position info(Sg_File_Info) as transformation generated for all SgNodes in memory pool.
std::vector< SgDeclarationStatement * > getDependentDeclarations(SgStatement *stmt)
Get a statement's dependent declarations which declares the types used in the statement....
SgBasicBlock * makeSingleStatementBodyToBlock(SgStatement *singleStmt)
Make a single statement body to be a basic block. Its parent is if, while, catch, or upc_forall etc.
void computeUniqueNameForUseAsIdentifier(SgNode *astNode)
Traversal to set the global map of names to node and node to names.collisions to support generateUniq...
ROSE_DLL_API void collectReadOnlyVariables(SgStatement *stmt, std::set< SgInitializedName * > &readOnlyVars, bool coarseGrain=true)
Collect read only variables within a statement. The statement can be either of a function,...
std::string generateUniqueNameForUseAsIdentifier_support(SgDeclarationStatement *declaration)
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API PreprocessingInfo * findHeader(SgSourceFile *source_file, const std::string &header_file_name, bool isSystemHeader)
Find the preprocessingInfo node representing #include <header.h> or #include "header....
ROSE_DLL_API void myRemoveStatement(SgStatement *stmt)
A special purpose statement removal function, originally from inlinerSupport.h, Need Jeremiah's atten...
ROSE_DLL_API SgScopeStatement * getScope(const SgNode *astNode)
Get the closest scope from astNode. Return astNode if it is already a scope.
ROSE_DLL_API bool isStrictIntegerType(SgType *t)
Check if a type is an integral type, only allowing signed/unsigned short, int, long,...
ROSE_DLL_API bool is_Java_language()
ROSE_DLL_API void insertStatementAfter(SgStatement *targetStmt, SgStatement *newStmt, bool autoMovePreprocessingInfo=true)
Insert a statement after a target statement, Move around preprocessing info automatically by default.
ROSE_DLL_API bool isEquivalentType(const SgType *lhs, const SgType *rhs)
Test for equivalence of types independent of access permissions (private or protected modes for membe...
ROSE_DLL_API bool isTemplateInstantiationNode(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API void removeStatement(SgStatement *stmt, bool autoRelocatePreprocessingInfo=true)
Remove a statement from its attach point of the AST. Automatically keep its associated preprocessing ...
ROSE_DLL_API SgOmpClauseBodyStatement * findEnclosingOmpClauseBodyStatement(SgStatement *s)
Find enclosing OpenMP clause body statement from s. If s is already one, return it directly.
ROSE_DLL_API bool scopeHasStatementsFromSameFile(SgScopeStatement *scope)
This function supports the token-based unparsing when used with unparsing of header files to know whe...
ROSE_DLL_API SgSourceFile * getEnclosingSourceFile(SgNode *n, const bool includingSelf=false)
Find enclosing source file node.
void rebuildSymbolTable(SgScopeStatement *scope)
Regenerate the symbol table.
ROSE_DLL_API SgSymbol * lookupSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
void setBaseTypeDefiningDeclaration(SgVariableDeclaration *var_decl, SgDeclarationStatement *base_decl)
a better version for SgVariableDeclaration::set_baseTypeDefininingDeclaration(), handling all side ef...
ROSE_DLL_API void pastePreprocessingInfo(SgLocatedNode *dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType &saved_buf)
Paste preprocessing information from a buffer to a destination node. Used in combination of cutPrepro...
ROSE_DLL_API SgStatement * lastFrontEndSpecificStatement(SgGlobal *globalScope)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API SgFunctionType * findFunctionType(SgType *return_type, SgFunctionParameterTypeList *typeList)
Find the function type matching a function signature plus a given return type.
std::set< unsigned int > collectSourceSequenceNumbers(SgNode *astNode)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API bool is_OpenMP_language()
ROSE_DLL_API std::set< SgNode * > getFrontendSpecificNodes()
Find a node by type using upward traversal.
ROSE_DLL_API bool mergeAssignmentWithDeclaration(SgExprStatement *assign_stmt, SgVariableDeclaration *decl, bool removeAssignStmt=true)
Merge an assignment into its upstream declaration statement. Callers should make sure the merge is se...
ROSE_DLL_API void setFortranNumericLabel(SgStatement *stmt, int label_value, SgLabelSymbol::label_type_enum label_type=SgLabelSymbol::e_start_label_type, SgScopeStatement *label_scope=NULL)
Set a numerical label for a Fortran statement. The statement should have a enclosing function definit...
ROSE_DLL_API SgType * lookupNamedTypeInParentScopes(const std::string &type_name, SgScopeStatement *scope=NULL)
Lookup a named type based on its name, bottomup searching from a specified scope. Note name collison ...
ROSE_DLL_API SgFile * processFile(SgProject *, std::string, bool unparse=false)
Invoke JavaRose to translate a given file and put the resulting AST in the global space of the projec...
bool get(const Word *words, size_t idx)
Return a single bit.
void swap_child(SageNode &lhs, SageNode &rhs, SageChild *(SageNode::*getter)() const, void(SageNode::*setter)(SageChild *))
swaps children (of equal kind) between two ancestor nodes of the same type
std::remove_const< typenamestd::remove_reference< RoseVisitor >::type >::type dispatch(RoseVisitor &&rv, SgNode *n)
uncovers the type of SgNode and passes it to an function "handle" in RoseVisitor.
This file implements generic (template) sage query functions Currently this includes functions for:
static ROSE_DLL_API DeferredTransformation replaceDefiningFunctionDeclarationWithFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
operator=()
ROSE_DLL_API ~DeferredTransformation(void)
Copy constructor.
ROSE_DLL_API DeferredTransformation & operator=(const DeferredTransformation &X)
Shallow; does not delete fields.
struct DispatchHandler