Program Listing for File sageInterface.h

Program Listing for File sageInterface.h#

↰ Return to documentation for file (src/frontend/SageIII/sageInterface/sageInterface.h)

#ifndef ROSE_SAGE_INTERFACE
#define ROSE_SAGE_INTERFACE

#include "sage3basic.hhh"
#include <stdint.h>
#include <utility>

#include "rosePublicConfig.h" // for ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
#include "nodeQuery.h" //for querySubTree

#if 0   // FMZ(07/07/2010): the argument "nextErrorCode" should be call-by-reference
SgFile* determineFileType ( std::vector<std::string> argv, int nextErrorCode, SgProject* project );
#else
SgFile* determineFileType ( std::vector<std::string> argv, int& nextErrorCode, SgProject* project );
#endif

// DQ (7/20/2008): Added support for unparsing abitrary strings in the unparser.
#include "astUnparseAttribute.h"
#include <set>

#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
#include "LivenessAnalysis.h"
#include "ClassHierarchyGraph.h"
#endif

#include "ompSupport.h"
// DQ (8/19/2004): Moved from ROSE/src/midend/astRewriteMechanism/rewrite.h
ROSE_DLL_API std::string getVariantName (VariantT v);

// DQ (12/9/2004): Qing, Rich and Dan have decided to start this namespace within ROSE
// This namespace is specific to interface functions that operate on the Sage III AST.
// The name was chosen so as not to conflict with other classes within ROSE.
// This will become the future home of many interface functions which operate on
// the AST and which are generally useful to users.  As a namespace multiple files can be used
// to represent the compete interface and different developers may contribute interface
// functions easily.

// Constructor handling: (We have sageBuilder.h now for this purpose, Liao 2/1/2008)
//     We could add simpler layers of support for construction of IR nodes by
// hiding many details in "makeSg***()" functions. Such functions would
// return pointers to the associated Sg*** objects and would be able to hide
// many IR specific details, including:
//      memory handling
//      optional parameter settings not often required
//      use of Sg_File_Info objects (and setting them as transformations)
//
// namespace AST_Interface  (this name is taken already by some of Qing's work :-)

#define TRANS_FILE Sg_File_Info::generateDefaultFileInfoForTransformationNode()


namespace SageInterface
   {
  // Liao 6/22/2016: keep records of loop init-stmt normalization, later help undo it to support autoPar.
  struct Transformation_Record
  {
    // a lookup table to check if a for loop has been normalized for its c99-style init-stmt
    std::map <SgForStatement* , bool > forLoopInitNormalizationTable;
    // Detailed record about the original declaration (1st in the pair) and the normalization generated new declaration (2nd in the pair)
    std::map <SgForStatement* , std::pair<SgVariableDeclaration*, SgVariableDeclaration*>  >  forLoopInitNormalizationRecord;
  } ;

  ROSE_DLL_API extern Transformation_Record trans_records;

  // DQ (4/3/2014): Added general AST support separate from the AST.

  // Container and API for analysis information that is outside of the AST and as a result
  // prevents frequent modification of the IR.
     class DeclarationSets
        {
       // DQ (4/3/2014): This stores all associated declarations as a map of sets.
       // the key to the map is the first nondefining declaration and the elements of the set are
       // all of the associated declarations (including the defining declaration).

          private:
               std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* > declarationMap;

          public:
               void addDeclaration(SgDeclarationStatement* decl);
               const std::set<SgDeclarationStatement*>* getDeclarations(SgDeclarationStatement* decl);

               std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* > & getDeclarationMap();

               bool isLocatedInDefiningScope(SgDeclarationStatement* decl);

        };

  // DQ (4/3/2014): This constructs a data structure that holds analysis information about
  // the AST that is separate from the AST.  This is intended to be a general mechanism
  // to support analysis information without constantly modifying the IR.
     DeclarationSets* buildDeclarationSets(SgNode*);

ROSE_DLL_API extern int gensym_counter;

 void addMessageStatement( SgStatement* stmt, std::string message );

  class UniqueNameAttribute : public AstAttribute
  {
    private:
     std::string name;
    public:
     UniqueNameAttribute(std::string n="") {name =n; };
     void set_name (std::string n) {name = n;};
     std::string get_name () {return name;};
  };



// REX FIX: SgTemplateParameter cannot store attributes directly (inherits SgSupport).
// So we use a global map to store the keyword.
ROSE_DLL_API void setTemplateParameterKeyword(SgTemplateParameter* param, std::string kw);
ROSE_DLL_API std::string getTemplateParameterKeyword(SgTemplateParameter* param);

 //------------------------------------------------------------------------

// DQ (8/5/2020): the "using namespace" directive will not hide existing visability of symbols in resolving visability.
// So we need to test if a symbol is visible exclusing matching alises due to using direectives before we can decide to
// persue name space qualification. This is best demonstrated by Cxx_tests/test2020_18.C, test2020_19.C, test2020_20.C,
// and test2020_21.C.
   ROSE_DLL_API SgSymbol *lookupSymbolInParentScopesIgnoringAliasSymbols (const SgName & name, SgScopeStatement *currentScope = NULL, SgTemplateParameterPtrList* templateParameterList = NULL, SgTemplateArgumentPtrList* templateArgumentList = NULL);

// DQ (8/21/2013): Modified to make newest function parameters be default arguments.
// DQ (8/16/2013): For now we want to remove the use of default parameters and add the support for template parameters and template arguments.
// SgSymbol *lookupSymbolInParentScopes (const SgName & name, SgScopeStatement *currentScope=NULL);
// SgSymbol *lookupSymbolInParentScopes (const SgName & name, SgScopeStatement *currentScope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList);
   ROSE_DLL_API SgSymbol *lookupSymbolInParentScopes (const SgName & name, SgScopeStatement *currentScope = NULL, SgTemplateParameterPtrList* templateParameterList = NULL, SgTemplateArgumentPtrList* templateArgumentList = NULL);

   // Liao 1/22/2008, used for get symbols for generating variable reference nodes
   // ! Find a variable symbol in current and ancestor scopes for a given name
   ROSE_DLL_API SgVariableSymbol *lookupVariableSymbolInParentScopes (const SgName & name, SgScopeStatement *currentScope=NULL);

   // DQ (11/24/2007): Functions moved from the Fortran support so that they could be called from within astPostProcessing.
   ROSE_DLL_API SgFunctionSymbol *lookupFunctionSymbolInParentScopes (const SgName & functionName, SgScopeStatement *currentScope=NULL);

   // Liao, 1/24/2008, find exact match for a function
   ROSE_DLL_API SgFunctionSymbol *lookupFunctionSymbolInParentScopes (const SgName &  functionName,
                                                         const SgType* t,
                                                         SgScopeStatement *currentScope=NULL);

   ROSE_DLL_API SgFunctionSymbol *lookupTemplateFunctionSymbolInParentScopes (const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement *currentScope=NULL);
   ROSE_DLL_API SgFunctionSymbol *lookupTemplateMemberFunctionSymbolInParentScopes (const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement *currentScope=NULL);

   ROSE_DLL_API SgTemplateVariableSymbol * lookupTemplateVariableSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList * tplparams, SgTemplateArgumentPtrList* tplargs, SgScopeStatement *currentScope=NULL);


// DQ (8/21/2013): Modified to make newest function parameters be default arguments.
// DQ (8/16/2013): For now we want to remove the use of default parameters and add the support for template parameters and template arguments.
// DQ (5/7/2011): Added support for SgClassSymbol (used in name qualification support).
// SgClassSymbol*     lookupClassSymbolInParentScopes    (const SgName & name, SgScopeStatement *currentScope = NULL);
   ROSE_DLL_API SgClassSymbol*     lookupClassSymbolInParentScopes    (const SgName & name, SgScopeStatement *currentScope = NULL, SgTemplateArgumentPtrList* templateArgumentList = NULL);
   ROSE_DLL_API SgTypedefSymbol*   lookupTypedefSymbolInParentScopes  (const SgName & name, SgScopeStatement *currentScope = NULL);

   ROSE_DLL_API SgNonrealSymbol*   lookupNonrealSymbolInParentScopes  (const SgName & name, SgScopeStatement *currentScope = NULL, SgTemplateParameterPtrList* templateParameterList = NULL, SgTemplateArgumentPtrList* templateArgumentList = NULL);
#if 0
 // DQ (8/13/2013): This function does not make since any more, now that we have made the symbol
 // table handling more precise and we have to provide template parameters for any template lookup.
 // We also have to know if we want to lookup template classes, template functions, or template
 // member functions (since each have specific requirements).
   SgTemplateSymbol*  lookupTemplateSymbolInParentScopes (const SgName & name, SgScopeStatement *currentScope = NULL);
#endif
#if 0
// DQ (8/13/2013): I am not sure if we want this functions in place of lookupTemplateSymbolInParentScopes.
// Where these are called we might not know enough information about the template parameters or function
// types, for example.
   SgTemplateClassSymbol*           lookupTemplateClassSymbolInParentScopes          (const SgName & name, SgScopeStatement *currentScope = NULL, SgTemplateParameterPtrList* templateParameterList = NULL, SgTemplateArgumentPtrList* templateArgumentList = NULL);
   SgTemplateFunctionSymbol*        lookupTemplateFunctionSymbolInParentScopes       (const SgName & name, SgScopeStatement *currentScope = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
   SgTemplateMemberFunctionSymbol*  lookupTemplateMemberFunctionSymbolInParentScopes (const SgName & name, SgScopeStatement *currentScope = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
#endif

// DQ (8/21/2013): Modified to make some of the newest function parameters be default arguments.
// DQ (8/13/2013): I am not sure if we want this functions in place of lookupTemplateSymbolInParentScopes.
   ROSE_DLL_API SgTemplateClassSymbol* lookupTemplateClassSymbolInParentScopes (const SgName &  name, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList, SgScopeStatement *cscope = NULL);

   ROSE_DLL_API SgEnumSymbol*      lookupEnumSymbolInParentScopes     (const SgName & name, SgScopeStatement *currentScope = NULL);
   ROSE_DLL_API SgNamespaceSymbol* lookupNamespaceSymbolInParentScopes(const SgName & name, SgScopeStatement *currentScope = NULL);

// DQ (7/17/2011): Added function from cxx branch that I need here for the Java support.
// SgClassSymbol* lookupClassSymbolInParentScopes (const SgName &  name, SgScopeStatement *cscope);

   // DQ (12/9/2004): Moved this function (by Alin Jula) from being a member of SgInitializedName
   // to this location where it can be a part of the interface for the Sage III AST.
   ROSE_DLL_API int set_name (SgInitializedName * initializedNameNode, SgName new_name);

   void outputGlobalFunctionTypeSymbolTable ();

   // DQ (6/27/2005):
   ROSE_DLL_API void outputLocalSymbolTables (SgNode * node);

   class OutputLocalSymbolTables:public AstSimpleProcessing
         {
           public:
     void visit (SgNode * node);
         };
   // DQ (9/28/2005):
   void rebuildSymbolTable (SgScopeStatement * scope);
   void ensureSymbolParentPointers(SgNode* root);

   void clearUnusedVariableSymbols (SgNode* root = NULL);

   // DQ (3/1/2009):
   void fixupReferencesToSymbols( const SgScopeStatement* this_scope,  SgScopeStatement* copy_scope, SgCopyHelp & help );


 //------------------------------------------------------------------------

   // DQ (9/21/2005): General function for extracting the name of declarations (when they have names)
     std::string get_name (const SgNode * node);

   // DQ (6/13/2005): General function for extracting the name of declarations (when they have names)
     std::string get_name (const SgStatement * stmt);

     std::string get_name (const SgExpression * expr);

   // DQ (6/13/2005): General function for extracting the name of declarations (when they have names)
     std::string get_name (const SgDeclarationStatement * declaration);

   // DQ (6/13/2005): General function for extracting the name of declarations (when they have names)
     std::string get_name (const SgScopeStatement * scope);

   // DQ (2/11/2007): Added this function to make debugging support more complete (useful for symbol table debugging support).
     std::string get_name (const SgSymbol * symbol);

     std::string get_name (const SgType * type);


     std::string get_name (const SgSupport * node);


     std::string get_name (const SgLocatedNodeSupport * node);

     std::string get_name ( const SgC_PreprocessorDirectiveStatement* directive );

     std::string get_name ( const SgToken* token );

   // PP (11/22/2021): General function for extracting the type of declarations (when they declare types)
     SgType* getDeclaredType(const SgDeclarationStatement* declaration);


  // DQ (3/20/2016): Added to refactor some of the DSL infrastructure support.
     std::string generateUniqueNameForUseAsIdentifier ( SgDeclarationStatement* declaration );
     std::string generateUniqueNameForUseAsIdentifier_support ( SgDeclarationStatement* declaration );

     extern std::map<std::string,int>     local_name_collision_map;
     extern std::map<std::string,SgNode*> local_name_to_node_map;
     extern std::map<SgNode*,std::string> local_node_to_name_map;

     void computeUniqueNameForUseAsIdentifier( SgNode* astNode );

     void reset_name_collision_map();


 //------------------------------------------------------------------------

  // DQ (6/21/2005): Get the default destructor from the class declaration
     ROSE_DLL_API SgMemberFunctionDeclaration *getDefaultDestructor (SgClassDeclaration* classDeclaration);

   // DQ (6/22/2005): Get the default constructor from the class declaration
     ROSE_DLL_API SgMemberFunctionDeclaration *getDefaultConstructor (SgClassDeclaration* classDeclaration);
  // DQ (8/27/2005):
     ROSE_DLL_API bool templateDefinitionIsInClass (SgTemplateInstantiationMemberFunctionDecl* memberFunctionDeclaration);

  // DQ (9/17/2005):
     ROSE_DLL_API SgTemplateInstantiationMemberFunctionDecl* buildForwardFunctionDeclaration (SgTemplateInstantiationMemberFunctionDecl * memberFunctionInstantiation);

     ROSE_DLL_API bool isStructDeclaration(SgNode * node);
     ROSE_DLL_API bool isUnionDeclaration(SgNode * node);

#if 0
 // DQ (8/28/2005): This is already a member function of the SgFunctionDeclaration
 // (so that it can handle template functions and member functions)

    // DQ (8/27/2005):
     bool isTemplateMemberFunction (SgTemplateInstantiationMemberFunctionDecl* memberFunctionDeclaration);
#endif

  // DQ (11/9/2020): Added function to support adding a default constructor definition to a class
  // if it does not have a default constructor, but has any other constructor that would prevend
  // a compiler generated default constructor from being generated by the compiler.
  // Note the physical_file_id is so that it can be marked to be unparsed when header file unparsing is active.
     ROSE_DLL_API bool addDefaultConstructorIfRequired ( SgClassType* classType, int physical_file_id = Sg_File_Info::TRANSFORMATION_FILE_ID );


 //------------------------------------------------------------------------

  void recursivePrintCurrentAndParent (SgNode* n) ;

   void saveToPDF(SgNode* node, std::string filename);
   void saveToPDF(SgNode* node); // enable calling from gdb

   void printAST (SgNode* node);

   void printAST2TextFile (SgNode* node, const char* filename, bool printType=true);

   void printAST2TextFile (SgNode* node, std::string filename, bool printType=true);

 // DQ (2/12/2012): Added some diagnostic support.
   void whereAmI(SgNode* node);

   std::string extractPragmaKeyword(const SgPragmaDeclaration *);

   ROSE_DLL_API bool isOmpStatement(SgNode* );
   // DQ (8/27/2005):
   bool isOverloaded (SgFunctionDeclaration * functionDeclaration);

// DQ (2/14/2012): Added support function used for variable declarations in conditionals.
   void initializeIfStmt(SgIfStmt *ifstmt, SgStatement* conditional, SgStatement * true_body, SgStatement * false_body);

   void initializeSwitchStatement(SgSwitchStatement* switchStatement,SgStatement *item_selector,SgStatement *body);

   void initializeWhileStatement(SgWhileStmt* whileStatement, SgStatement *  condition, SgStatement *body, SgStatement *else_body);

   void annotateExpressionsWithUniqueNames (SgProject* project);

   ROSE_DLL_API bool isMain (const SgNode* node);
   // DQ (6/22/2005):
    std::string generateUniqueName ( const SgNode * node, bool ignoreDifferenceBetweenDefiningAndNondefiningDeclarations);

    std::string generateUniqueVariableName(SgScopeStatement* scope, std::string baseName = "temp");

  // DQ (8/10/2010): Added const to first parameter.
  // DQ (3/10/2007):
    std::string declarationPositionString (const SgDeclarationStatement * declaration);

  // DQ (1/20/2007):
    ROSE_DLL_API std::string generateProjectName (const SgProject * project, bool supressSuffix = false );

  SgFunctionDeclaration* getDeclarationOfNamedFunction(SgExpression* func);

  SgExpression* forallMaskExpression(SgForAllStatement* stmt);

  void addVarRefExpFromArrayDimInfo(SgNode * astNode, Rose_STL_Container<SgNode *>& NodeList_t);

  // DQ (10/6/2006): Added support for faster mangled name generation (caching avoids recomputation).
#ifndef SWIG
// DQ (3/10/2013): This appears to be a problem for the SWIG interface (undefined reference at link-time).
  void clearMangledNameCache (SgGlobal * globalScope);
  void resetMangledNameCache (SgGlobal * globalScope);
#endif

  std::string getMangledNameFromCache (SgNode * astNode);
  std::string addMangledNameToCache (SgNode * astNode, const std::string & mangledName);

  SgDeclarationStatement * getNonInstantiatonDeclarationForClass (SgTemplateInstantiationMemberFunctionDecl * memberFunctionInstantiation);

  void setBaseTypeDefiningDeclaration(SgVariableDeclaration* var_decl, SgDeclarationStatement *base_decl);

  // DQ (10/14/2006): This function tests the AST to see if for a non-defining declaration, the
  // bool declarationPreceedsDefinition ( SgClassDeclaration* classNonDefiningDeclaration, SgClassDeclaration* classDefiningDeclaration );
  bool declarationPreceedsDefinition (SgDeclarationStatement *nonDefiningDeclaration, SgDeclarationStatement *definingDeclaration);

  // DQ (10/19/2006): Function calls have interesting context dependent rules to determine if
  // they are output with a global qualifier or not.  Were this is true we have to avoid global
  // qualifiers, since the function's scope has not been defined.  This is an example of where
  // qualification of function names in function calls are context dependent; an interesting
  // example of where the C++ language is not friendly to source-to-source processing :-).
  bool functionCallExpressionPreceedsDeclarationWhichAssociatesScope (SgFunctionCallExp * functionCall);

    ROSE_DLL_API std::vector < SgNode * >astIntersection (SgNode * original, SgNode * copy, SgCopyHelp * help = NULL);

   ROSE_DLL_API SgNode* deepCopyNode (const SgNode* subtree);

   template <typename NodeType>
   NodeType* deepCopy (const NodeType* subtree) {
     return dynamic_cast<NodeType*>(deepCopyNode(subtree));
   }

   ROSE_DLL_API SgExpression* copyExpression(SgExpression* e);

   ROSE_DLL_API SgStatement* copyStatement(SgStatement* s);

// from VarSym.cc in src/midend/astOutlining/src/ASTtools
  ROSE_DLL_API SgVariableSymbol* getFirstVarSym (SgVariableDeclaration* decl);

  ROSE_DLL_API SgInitializedName* getFirstInitializedName (SgVariableDeclaration* decl);

ROSE_DLL_API void myRemoveStatement(SgStatement* stmt);

ROSE_DLL_API bool isConstantTrue(SgExpression* e);

ROSE_DLL_API bool isConstantFalse(SgExpression* e);

ROSE_DLL_API bool isCallToParticularFunction(SgFunctionDeclaration* decl, SgExpression* e);
ROSE_DLL_API bool isCallToParticularFunction(const std::string& qualifiedName, size_t arity, SgExpression* e);

bool ROSE_DLL_API isStatic(SgDeclarationStatement* stmt);

ROSE_DLL_API void setStatic(SgDeclarationStatement* stmt);

ROSE_DLL_API bool isExtern(SgDeclarationStatement* stmt);

ROSE_DLL_API void setExtern(SgDeclarationStatement* stmt);

bool ROSE_DLL_API isMutable(SgInitializedName* name);

std::vector<SgInitializedName*> getInParameters(const SgInitializedNamePtrList &params);

std::vector<SgInitializedName*> getOutParameters(const SgInitializedNamePtrList &params);

class StatementGenerator {
  public:
  virtual ~StatementGenerator() {};
  virtual SgStatement* generate(SgExpression* where_to_write_answer) = 0;
};

bool isAssignmentStatement(SgNode* _s, SgExpression** lhs=NULL, SgExpression** rhs=NULL, bool* readlhs=NULL);

ROSE_DLL_API SgInitializedName* convertRefToInitializedName(SgNode* current, bool coarseGrain=true);

ROSE_DLL_API SgStatement* getFirstStatementAtLine(SgSourceFile * sourceFile, int line);

ROSE_DLL_API void getAllStatementsAtLine(SgSourceFile * sourceFile, int line, SgStatementPtrList &returnList);

ROSE_DLL_API void dumpInfo(SgNode* node, std::string desc="");

ROSE_DLL_API std::vector<SgDeclarationStatement*>
sortSgNodeListBasedOnAppearanceOrderInSource(const std::vector<SgDeclarationStatement*>& nodevec);

// DQ (4/13/2013): We need these to support the unparing of operators defined by operator syntax or member function names.
// bool isPrefixOperator( const SgMemberFunctionRefExp* memberFunctionRefExp );
bool isPrefixOperator( SgExpression* exp );

bool isPrefixOperatorName( const SgName & functionName );

bool isPostfixOperator( SgExpression* exp );

bool isIndexOperator( SgExpression* exp );

// DQ (1/10/2014): Adding more general support for token based unparsing.
SgStatement* lastStatementOfScopeWithTokenInfo (SgScopeStatement* scope, std::map<SgNode*,TokenStreamSequenceToNodeMapping*> & tokenStreamSequenceMap);

// DQ (8/12/2020): Check the access permissions of all defining and nodefining declarations.
void checkAccessPermissions ( SgNode* );

// DQ (8/14/2020): Check the symbol tables for specific scopes (debugging support).
void checkSymbolTables ( SgNode* );

// DQ (11/9/2020): Added support for makring IR nodes and subtrees of the AST to be unparsed (physical_file_id
// is required when unparsing header files is true or support multiple files and shared IR nodes).
void markSubtreeToBeUnparsed(SgNode* root, int physical_file_id);
void markNodeToBeUnparsed(SgNode* node, int physical_file_id);



//------------------------------------------------------------------------

// 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).
// The value of 0 allows the old implementation to be tested, and the value of 1 allows the new optimized implementation to be tested.
// However to get all of the functions to be inlined, we have to recompile all of ROSE.
#define INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS 1

//  std::string version();  // utility_functions.h, version number
#if INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS
  ROSE_DLL_API inline bool is_C_language ()         { return Rose::is_C_language; }
  ROSE_DLL_API inline bool is_OpenMP_language ()    { return Rose::is_OpenMP_language; }
  ROSE_DLL_API inline bool is_UPC_language ()       { return Rose::is_UPC_language; }
  ROSE_DLL_API inline bool is_UPC_dynamic_threads() { return Rose::is_UPC_dynamic_threads; }
  ROSE_DLL_API inline bool is_C99_language ()       { return Rose::is_C99_language; }
  ROSE_DLL_API inline bool is_Cxx_language ()       { return Rose::is_Cxx_language; }
  ROSE_DLL_API inline bool is_Fortran_language ()   { return Rose::is_Fortran_language; }
  ROSE_DLL_API inline bool is_CAF_language ()       { return Rose::is_CAF_language; }
  ROSE_DLL_API inline bool is_Cuda_language()       { return Rose::is_Cuda_language; }
  ROSE_DLL_API inline bool is_OpenCL_language()     { return Rose::is_OpenCL_language; }
#else
  ROSE_DLL_API bool is_C_language ();
  ROSE_DLL_API bool is_OpenMP_language ();
  ROSE_DLL_API bool is_UPC_language ();
  ROSE_DLL_API bool is_UPC_dynamic_threads();
  ROSE_DLL_API bool is_C99_language ();
  ROSE_DLL_API bool is_Cxx_language ();
  ROSE_DLL_API bool is_Fortran_language ();
  ROSE_DLL_API bool is_CAF_language ();
  ROSE_DLL_API bool is_Cuda_language();
  ROSE_DLL_API bool is_OpenCL_language();
#endif

  ROSE_DLL_API bool is_mixed_C_and_Cxx_language ();
  ROSE_DLL_API bool is_mixed_Fortran_and_C_language ();
  ROSE_DLL_API bool is_mixed_Fortran_and_Cxx_language ();
  ROSE_DLL_API bool is_mixed_Fortran_and_C_and_Cxx_language ();

  ROSE_DLL_API bool is_language_case_insensitive ();
  ROSE_DLL_API bool language_may_contain_nondeclarations_in_scope ();


//------------------------------------------------------------------------

  // DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
  // labels for scopes in a function (as required for name mangling).
  void resetScopeNumbers (SgFunctionDefinition * functionDeclaration);

  // DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
  // labels for scopes in a function (as required for name mangling).
  void clearScopeNumbers (SgFunctionDefinition * functionDefinition);


  SgNamespaceDefinitionStatement * enclosingNamespaceScope (SgDeclarationStatement * declaration);
//  SgNamespaceDefinitionStatement * getEnclosingNamespaceScope (SgNode * node);

  bool isPrototypeInScope (SgScopeStatement * scope,
                           SgFunctionDeclaration * functionDeclaration,
                           SgDeclarationStatement * startingAtDeclaration);

  bool ROSE_DLL_API isAncestor(SgNode* node1, SgNode* node2);
//------------------------------------------------------------------------

  void dumpPreprocInfo (SgLocatedNode* locatedNode);

ROSE_DLL_API PreprocessingInfo * findHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader);

ROSE_DLL_API PreprocessingInfo * insertHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader, bool asLastHeader);

ROSE_DLL_API void insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader);

ROSE_DLL_API PreprocessingInfo * insertHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader = false, PreprocessingInfo::RelativePositionType position = PreprocessingInfo::before);

ROSE_DLL_API PreprocessingInfo* insertHeader(const std::string& filename, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::after, bool isSystemHeader=false, SgScopeStatement* scope=NULL);

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);

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);


ROSE_DLL_API void cutPreprocessingInfo (SgLocatedNode* src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf);

ROSE_DLL_API void pastePreprocessingInfo (SgLocatedNode* dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& saved_buf);

ROSE_DLL_API PreprocessingInfo* attachArbitraryText(SgLocatedNode* target,
                const std::string & text,
               PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before);

ROSE_DLL_API void replaceMacroCallsWithExpandedStrings(SgPragmaDeclaration* target);

PreprocessingInfo* attachComment(
  SgSourceFile * source_file,
  const std::string & content,
  PreprocessingInfo::DirectiveType directive_type = PreprocessingInfo::C_StyleComment,
  PreprocessingInfo::RelativePositionType  position = PreprocessingInfo::before
);

   ROSE_DLL_API PreprocessingInfo* attachComment(SgLocatedNode* target, const std::string & content,
               PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before,
               PreprocessingInfo::DirectiveType dtype= PreprocessingInfo::CpreprocessorUnknownDeclaration);

// DQ (7/20/2008): I am not clear were I should put this function, candidates include: SgLocatedNode or SgInterface
  ROSE_DLL_API void addTextForUnparser ( SgNode* astNode, std::string s, AstUnparseAttribute::RelativePositionType inputlocation );

void guardNode(SgLocatedNode * target, std::string guard);



//------------------------------------------------------------------------

// ************************************************************************
//              Newer versions of now depricated functions
// ************************************************************************

// DQ (5/1/2012): This function queries the SageBuilder::SourcePositionClassification mode (stored in the SageBuilder
// interface) and used the specified mode to initialize the source position data (Sg_File_Info objects).  This
// function is the only function that should be called directly (though in a namespace we can't define permissions).
  ROSE_DLL_API void setSourcePosition(SgNode* node);

// A better name might be "setSourcePositionForSubTree"
  ROSE_DLL_API void setSourcePositionAtRootAndAllChildren(SgNode *root);

void setSourcePositionAsTransformation(SgNode *node);

// DQ (5/1/2012): Newly renamed function (previous name preserved for backward compatability).
void setSourcePositionPointersToNull(SgNode *node);

// ************************************************************************



// ************************************************************************
//                  Older deprecated functions
// ************************************************************************
  // Liao, 1/8/2007, set file info. for a whole subtree as transformation generated
  ROSE_DLL_API void setOneSourcePositionForTransformation(SgNode *node);

  ROSE_DLL_API void setOneSourcePositionNull(SgNode *node);

  ROSE_DLL_API void setSourcePositionForTransformation (SgNode * root);

//  ROSE_DLL_API void setSourcePositionForTransformation_memoryPool();

  ROSE_DLL_API bool insideSystemHeader (SgLocatedNode* node);

// DQ (2/27/2021): Adding support to detect if a SgLocatedNode is located in a header file.
  ROSE_DLL_API bool insideHeader (SgLocatedNode* node);

// ROSE_DLL_API void setSourcePosition (SgLocatedNode * locatedNode);
// ************************************************************************



//------------------------------------------------------------------------

ROSE_DLL_API  std::string getTypeName ( SgType* type );

ROSE_DLL_API SgType* getBoolType(SgNode* n);

ROSE_DLL_API bool isStrictIntegerType(SgType* t);
ROSE_DLL_API SgType* getFirstVarType(SgVariableDeclaration* decl);

ROSE_DLL_API bool isDefaultConstructible(SgType* type);

ROSE_DLL_API bool isCopyConstructible(SgType* type);

ROSE_DLL_API bool isAssignable(SgType* type);

#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
ROSE_DLL_API bool isPureVirtualClass(SgType* type, const ClassHierarchyWrapper& classHierarchy);
#endif

ROSE_DLL_API bool hasTrivialDestructor(SgType* t);

ROSE_DLL_API bool isNonconstReference(SgType* t);

ROSE_DLL_API bool isReferenceType(SgType* t);

ROSE_DLL_API bool isPointerType(SgType* t);

ROSE_DLL_API bool isPointerToNonConstType(SgType* type);

/* const char* p = "aa"; is not treated as having a const type. It is a pointer to const char.
 * Similarly, neither for const int b[10]; or const int & c =10;
 * The standard says, "A compound type is not cv-qualified by the cv-qualifiers (if any) of
the types from which it is compounded. Any cv-qualifiers applied to an array type affect the array element type, not the array type".
 */
ROSE_DLL_API bool isConstType(SgType* t);

SgType* removeConst(SgType* t);

ROSE_DLL_API bool isVolatileType(SgType* t);

ROSE_DLL_API bool isRestrictType(SgType* t);


ROSE_DLL_API bool isScalarType(SgType* t);

ROSE_DLL_API bool isStrictIntegerType(SgType* t);

ROSE_DLL_API bool isStructType(SgType* t);

ROSE_DLL_API std::string mangleType(SgType* type);

ROSE_DLL_API std::string mangleScalarType(SgType* type);

ROSE_DLL_API std::string mangleModifierType(SgModifierType* type);

ROSE_DLL_API size_t getArrayElementCount(SgArrayType* t);

ROSE_DLL_API int getDimensionCount(SgType* t);

ROSE_DLL_API SgType* getArrayElementType(SgType* t);

ROSE_DLL_API SgType* getElementType(SgType* t);


std::vector<SgExpression*>
get_C_array_dimensions(const SgArrayType& arrtype);

std::vector<SgExpression*>
get_C_array_dimensions(const SgArrayType& arrtype, const SgVarRefExp& varref);

std::vector<SgExpression*>
get_C_array_dimensions(const SgArrayType& arrtype, SgInitializedName& initname);


ROSE_DLL_API bool isArrayReference(SgExpression* ref, SgExpression** arrayNameExp=NULL, std::vector<SgExpression*>** subscripts=NULL);


ROSE_DLL_API int collectVariableReferencesInArrayTypes (SgLocatedNode* root, Rose_STL_Container<SgNode*> & currentVarRefList);

ROSE_DLL_API bool hasUpcSharedType(SgType* t, SgModifierType ** mod_type_out = NULL  );


ROSE_DLL_API bool isUpcSharedType(SgType* t, SgModifierType ** mod_type_out = NULL);

ROSE_DLL_API bool isUpcSharedModifierType (SgModifierType* mod_type);

ROSE_DLL_API bool isUpcSharedArrayType (SgArrayType* array_type);

ROSE_DLL_API bool isUpcStrictSharedModifierType(SgModifierType* mode_type);

ROSE_DLL_API size_t getUpcSharedBlockSize(SgModifierType* mod_type);

ROSE_DLL_API size_t getUpcSharedBlockSize(SgType* t);

ROSE_DLL_API bool isUpcPhaseLessSharedType (SgType* t);

ROSE_DLL_API bool isUpcPrivateToSharedType(SgType* t);

ROSE_DLL_API bool isUpcArrayWithThreads(SgArrayType* t);

ROSE_DLL_API SgType* lookupNamedTypeInParentScopes(const std::string& type_name, SgScopeStatement* scope=NULL);

// DQ (7/22/2014): Added support for comparing expression types in actual arguments with those expected from the formal function parameter types.
ROSE_DLL_API SgType* getAssociatedTypeFromFunctionTypeList(SgExpression* actual_argument_expression);

ROSE_DLL_API bool templateArgumentEquivalence(SgTemplateArgument * arg1, SgTemplateArgument * arg2);

ROSE_DLL_API bool templateArgumentListEquivalence(const SgTemplateArgumentPtrList & list1, const SgTemplateArgumentPtrList & list2);

ROSE_DLL_API bool isEquivalentType (const SgType* lhs, const SgType* rhs);

ROSE_DLL_API SgFunctionType* findFunctionType (SgType* return_type, SgFunctionParameterTypeList* typeList);

ROSE_DLL_API bool isEquivalentFunctionType (const SgFunctionType* lhs, const SgFunctionType* rhs);


//------------------------------------------------------------------------

// by Jeremiah
ROSE_DLL_API void addStepToLoopBody(SgScopeStatement* loopStmt, SgStatement* step);

ROSE_DLL_API void moveForStatementIncrementIntoBody(SgForStatement* f);
ROSE_DLL_API void convertForToWhile(SgForStatement* f);
ROSE_DLL_API void convertAllForsToWhiles(SgNode* top);
ROSE_DLL_API void changeContinuesToGotos(SgStatement* stmt, SgLabelStatement* label);

ROSE_DLL_API SgInitializedName* getLoopIndexVariable(SgNode* loop);

ROSE_DLL_API bool isLoopIndexVariable(SgInitializedName* ivar, SgNode* subtree_root);


ROSE_DLL_API bool hasMultipleInitStatmentsOrExpressions (SgForStatement* for_loop);

ROSE_DLL_API SgStatement* getLoopBody(SgScopeStatement* loop);

ROSE_DLL_API void setLoopBody(SgScopeStatement* loop, SgStatement* body);

ROSE_DLL_API SgStatement* getLoopCondition(SgScopeStatement* loop);

ROSE_DLL_API void setLoopCondition(SgScopeStatement* loop, SgStatement* cond);

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);

ROSE_DLL_API bool isCanonicalDoLoop(SgFortranDo* loop,SgInitializedName** ivar/*=NULL*/, SgExpression** lb/*=NULL*/, SgExpression** ub/*=NULL*/, SgExpression** step/*=NULL*/, SgStatement** body/*=NULL*/, bool *hasIncrementalIterationSpace/*= NULL*/, bool* isInclusiveUpperBound/*=NULL*/);

ROSE_DLL_API void setLoopLowerBound(SgNode* loop, SgExpression* lb);

ROSE_DLL_API void setLoopUpperBound(SgNode* loop, SgExpression* ub);

ROSE_DLL_API void setLoopStride(SgNode* loop, SgExpression* stride);


ROSE_DLL_API bool normalizeForLoopInitDeclaration(SgForStatement* loop);

ROSE_DLL_API bool unnormalizeForLoopInitDeclaration(SgForStatement* loop);

ROSE_DLL_API bool forLoopNormalization(SgForStatement* loop, bool foldConstant = true);

ROSE_DLL_API bool normalizeForLoopTest(SgForStatement* loop);
ROSE_DLL_API bool normalizeForLoopIncrement(SgForStatement* loop);

ROSE_DLL_API bool doLoopNormalization(SgFortranDo* loop);

ROSE_DLL_API bool loopUnrolling(SgForStatement* loop, size_t unrolling_factor);

ROSE_DLL_API bool loopInterchange(SgForStatement* loop, size_t depth, size_t lexicoOrder);

ROSE_DLL_API bool loopTiling(SgForStatement* loopNest, size_t targetLevel, size_t tileSize);

//Winnie Loop Collapsing
SgExprListExp * loopCollapsing(SgForStatement* target_loop, size_t collapsing_factor);

bool getForLoopInformations(
  SgForStatement * for_loop,
  SgVariableSymbol * & iterator,
  SgExpression * & lower_bound,
  SgExpression * & upper_bound,
  SgExpression * & stride
);


//------------------------------------------------------------------------

template <typename NodeType>
std::vector<NodeType*> querySubTree(SgNode* top, VariantT variant = (VariantT)NodeType::static_variant)
   {
#if 0
     printf ("Top of SageInterface::querySubTree() \n");
#endif

     Rose_STL_Container<SgNode*> nodes = NodeQuery::querySubTree(top,variant);
     std::vector<NodeType*> result(nodes.size(), NULL);
     int count = 0;
#if 0
     printf ("In SageInterface::querySubTree(): before initialization loop \n");
#endif

     for (Rose_STL_Container<SgNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i, ++count)
        {
#if 0
          printf ("In SageInterface::querySubTree(): in loop: count = %d \n",count);
#endif
          NodeType* node = dynamic_cast<NodeType*>(*i);
          ROSE_ASSERT (node);
          result[count] = node;
        }
#if 0
     printf ("Leaving SageInterface::querySubTree(): after initialization loop \n");
#endif

     return result;
   }
    std::vector < SgFile * >generateFileList ();

ROSE_DLL_API SgProject * getProject();

  SgProject * getProject(const SgNode * node);

template <typename NodeType>
static std::vector<NodeType*> getSgNodeListFromMemoryPool()
{
  // This function uses a memory pool traversal specific to the SgFile IR nodes
  class MyTraversal : public ROSE_VisitTraversal
  {
    public:
      std::vector<NodeType*> resultlist;
      void visit ( SgNode* node)
      {
        NodeType* result = dynamic_cast<NodeType* > (node);
        ROSE_ASSERT(result!= NULL);
        if (result!= NULL)
        {
          resultlist.push_back(result);
        }
      };
      virtual ~MyTraversal() {}
  };

  MyTraversal my_traversal;
  NodeType::traverseMemoryPoolNodes(my_traversal);
  return my_traversal.resultlist;
}


ROSE_DLL_API SgFunctionDeclaration* findMain(SgNode* currentNode);

SgStatement* findLastDeclarationStatement(SgScopeStatement * scope, bool includePragma = false);

          //midend/programTransformation/partialRedundancyElimination/pre.h
std::vector<SgVariableSymbol*> getSymbolsUsedInExpression(SgExpression* expr);


std::vector<SgBreakStmt*> findBreakStmts(SgStatement* code, const std::string& fortranLabel = "");


std::vector<SgContinueStmt*> findContinueStmts(SgStatement* code, const std::string& fortranLabel = "");
std::vector<SgGotoStatement*> findGotoStmts(SgStatement* scope, SgLabelStatement* l);
std::vector<SgStatement*> getSwitchCases(SgSwitchStatement* sw);

void collectVarRefs(SgLocatedNode* root, std::vector<SgVarRefExp* >& result);

template <typename T>
T* findDeclarationStatement(SgNode* root, std::string name, SgScopeStatement* scope, bool isDefining)
   {
     bool found = false;

#if 0
     printf ("In findDeclarationStatement(): root       = %p \n",root);
     printf ("In findDeclarationStatement(): name       = %s \n",name.c_str());
     printf ("In findDeclarationStatement(): scope      = %p \n",scope);
     printf ("In findDeclarationStatement(): isDefining = %s \n",isDefining ? "true" : "false");
#endif

  // Do we really want a NULL pointer to be acceptable input to this function?
  // Maybe we should have an assertion that it is non-null?
     if (!root) return NULL;

     T* decl = dynamic_cast<T*>(root);

#if 0
     printf ("In findDeclarationStatement(): decl       = %p \n",decl);
#endif

     if (decl != NULL)
        {
          // CLANG FRONTEND FIX: search_for_symbol_from_symbol_table() can return NULL
          // for Clang-generated implicit/compiler-generated declarations
          SgSymbol* symbol = decl->search_for_symbol_from_symbol_table();

          if (symbol != NULL)
             {
               if (scope)
                  {
                    if ((decl->get_scope() == scope) && (symbol->get_name() == name))
                       {
                         found = true;
                       }
                  }
                 else // Liao 2/9/2010. We should allow NULL scope
                  {
#if 0
                 // DQ (12/6/2016): Include this into the debugging code to aboid compiler warning about unused variable.
                    printf ("In findDeclarationStatement(): decl->search_for_symbol_from_symbol_table() = %p \n",symbol);
                    printf ("In findDeclarationStatement(): decl->search_for_symbol_from_symbol_table()->get_name() = %s \n",symbol->get_name().str());
#endif
                    if (symbol->get_name() == name)
                       {
                         found = true;
                       }
                  }
             }
        }

     if (found)
        {
          if (isDefining)
             {
#if 0
               printf ("In findDeclarationStatement(): decl->get_firstNondefiningDeclaration() = %p \n",decl->get_firstNondefiningDeclaration());
               printf ("In findDeclarationStatement(): decl->get_definingDeclaration()         = %p \n",decl->get_definingDeclaration());
#endif
               ROSE_ASSERT (decl->get_definingDeclaration() != NULL);
#if 0
               printf ("In findDeclarationStatement(): returing decl->get_definingDeclaration() = %p \n",decl->get_definingDeclaration());
#endif
               return dynamic_cast<T*> (decl->get_definingDeclaration());
             }
            else
             {
#if 0
               printf ("In findDeclarationStatement(): returing decl = %p \n",decl);
#endif
               return decl;
             }
        }

     std::vector<SgNode*> children = root->get_traversalSuccessorContainer();

#if 0
     printf ("In findDeclarationStatement(): children.size() = %zu \n",children.size());
#endif

  // DQ (4/10/2016): Note that if we are searching for a function member that has it's defining
  // declaration defined outside of the class then it will not be found in the child list.
     for (std::vector<SgNode*>::const_iterator i = children.begin(); i != children.end(); ++i)
        {
          T* target = findDeclarationStatement<T> (*i,name,scope,isDefining);

          if (target)
             {
               return target;
             }
        }

     return NULL;
   }
  SgFunctionDeclaration* findFunctionDeclaration(SgNode* root, std::string name, SgScopeStatement* scope, bool isDefining);

#if 0 //TODO
  // 1. preorder traversal from current SgNode till find next SgNode of type V_SgXXX
  //    until reach the end node
  SgNode* getNextSgNode( const SgNode* astSourceNode, VariantT=V_SgNode, SgNode* astEndNode=NULL);

  // 2. return all nodes of type VariantT following the source node
  std::vector<SgNode*> getAllNextSgNode( const SgNode* astSourceNode, VariantT=V_SgNode, SgNode* astEndNode=NULL);
#endif


//------------------------------------------------------------------------

// remember to put const to all arguments.


template <typename NodeType>
NodeType* getEnclosingNode(const SgNode* astNode, const bool includingSelf = false)
   {
#define DEBUG_GET_ENCLOSING_NODE 0

#if 1 /* TOP_LEVEL_IF */
  // DQ (12/31/2019): This version does not detect a cycle that Robb's version detects in processing Cxx11_tests/test2016_23.C.
  // This will have to be investigated seperately from the issue I am working on currently.

  // DQ (10/20/2012): This is the older version of this implementation.  Until I am sure that
  // the newer version (below) is what we want to use I will resolve this conflict by keeping
  // the previous version in place.

     if (nullptr == astNode)
        {
          return nullptr;
        }

     if ( (includingSelf ) && (dynamic_cast<const NodeType*>(astNode)) )
        {
          return const_cast<NodeType*>(dynamic_cast<const NodeType*> (astNode));
        }

  // DQ (3/5/2012): Check for reference to self...
     ROSE_ASSERT(astNode->get_parent() != astNode);

     SgNode* parent = astNode->get_parent();

  // DQ (3/5/2012): Check for loops that will cause infinite loops.
     SgNode* previouslySeenParent = parent;
     bool foundCycle = false;
     int counter = 0;

#if DEBUG_GET_ENCLOSING_NODE
     printf ("In getEnclosingNode(): previouslySeenParent = %p = %s \n",previouslySeenParent,previouslySeenParent->class_name().c_str());
#endif

     while ( (foundCycle == false) && (parent != nullptr) && (!dynamic_cast<const NodeType*>(parent)) )
        {
          ROSE_ASSERT(parent->get_parent() != parent);

#if DEBUG_GET_ENCLOSING_NODE
          printf (" --- parent = %p = %s \n",parent,parent->class_name().c_str());
          printf (" --- --- parent->get_parent() = %p = %s \n",parent->get_parent(),parent->get_parent()->class_name().c_str());
#endif

#if 1
       // DQ (1/8/2020): ROSE-82 (on RZ) This limit needs to be larger and increasing it to 500 was enough
       // for a specific code with a long chain of if-then-else nesting, So to make this sufficent for more
       // general code we have increased the lomit to 100,000.  Note that 50 was not enough for real code,
       // but was enough for our regression tests.
       // DQ (12/30/2019): This is added to support detection of infinite loops over parent pointers.
       // if (counter >= 500)
          if (counter >= 100000)
             {
               printf ("Exiting: In getEnclosingNode(): loop limit exceeded: counter = %d \n",counter);
               ROSE_ABORT();
             }
#endif
          parent = parent->get_parent();

       // DQ (3/5/2012): Check for loops that will cause infinite loops.
       // ROSE_ASSERT(parent != previouslySeenParent);
          if (parent == previouslySeenParent)
             {
               foundCycle = true;
             }
          counter++;

        }

#if DEBUG_GET_ENCLOSING_NODE
     printf ("previouslySeenParent = %p = %s \n",previouslySeenParent,previouslySeenParent->class_name().c_str());
#endif

     parent = previouslySeenParent;

     SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(parent);
     if (declarationStatement != nullptr)
        {
#if 0
          printf ("Found a SgDeclarationStatement \n");
#endif
          SgDeclarationStatement* definingDeclaration         = declarationStatement->get_definingDeclaration();
          SgDeclarationStatement* firstNondefiningDeclaration = declarationStatement->get_firstNondefiningDeclaration();

#if 0
          printf (" --- declarationStatement         = %p \n",declarationStatement);
          printf (" --- definingDeclaration          = %p \n",definingDeclaration);
          if (definingDeclaration != NULL && definingDeclaration->get_parent() != NULL)
               printf (" --- definingDeclaration ->get_parent()         = %p = %s \n",definingDeclaration->get_parent(),definingDeclaration->get_parent()->class_name().c_str());
          printf (" --- firstNondefiningDeclaration  = %p \n",firstNondefiningDeclaration);
          if (firstNondefiningDeclaration != NULL && firstNondefiningDeclaration->get_parent() != NULL)
               printf (" --- firstNondefiningDeclaration ->get_parent() = %p = %s \n",firstNondefiningDeclaration->get_parent(),firstNondefiningDeclaration->get_parent()->class_name().c_str());
#endif
          if (definingDeclaration != nullptr && declarationStatement != firstNondefiningDeclaration)
             {
#if 0
               printf ("Found a nondefining declaration so use the non-defining declaration instead \n");
#endif
            // DQ (10/19/2012): Use the defining declaration instead.
            // parent = firstNondefiningDeclaration;
               parent = definingDeclaration;
             }
        }

#if 0
     printf ("reset: previouslySeenParent = %p = %s \n",previouslySeenParent,previouslySeenParent->class_name().c_str());
#endif

  // DQ (10/19/2012): This branch is just to document the cycle that was previously detected, it is for
  // debugging only. Thus it ony make sense for it to be executed when "(foundCycle == true)".  However,
  // this will have to be revisited later since it appears clear that it is a problem for the binary analysis
  // work when it is visited for this case.  Since the cycle is detected, but there is no assertion on the
  // cycle, we don't exit when a cycle is identified (which is the point of the code below).
  // Note also that I have fixed the code (above and below) to only chase pointers through defining
  // declarations (where they exist), this is important since non-defining declarations can be almost
  // anywhere (and thus chasing them can make it appear that there are cycles where there are none
  // (I think); test2012_234.C demonstrates an example of this.
  // DQ (10/9/2012): Robb has suggested this change to fix the binary analysis work.
  // if (foundCycle == true)
     if (foundCycle == false)
        {


          while ( (parent != nullptr) && (!dynamic_cast<const NodeType*>(parent)) )
             {
               ROSE_ASSERT(parent->get_parent() != parent);
#if 0
               printf ("In getEnclosingNode() (2nd try): parent = %p = %s \n",parent,parent->class_name().c_str());
               if (parent->get_file_info() != NULL)
                    parent->get_file_info()->display("In getEnclosingNode() (2nd try): debug");
#endif
               SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(parent);
               if (declarationStatement != nullptr)
                  {
#if DEBUG_GET_ENCLOSING_NODE
                    printf ("Found a SgDeclarationStatement \n");
#endif
                    SgDeclarationStatement* definingDeclaration         = declarationStatement->get_definingDeclaration();
                    SgDeclarationStatement* firstNondefiningDeclaration = declarationStatement->get_firstNondefiningDeclaration();
                    if (definingDeclaration != nullptr && declarationStatement != firstNondefiningDeclaration)
                       {
#if 0
                         printf ("Found a nondefining declaration so use the firstNondefining declaration instead \n");
#endif
                      // DQ (10/19/2012): Use the defining declaration instead.
                      // parent = firstNondefiningDeclaration;
                         parent = definingDeclaration;
                       }
                  }

               parent = parent->get_parent();

#if 1
            // DQ (3/5/2012): Check for loops that will cause infinite loops.
               ROSE_ASSERT(parent != previouslySeenParent);
#else
               printf ("WARNING::WARNING::WARNING commented out assertion for parent != previouslySeenParent \n");
               if (parent == previouslySeenParent)
                    break;
#endif
             }
        }

     return const_cast<NodeType*>(dynamic_cast<const NodeType*> (parent));
#else /* TOP_LEVEL_IF */
  // DQ (10/20/2012): Using Robb's newer version with my modification to use the definingDeclaration rather than firstNondefiningDeclaration (below).

       // Find the parent of specified type, but watch out for cycles in the ancestry (which would cause an infinite loop).
       // Cast away const because isSg* functions aren't defined for const node pointers; and our return is not const.
       SgNode *node = const_cast<SgNode*>(!astNode || includingSelf ? astNode : astNode->get_parent());
       std::set<const SgNode*> seen; // nodes we've seen, in order to detect cycles
       while (node) {
           if (NodeType *found = dynamic_cast<NodeType*>(node))
               return found;

        // FIXME: Cycle detection could be moved elsewhere so we don't need to do it on every call. [RPM 2012-10-09]
        // DQ (12/30/2019): Provide more detail in error message.
           if (seen.insert(node).second == false)
             {
               printf ("Error: node is already in set and defines a cycle: node = %p = %s \n",node,node->class_name().c_str());
               std::set<const SgNode*>::const_iterator i = seen.begin();
               while (i != seen.end())
                 {
                   const SgNode* element = *i;
                   printf (" --- seen element: element = %p = %s \n",element,element->class_name().c_str());
                   i++;
                 }

               printf ("Exiting after error! \n");
               ROSE_ABORT();
             }
           // ROSE_ASSERT(seen.insert(node).second);

           // Traverse to parent (declaration statements are a special case)
           if (SgDeclarationStatement *declarationStatement = isSgDeclarationStatement(node)) {
               SgDeclarationStatement *definingDeclaration = declarationStatement->get_definingDeclaration();
               SgDeclarationStatement *firstNondefiningDeclaration = declarationStatement->get_firstNondefiningDeclaration();
               if (definingDeclaration && firstNondefiningDeclaration && declarationStatement != firstNondefiningDeclaration) {
                // DQ (10/19/2012): Use the defining declaration instead.
                // node = firstNondefiningDeclaration;
                   node = definingDeclaration;
               }
           } else {
               node = node->get_parent();
           }
       }
       return NULL;
#endif /* TOP_LEVEL_IF */
   }

  ROSE_DLL_API SgSourceFile* getEnclosingSourceFile(const SgNode* n, const bool includingSelf=false);

  ROSE_DLL_API SgScopeStatement* getScope(const SgNode* astNode);

  ROSE_DLL_API SgScopeStatement* getEnclosingScope(SgNode* n, const bool includingSelf=false);

  ROSE_DLL_API SgGlobal* getGlobalScope( const SgNode* astNode);

 // DQ (12/7/2020): This is supporting the recognition of functions in header files from two different AST.
  ROSE_DLL_API bool hasSameGlobalScope ( SgStatement* statement_1, SgStatement* statement_2 );

  ROSE_DLL_API SgFunctionDefinition* getEnclosingProcedure(SgNode* n, const bool includingSelf=false);

  ROSE_DLL_API SgFunctionDefinition* getEnclosingFunctionDefinition(SgNode* astNode, const bool includingSelf=false);

  ROSE_DLL_API SgStatement* getEnclosingStatement(SgNode* n);

  ROSE_DLL_API SgSwitchStatement* findEnclosingSwitch(SgStatement* s);

  ROSE_DLL_API SgOmpClauseBodyStatement* findEnclosingOmpClauseBodyStatement(SgStatement* s);

  ROSE_DLL_API SgScopeStatement* findEnclosingLoop(SgStatement* s, const std::string& fortranLabel = "", bool stopOnSwitches = false);

  ROSE_DLL_API SgFunctionDeclaration * getEnclosingFunctionDeclaration (SgNode * astNode, const bool includingSelf=false);

  //roseSupport/utility_functions.h
  ROSE_DLL_API SgFile* getEnclosingFileNode (SgNode* astNode );

  ROSE_DLL_API SgInitializer* getInitializerOfExpression(SgExpression* n);

  ROSE_DLL_API SgClassDefinition* getEnclosingClassDefinition(SgNode* astnode, const bool includingSelf=false);

  ROSE_DLL_API SgClassDeclaration* getEnclosingClassDeclaration( SgNode* astNode );

  ROSE_DLL_API SgModuleStatement* getEnclosingModuleStatement( SgNode* astNode, const bool includingSelf = false);

  ROSE_DLL_API SgDeclarationStatement* getTemplateDeclaration( const SgNode* astNode);

  ROSE_DLL_API SgType* getAssociatedType( const SgNode* astNode );

  // DQ (2/7/2019): Adding support for name qualification of variable references associated with SgPointerMemberType function parameters.
  ROSE_DLL_API SgExprListExp* getEnclosingExprListExp(SgNode* astNode, const bool includingSelf = false);

  // DQ (2/7/2019): Need a function to return when an expression is in an expression subtree.
  // This is part of index evaluation ofr expressions in function argument lists, but likely usefule elsewhere as well.
  ROSE_DLL_API bool isInSubTree(SgExpression* subtree, SgExpression* exp);

  // DQ (2/7/2019): Need a function to return the SgFunctionDeclaration from a SgFunctionCallExp.
  ROSE_DLL_API SgFunctionDeclaration* getFunctionDeclaration ( SgFunctionCallExp* functionCallExp );

  // DQ (2/17/2019): Generalizing this support for SgVarRefExp and SgMemberFunctionRefExp nodes.
  // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
  ROSE_DLL_API bool isDataMemberReference(SgVarRefExp* varRefExp);
  // ROSE_DLL_API bool isAddressTaken(SgVarRefExp* varRefExp);
  ROSE_DLL_API bool isAddressTaken(SgExpression* refExp);

  // DQ (2/17/2019): Adding support for detecting when to use added name qualification for membr function references.
  ROSE_DLL_API bool isMemberFunctionMemberReference(SgMemberFunctionRefExp* memberFunctionRefExp);

  // DQ (2/15/2019): Adding support for detecting which class a member reference is being made from.
  // ROSE_DLL_API SgClassType* getClassTypeForDataMemberReference(SgVarRefExp* varRefExp);
  // ROSE_DLL_API std::list<SgClassType*> getClassTypeChainForDataMemberReference(SgVarRefExp* varRefExp);
  ROSE_DLL_API std::list<SgClassType*> getClassTypeChainForMemberReference(SgExpression* refExp);

  ROSE_DLL_API std::set<SgNode*> getFrontendSpecificNodes();

  // DQ (2/17/2019): Display the shared nodes in the AST for debugging.
  ROSE_DLL_API void outputSharedNodes( SgNode* node );

  // DQ (10/31/2020): Added function to help debug edits to statements in scopes.
  ROSE_DLL_API void displayScope(SgScopeStatement* scope);

// TODO
#if 0
   SgNode * getEnclosingSgNode(SgNode* source,VariantT, SgNode* endNode=NULL);
   std::vector<SgNode *>  getAllEnclosingSgNode(SgNode* source,VariantT, SgNode* endNode=NULL);
   SgVariableDeclaration* findVariableDeclaratin( const string& varname)

   SgClassDeclaration* getEnclosingClassDeclaration( const SgNode* astNode);

   // e.g. for some expression, find its parent statement
   SgStatement* getEnclosingStatement(const SgNode* astNode);

   SgSwitchStatement* getEnclosingSwitch(SgStatement* s);
   SgModuleStatement* getEnclosingModuleStatement( const SgNode* astNode);

  // used to build a variable reference for compiler generated code in current scope
   SgSymbol * findReachingDefinition (SgScopeStatement* startScope, SgName &name);
#endif

//------------------------------------------------------------------------

  // Liao, 1/9/2008
  ROSE_DLL_API SgGlobal * getFirstGlobalScope(SgProject *project);

  ROSE_DLL_API SgStatement* getLastStatement(SgScopeStatement *scope);

  ROSE_DLL_API SgStatement* getFirstStatement(SgScopeStatement *scope,bool includingCompilerGenerated=false);
  ROSE_DLL_API SgFunctionDeclaration* findFirstDefiningFunctionDecl(SgScopeStatement* scope);

  ROSE_DLL_API SgStatement* getNextStatement(SgStatement * currentStmt);

  ROSE_DLL_API SgStatement* getPreviousStatement(SgStatement * currentStmt, bool climbOutScope = true);
#if 0 //TODO
  // preorder traversal from current SgNode till find next SgNode of type V_SgXXX
  SgNode* getNextSgNode( const SgNode* currentNode, VariantT=V_SgNode);
#endif

  // DQ (11/15/2018): Adding support for traversals over the include file tree.
  void listHeaderFiles ( SgIncludeFile* includeFile );



//------------------------------------------------------------------------

 ROSE_DLL_API bool isEqualToIntConst(SgExpression* e, int value);


 ROSE_DLL_API bool isSameFunction(SgFunctionDeclaration* func1, SgFunctionDeclaration* func2);

 ROSE_DLL_API bool isLastStatement(SgStatement* stmt);


//------------------------------------------------------------------------

#if 1
struct DeferredTransformation
   {
  // DQ (11/19/2020): We need to expand the use of this to cover deffered transformations of common SageInterface transformations (e.g. replaceStatement).
  // So I needed to move this out of being specific to the outliner and make it more generally data structure in the SageInterface.

  // DQ (11/15/2020): Need to add the concept of deffered transformation to cover replaceStatement operations.

  // DQ (8/7/2019): Store data required to support defering the transformation to insert the outlined function prototypes
  // into class declaration (when this is required to support the outlined function's access to protected or private data members).
  // This is part of an optimization to support the optimization of header file unparsing (limiting the overhead of supporting any
  // header file to just focus on the few (typically one) header file that would have to be unparsed.

     enum TransformationKind
        {
       // DQ (11/22/2020): Might need to also add SageInterface::addDefaultConstructorIfRequired() and SageStatement::insert_statment()
       // to support the processStatements.C transforamtions to pre-process the AST (return expressions and variable initializations).
          e_error,
          e_default,
          e_outliner,
          e_replaceStatement,
          e_removeStatement,
          e_replaceDefiningFunctionDeclarationWithFunctionPrototype,
          e_last
        };

     TransformationKind deferredTransformationKind;

  // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
  // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
  // definitions in the dynamic library file with function prototypes.
     std::string transformationLabel;

  // Remove sets statementToRemove, replace sets statementToRemove and StatementToAdd.
     SgStatement* statementToRemove;
     SgStatement* statementToAdd;

     SgClassDefinition* class_definition;
     SgDeclarationStatement* target_class_member;
     SgDeclarationStatement* new_function_prototype;

     typedef std::set<SgClassDefinition *> ClassDefSet_t;
     ClassDefSet_t targetClasses;

     typedef std::vector<SgFunctionDeclaration *> FuncDeclList_t;
     FuncDeclList_t targetFriends;

  // DQ (2/28/2021): Adding support for outlining where it involves building up pre-transformations.
  // For example, in the code segregation, we build a conditiona around the interval of statements
  // that we are outlining. This conditional is used to overwrite the first statement in the interval
  // list.  Because we don't want to transform the AST until after the outlining, we need so save the
  // whole interval so that we, after the outlining, remove the statements in the interval after that
  // first statement.
     typedef std::vector<SgStatement*> IntervalType;
     IntervalType statementInterval;
     SgStatement* locationToOverwriteWithTransformation;
     SgStatement* transformationToOverwriteFirstStatementInInterval;
     SgBasicBlock* blockOfStatementsToOutline;

  // DQ (12/5/2019): Added ROSE_DLL_API prefix for Windows support (too all of these functions).
     ROSE_DLL_API DeferredTransformation();
     ROSE_DLL_API DeferredTransformation(SgClassDefinition* class_definition, SgDeclarationStatement* target_class_member, SgDeclarationStatement* new_function_prototype);
     ROSE_DLL_API DeferredTransformation (const DeferredTransformation& X);
     ROSE_DLL_API ~DeferredTransformation (void);

     ROSE_DLL_API DeferredTransformation & operator= (const DeferredTransformation& X);

  // DQ (11/20/20): static function to generate specialized version of deferred transformation object.
     static ROSE_DLL_API DeferredTransformation replaceDefiningFunctionDeclarationWithFunctionPrototype( SgFunctionDeclaration* functionDeclaration );
     static ROSE_DLL_API DeferredTransformation replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool movePreprocessinInfo = false);

     static ROSE_DLL_API std::string outputDeferredTransformationKind(const TransformationKind & kind);
     ROSE_DLL_API void display ( std::string label ) const;

   };
#endif


// DQ (2/24/2009): Simple function to delete an AST subtree (used in outlining).
ROSE_DLL_API void deleteAST(SgNode* node);

ROSE_DLL_API void deleteExpressionTreeWithOriginalExpressionSubtrees(SgNode* root);

// DQ (2/25/2009): Added new function to support outliner.
ROSE_DLL_API void moveStatementsBetweenBlocks ( SgBasicBlock* sourceBlock, SgBasicBlock* targetBlock );

ROSE_DLL_API void moveStatementsBetweenBlocks ( SgNamespaceDefinitionStatement* sourceBlock, SgNamespaceDefinitionStatement* targetBlock );

ROSE_DLL_API bool isLambdaFunction (SgFunctionDeclaration* func);

ROSE_DLL_API bool isLambdaCapturedVariable (SgVarRefExp* varRef);

ROSE_DLL_API void moveVariableDeclaration(SgVariableDeclaration* decl, SgScopeStatement* target_scope);
ROSE_DLL_API void appendStatement(SgStatement *stmt, SgScopeStatement* scope=NULL);

ROSE_DLL_API void appendStatement(SgStatement *stmt, SgForInitStatement* for_init_stmt);

ROSE_DLL_API void appendStatementList(const std::vector<SgStatement*>& stmt, SgScopeStatement* scope=NULL);

// DQ (2/6/2009): Added function to support outlining into separate file.
ROSE_DLL_API void appendStatementWithDependentDeclaration( SgDeclarationStatement* decl, SgGlobal* scope, SgStatement* original_statement, bool excludeHeaderFiles );

ROSE_DLL_API void prependStatement(SgStatement *stmt, SgScopeStatement* scope=NULL);

ROSE_DLL_API void prependStatement(SgStatement *stmt, SgForInitStatement* for_init_stmt);

ROSE_DLL_API void prependStatementList(const std::vector<SgStatement*>& stmt, SgScopeStatement* scope=NULL);

ROSE_DLL_API bool  hasSimpleChildrenList (SgScopeStatement* scope);

ROSE_DLL_API void insertStatement(SgStatement *targetStmt, SgStatement* newStmt, bool insertBefore= true, bool autoMovePreprocessingInfo = true);

//target's scope
ROSE_DLL_API void insertStatementList(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts, bool insertBefore= true);

ROSE_DLL_API void insertStatementBefore(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo = true);

ROSE_DLL_API void insertStatementListBefore(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts);

ROSE_DLL_API void insertStatementAfter(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo = true);

ROSE_DLL_API void insertStatementListAfter(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmt);

ROSE_DLL_API void insertStatementAfterLastDeclaration(SgStatement* stmt, SgScopeStatement* scope);

ROSE_DLL_API void insertStatementAfterLastDeclaration(std::vector<SgStatement*> stmt_list, SgScopeStatement* scope);

//  then the statement is inserted at the end of the scope.
ROSE_DLL_API void insertStatementBeforeFirstNonDeclaration(SgStatement *newStmt, SgScopeStatement *scope,
                                                           bool movePreprocessingInfo=true);

//then the new statements are inserted at the end of the scope.
ROSE_DLL_API void insertStatementListBeforeFirstNonDeclaration(const std::vector<SgStatement*> &newStmts, SgScopeStatement *scope);

// 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.
ROSE_DLL_API SgStatement* lastFrontEndSpecificStatement( SgGlobal* globalScope );

ROSE_DLL_API bool isRemovableStatement ( SgStatement* s );

ROSE_DLL_API void removeStatement(SgStatement* stmt, bool autoRelocatePreprocessingInfo = true);

ROSE_DLL_API void deepDelete(SgNode* root);

ROSE_DLL_API void replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool movePreprocessinInfo = false);

ROSE_DLL_API SgNode* replaceWithPattern (SgNode * anchor, SgNode* new_pattern);

// Essentially replace variable a with b.
ROSE_DLL_API void replaceVariableReferences(SgVariableSymbol* old_sym, SgVariableSymbol* new_sym, SgScopeStatement * scope );

// 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.
ROSE_DLL_API bool statementCanBeTransformed(SgStatement* stmt);


std::pair<SgVariableDeclaration*, SgExpression* > createTempVariableForExpression(SgExpression* expression,
        SgScopeStatement* scope, bool initializeInDeclaration, SgAssignOp** reEvaluate = NULL);

/*  This function creates a temporary variable for a given expression in the given scope
   This is different from SageInterface::createTempVariableForExpression in that it does not
   try to be smart to create pointers to reference types and so on. The tempt is initialized to expression.
   The caller is responsible for setting the parent of SgVariableDeclaration since buildVariableDeclaration
   may not set_parent() when the scope stack is empty. See programTransformation/extractFunctionArgumentsNormalization/ExtractFunctionArguments.C for sample usage.
   @param expression Expression which will be replaced by a variable
   @param scope scope in which the temporary variable will be generated
*/

std::pair<SgVariableDeclaration*, SgExpression*> createTempVariableAndReferenceForExpression
    (SgExpression* expression, SgScopeStatement* scope);


ROSE_DLL_API SgVariableSymbol* appendArg(SgFunctionParameterList *, SgInitializedName*);
ROSE_DLL_API SgVariableSymbol* prependArg(SgFunctionParameterList *, SgInitializedName*);

ROSE_DLL_API void appendExpression(SgExprListExp *, SgExpression*);

ROSE_DLL_API void appendExpressionList(SgExprListExp *, const std::vector<SgExpression*>&);

template <class actualFunction>
void setParameterList(actualFunction *func,SgFunctionParameterList *paralist) {

  // TODO consider the difference between C++ and Fortran
  // fixup the scope of arguments,no symbols for nondefining function declaration's arguments

  // DQ (11/25/2011): templated function so that we can handle both
  // SgFunctionDeclaration and SgTemplateFunctionDeclaration (and their associated member
  // function derived classes).

     ROSE_ASSERT(func != NULL);
     ROSE_ASSERT(paralist != NULL);

#if 0
  // At this point we don't have cerr and endl defined, so comment this code out.
  // Warn to users if a paralist is being shared
     if (paralist->get_parent() !=NULL)
        {
          cerr << "Waring! Setting a used SgFunctionParameterList to function: "
               << (func->get_name()).getString()<<endl
               << " Sharing parameter lists can corrupt symbol tables!"<<endl
               << " Please use deepCopy() to get an exclusive parameter list for each function declaration!"<<endl;
       // ROSE_ASSERT(false);
        }
#endif

  // Liao,2/5/2008  constructor of SgFunctionDeclaration will automatically generate SgFunctionParameterList, so be cautious when set new paralist!!
     if (func->get_parameterList() != NULL)
        {
          if (func->get_parameterList() != paralist)
             {
               delete func->get_parameterList();
             }
        }

     func->set_parameterList(paralist);
     paralist->set_parent(func);

     {
        // DQ (5/15/2012): Need to set the declptr in each SgInitializedName IR node.
        // This is needed to support the AST Copy mechanism (at least). The files: test2005_150.C,
        // test2012_81.C and testcode2012_82.C demonstrate this problem.
      SgInitializedNamePtrList & args = paralist->get_args();
       for (SgInitializedNamePtrList::iterator i = args.begin(); i != args.end(); i++)
        {
          (*i)->set_declptr(func);
        }
     }
   }

ROSE_DLL_API void setPragma(SgPragmaDeclaration* decl, SgPragma *pragma);

ROSE_DLL_API void replaceExpression(SgExpression* oldExp, SgExpression* newExp, bool keepOldExp=false);

ROSE_DLL_API void replaceExpressionWithStatement(SgExpression* from,
                                    SageInterface::StatementGenerator* to);
ROSE_DLL_API void replaceSubexpressionWithStatement(SgExpression* from,
                                      SageInterface::StatementGenerator* to);

ROSE_DLL_API void setOperand(SgExpression* target, SgExpression* operand);

ROSE_DLL_API void setLhsOperand(SgExpression* target, SgExpression* lhs);

ROSE_DLL_API void setRhsOperand(SgExpression* target, SgExpression* rhs);

ROSE_DLL_API void removeAllOriginalExpressionTrees(SgNode* top);

// DQ (1/25/2010): Added support for directories
ROSE_DLL_API void moveToSubdirectory ( std::string directoryName, SgFile* file );

ROSE_DLL_API SgStatement* findSurroundingStatementFromSameFile(SgStatement* targetStmt, bool & surroundingStatementPreceedsTargetStatement);

ROSE_DLL_API void moveCommentsToNewStatement(SgStatement* sourceStatement, const std::vector<int> & indexList, SgStatement* targetStatement, bool surroundingStatementPreceedsTargetStatement);

// DQ (7/19/2015): This is required to support general unparsing of template instantations for the GNU g++
// compiler which does not permit name qualification to be used to support the expression of the namespace
// where a template instantiatoon would be places.  Such name qualification would also sometimes require
// global qualification which is also not allowed by the GNU g++ compiler.  These issues appear to be
// specific to the GNU compiler versions, at least versions 4.4 through 4.8.
ROSE_DLL_API void moveDeclarationToAssociatedNamespace ( SgDeclarationStatement* declarationStatement );

ROSE_DLL_API bool isTemplateInstantiationNode(SgNode* node);

ROSE_DLL_API void wrapAllTemplateInstantiationsInAssociatedNamespaces(SgProject* root);

// DQ (12/1/2015): Adding support for fixup internal data struuctures that have references to statements (e.g. macro expansions).
ROSE_DLL_API void resetInternalMapsForTargetStatement(SgStatement* sourceStatement);

// DQ (6/7/2019): Add support for transforming function definitions to function prototypes in a subtree.
// We might have to make this specific to a file (only traversing the functions in that file).
ROSE_DLL_API void convertFunctionDefinitionsToFunctionPrototypes(SgNode* node);

// DQ (11/10/2019): Lower level support for convertFunctionDefinitionsToFunctionPrototypes().
// 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).
// ROSE_DLL_API void replaceDefiningFunctionDeclarationWithFunctionPrototype ( SgFunctionDeclaration* functionDeclaration );
// ROSE_DLL_API SgDeclarationStatement* replaceDefiningFunctionDeclarationWithFunctionPrototype ( SgFunctionDeclaration* functionDeclaration );
ROSE_DLL_API SgFunctionDeclaration* replaceDefiningFunctionDeclarationWithFunctionPrototype ( SgFunctionDeclaration* functionDeclaration );
ROSE_DLL_API std::vector<SgFunctionDeclaration*> generateFunctionDefinitionsList(SgNode* node);

// DQ (10/29/2020): build a function prototype for all but member functions outside of the class (except for template instantiations).
// The reason why member functions outside of the class are an exception is because they can not be used except in a class and there
// would already be one present for the code to compile.
ROSE_DLL_API SgFunctionDeclaration* buildFunctionPrototype ( SgFunctionDeclaration* functionDeclaration );


//------------------------------------------------------------------------


ROSE_DLL_API int fixVariableReferences(SgNode* root,  bool cleanUnusedSymbol=true);


ROSE_DLL_API void fixVariableDeclaration(SgVariableDeclaration* varDecl, SgScopeStatement* scope);

ROSE_DLL_API void fixStructDeclaration(SgClassDeclaration* structDecl, SgScopeStatement* scope);
ROSE_DLL_API void fixClassDeclaration(SgClassDeclaration* classDecl, SgScopeStatement* scope);

ROSE_DLL_API void fixNamespaceDeclaration(SgNamespaceDeclarationStatement* structDecl, SgScopeStatement* scope);


ROSE_DLL_API void fixLabelStatement(SgLabelStatement* label_stmt, SgScopeStatement* scope);

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);

ROSE_DLL_API int  suggestNextNumericLabel(SgFunctionDefinition* func_def);

ROSE_DLL_API void fixFunctionDeclaration(SgFunctionDeclaration* stmt, SgScopeStatement* scope);

ROSE_DLL_API void fixTemplateDeclaration(SgTemplateDeclaration* stmt, SgScopeStatement* scope);

ROSE_DLL_API void fixStatement(SgStatement* stmt, SgScopeStatement* scope);

// DQ (6/11/2015): This reports the statements that are marked as transformed (used to debug the token-based unparsing).
ROSE_DLL_API std::set<SgStatement*> collectTransformedStatements( SgNode* node );

ROSE_DLL_API std::set<SgStatement*> collectModifiedStatements( SgNode* node );

ROSE_DLL_API std::set<SgLocatedNode*> collectModifiedLocatedNodes( SgNode* node );

// DQ (6/5/2019): Use the previously constructed set (above) to reset the IR nodes to be marked as isModified.
ROSE_DLL_API void resetModifiedLocatedNodes(const std::set<SgLocatedNode*> & modifiedNodeSet);


// DQ (10/23/2018): Report nodes that are marked as modified.
ROSE_DLL_API void reportModifiedStatements(const std::string & label, SgNode* node);

// DQ (3/22/2019): Translate CPP directives from attached preprocessor information to CPP Directive Declaration IR nodes.
ROSE_DLL_API void translateToUseCppDeclarations( SgNode* n );

ROSE_DLL_API void translateScopeToUseCppDeclarations( SgScopeStatement* scope );

ROSE_DLL_API std::vector<SgC_PreprocessorDirectiveStatement*> translateStatementToUseCppDeclarations( SgStatement* statement, SgScopeStatement* scope);
ROSE_DLL_API void printOutComments ( SgLocatedNode* locatedNode );
ROSE_DLL_API bool skipTranslateToUseCppDeclaration( PreprocessingInfo* currentPreprocessingInfo );

// DQ (12/2/2019): Debugging support.
ROSE_DLL_API void outputFileIds( SgNode* node );




ROSE_DLL_API void updateDefiningNondefiningLinks(SgFunctionDeclaration* func, SgScopeStatement* scope);

//------------------------------------------------------------------------

ROSE_DLL_API bool
collectReadWriteRefs(SgStatement* stmt, std::vector<SgNode*>& readRefs, std::vector<SgNode*>& writeRefs, bool useCachedDefUse=false);

ROSE_DLL_API bool collectReadWriteVariables(SgStatement* stmt, std::set<SgInitializedName*>& readVars, std::set<SgInitializedName*>& writeVars, bool coarseGrain=true);

ROSE_DLL_API void collectReadOnlyVariables(SgStatement* stmt, std::set<SgInitializedName*>& readOnlyVars, bool coarseGrain=true);

ROSE_DLL_API void collectReadOnlySymbols(SgStatement* stmt, std::set<SgVariableSymbol*>& readOnlySymbols, bool coarseGrain=true);

ROSE_DLL_API bool isUseByAddressVariableRef(SgVarRefExp* ref);

ROSE_DLL_API void collectUseByAddressVariableRefs (const SgStatement* s, std::set<SgVarRefExp* >& varSetB);

#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
ROSE_DLL_API LivenessAnalysis * call_liveness_analysis(SgProject* project, bool debug=false);

ROSE_DLL_API void getLiveVariables(LivenessAnalysis * liv, SgForStatement* loop, std::set<SgInitializedName*>& liveIns, std::set<SgInitializedName*> & liveOuts);
#endif

ROSE_DLL_API void ReductionRecognition(SgForStatement* loop, std::set< std::pair <SgInitializedName*, OmpSupport::omp_construct_enum> > & results);


ROSE_DLL_API void constantFolding(SgNode* r);


ROSE_DLL_API int instrumentEndOfFunction(SgFunctionDeclaration * func, SgStatement* s);

ROSE_DLL_API void removeJumpsToNextStatement(SgNode*);

ROSE_DLL_API void removeUnusedLabels(SgNode* top, bool keepChild =false);

ROSE_DLL_API std::set<SgLabelStatement*> findUnusedLabels (SgNode* top);

ROSE_DLL_API void removeConsecutiveLabels(SgNode* top);


ROSE_DLL_API bool mergeDeclarationAndAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt, bool removeAssignStmt = true);


ROSE_DLL_API bool mergeAssignmentWithDeclaration (SgExprStatement* assign_stmt, SgVariableDeclaration* decl, bool removeAssignStmt = true);


ROSE_DLL_API bool mergeDeclarationWithAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt);


ROSE_DLL_API SgExprStatement* splitVariableDeclaration (SgVariableDeclaration* decl);

ROSE_DLL_API int splitVariableDeclaration (SgScopeStatement* scope, bool topLevelOnly = true);


 ROSE_DLL_API SgAssignInitializer* splitExpression(SgExpression* from, std::string newName = "");

ROSE_DLL_API void splitExpressionIntoBasicBlock(SgExpression* expr);

ROSE_DLL_API void removeLabeledGotos(SgNode* top);

ROSE_DLL_API void changeBreakStatementsToGotos(SgStatement* loopOrSwitch);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsBodyOfFor(SgForStatement* fs);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsBodyOfUpcForAll(SgUpcForAllStatement* fs);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsBodyOfWhile(SgWhileStmt* ws);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsBodyOfDoWhile(SgDoWhileStmt* ws);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsBodyOfSwitch(SgSwitchStatement* ws);

SgBasicBlock* ensureBasicBlockAsBodyOfCaseOption(SgCaseOptionStmt* cs);

SgBasicBlock* ensureBasicBlockAsBodyOfDefaultOption(SgDefaultOptionStmt * cs);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsTrueBodyOfIf(SgIfStmt* ifs);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsFalseBodyOfIf(SgIfStmt* ifs, bool createEmptyBody = true);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsBodyOfCatch(SgCatchOptionStmt* cos);

ROSE_DLL_API SgBasicBlock* ensureBasicBlockAsBodyOfOmpBodyStmt(SgOmpBodyStatement* ompbodyStmt);

// DQ (1/18/2015): This is added to support better quality token-based unparsing.
ROSE_DLL_API void cleanupNontransformedBasicBlockNode();

// DQ (1/18/2015): This is added to support better quality token-based unparsing.
ROSE_DLL_API void recordNormalizations(SgStatement* s);

bool isBodyStatement (SgStatement* s);

void changeAllBodiesToBlocks(SgNode* top, bool createEmptyBody = true);

// The same as changeAllBodiesToBlocks(SgNode* top). Phased out.
//void changeAllLoopBodiesToBlocks(SgNode* top);

SgBasicBlock * makeSingleStatementBodyToBlock(SgStatement* singleStmt);

#if 0
SgLocatedNode* ensureBasicBlockAsParent(SgStatement* s);
#endif

unsigned long long getIntegerConstantValue(SgValueExp* expr);

std::vector<SgDeclarationStatement*> getDependentDeclarations (SgStatement* stmt );


SgCommaOpExp *insertBeforeUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp);

SgCommaOpExp *insertAfterUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp, SgStatement** temp_decl = NULL, SgVarRefExp** temp_ref = NULL);


std::pair<SgStatement*, SgInitializedName*>
wrapFunction(SgFunctionDeclaration& definingDeclaration, SgName newName);

template <class NameGen>
std::pair<SgStatement*, SgInitializedName*>
wrapFunction(SgFunctionDeclaration& definingDeclaration, NameGen nameGen)
{
  return wrapFunction(definingDeclaration, nameGen(definingDeclaration.get_name()));
}

SgInitializedName& getFirstVariable(SgVariableDeclaration& vardecl);



// DQ (6/7/2012): Unclear where this function should go...
  bool hasTemplateSyntax( const SgName & name );

#if 0

//------------------------AST dump, stringify-----------------------------
//------------------------------------------------------------------------
  std::string buildOperatorString ( SgNode* astNode ); //transformationSupport.h

  // do we need these?
  std::string dump_node(const SgNode* astNode);
  std::string dump_tree(const SgNode* astNode);

  // or a friendly version of  unparseToString(), as a memeber function
  std::string SgNode::toString(bool asSubTree=true); // dump node or subtree

//----------------------------AST comparison------------------------------
//------------------------------------------------------------------------
// How to get generic functions for comparison?
  bool isNodeEqual(SgNode* node1, SgNode* node2); //?
  bool isTreeEqual(SgNode* tree1, SgNode* tree2);

  bool expressionTreeEqual(SgExpression*, SgExpression*);
  bool expressionTreeEqualStar(const SgExpressionPtrList&,
                             const SgExpressionPtrList&);

//----------------------AST verfication/repair----------------------------
//------------------------------------------------------------------------
// sanity check of AST subtree, any suggestions?
//  TODO
    verifySgNode(SgNode* node, bool subTree=true);
  //src/midend/astDiagnostics/AstConsistencyTests.h
  // AstTests::runAllTests(SgProject * )

  //src/midend/astUtil/astInterface/AstInterface.h.C
  //FixSgProject(SgProject &project)
  //FixSgTree(SgNode* r)

  //src/frontend/SageIII/astPostProcessing
  //AstPostProcessing(SgNode * node)

//--------------------------AST modification------------------------------
//------------------------------------------------------------------------
// any operations changing AST tree, including
// insert, copy, delete(remove), replace

  // insert before or after some point, argument list is consistent with LowLevelRewrite
  void insertAst(SgNode* targetPosition, SgNode* newNode, bool insertBefore=true);

  // previous examples
  //void myStatementInsert(SgStatement* target,...)
  // void AstInterfaceBase::InsertStmt(AstNodePtr const & orig, AstNodePtr const &n, bool insertbefore, bool extractfromBasicBlock)

  // copy
  // copy children of one basic block to another basic block
  //void appendStatementCopy (const SgBasicBlock* a, SgBasicBlock* b);
  void copyStatements (const SgBasicBlock* src, SgBasicBlock* dst);

  // delete (remove) a node or a whole subtree
  void removeSgNode(SgNode* targetNode); // need this?
  void removeSgNodeTree(SgNode* subtree); // need this?

  void removeStatement( SgStatement* targetStmt);

  //Move = delete + insert
  void moveAst (SgNode* src, SgNode* target); // need this?
      // similar to
  void moveStatements (SgBasicBlock* src, SgBasicBlock* target);

  // replace= delete old + insert new (via building or copying)

// DQ (1/25/2010): This does not appear to exist as a definition anywhere in ROSE.
// void replaceAst(SgNode* oldNode, SgNode* newNode);

   //void replaceChild(SgNode* parent, SgNode* from, SgNode* to);
   //bool AstInterface::ReplaceAst( const AstNodePtr& orig, const AstNodePtr& n)

//--------------------------AST transformations---------------------------
//------------------------------------------------------------------------
// Advanced AST modifications through basic AST modifications
// Might not be included in AST utitlity list, but listed here for the record.

  // extract statements/content from a scope
  void flattenBlocks(SgNode* n);

  //src/midend/astInlining/inlinerSupport.h
  void renameVariables(SgNode* n);
  void renameLabels(SgNode* n, SgFunctionDefinition* enclosingFunctionDefinition);

  void simpleCopyAndConstantPropagation(SgNode* top);
  void changeAllMembersToPublic(SgNode* n);

  void removeVariableDeclaration(SgInitializedName* initname);

  SgAssignOp* convertInitializerIntoAssignment(SgAssignInitializer* init);

  void pushTestIntoBody(LoopStatement* loopStmt);

  //programTransformation/finiteDifferencing/finiteDifferencing.h
  void moveForDeclaredVariables(SgNode* root);

//------------------------ Is/Has functions ------------------------------
//------------------------------------------------------------------------
// misc. boolean functions
// some of them could moved to SgXXX class as a member function

  bool isOverloaded (SgFunctionDeclaration * functionDeclaration);

  bool isSwitchCond (const SgStatement* s);
  bool isIfCond (const SgStatement* s);
  bool isWhileCond (const SgStatement* s);
  bool isStdNamespace (const SgScopeStatement* scope);
  bool isTemplateInst (const SgDeclarationStatement* decl);


  bool isCtor (const SgFunctionDeclaration* func);
  bool isDtor (const SgFunctionDeclaration* func);

   // src/midend/astInlining/typeTraits.h
  bool hasTrivialDestructor(SgType* t);
  ROSE_DLL_API bool isNonconstReference(SgType* t);
  ROSE_DLL_API bool isReferenceType(SgType* t);

  //  generic ones, or move to the SgXXX class as a member function

  bool isConst(SgNode* node); // const type, variable, function, etc.
  // .... and more

  bool isConstType (const SgType* type);
  bool isConstFunction (const SgFunctionDeclaration* decl);


  bool isMemberVariable(const SgInitializedName & var);
  //bool isMemberVariable(const SgNode& in);

  bool isPrototypeInScope (SgScopeStatement * scope,
                           SgFunctionDeclaration * functionDeclaration,
                           SgDeclarationStatement * startingAtDeclaration);

  bool MayRedefined(SgExpression* expr, SgNode* root);
  // bool isPotentiallyModified(SgExpression* expr, SgNode* root); // inlinderSupport.h
  bool hasAddressTaken(SgExpression* expr, SgNode* root);

  //src/midend/astInlining/inlinerSupport.C
     // can also classified as topdown search
  bool containsVariableReference(SgNode* root, SgInitializedName* var);

  bool isDeclarationOf(SgVariableDeclaration* decl, SgInitializedName* var);
  bool isPotentiallyModifiedDuringLifeOf(SgBasicBlock* sc,
                                       SgInitializedName* toCheck,
                                       SgInitializedName* lifetime)
  //src/midend/programTransformation/partialRedundancyElimination/pre.h
  bool anyOfListPotentiallyModifiedIn(const std::vector<SgVariableSymbol*>& syms, SgNode* n);

//------------------------ loop handling ---------------------------------
//------------------------------------------------------------------------
  //get and set loop control expressions
  // 0: init expr, 1: condition expr, 2: stride expr

  SgExpression* getForLoopTripleValues(int valuetype,SgForStatement* forstmt );
  int setForLoopTripleValues(int valuetype,SgForStatement* forstmt, SgExpression* exp);

  bool isLoopIndexVarRef(SgForStatement* forstmt, SgVarRefExp *varref);
  SgInitializedName * getLoopIndexVar(SgForStatement* forstmt);

//------------------------expressions-------------------------------------
//------------------------------------------------------------------------
  //src/midend/programTransformation/partialRedundancyElimination/pre.h
  int countComputationsOfExpressionIn(SgExpression* expr, SgNode* root);

        //src/midend/astInlining/replaceExpressionWithStatement.h
  void replaceAssignmentStmtWithStatement(SgExprStatement* from, StatementGenerator* to);

  void replaceSubexpressionWithStatement(SgExpression* from,
                                       StatementGenerator* to);
  SgExpression* getRootOfExpression(SgExpression* n);

//--------------------------preprocessing info. -------------------------
//------------------------------------------------------------------------
  void cutPreprocInfo (SgBasicBlock* b,
                       PreprocessingInfo::RelativePositionType pos,
                       AttachedPreprocessingInfoType& save_buf);
  void pastePreprocInfoFront (AttachedPreprocessingInfoType& save_buf,
                              SgStatement* s);
  void pastePreprocInfoBack (AttachedPreprocessingInfoType& save_buf,
                             SgStatement* s);

  // a generic one for all
  void moveBeforePreprocInfo (SgStatement* src, SgStatement* dest);
  void moveInsidePreprocInfo (SgBasicBlock* src, SgBasicBlock* dest);
  void moveAfterPreprocInfo (SgStatement* src, SgStatement* dest);

//--------------------------------operator--------------------------------
//------------------------------------------------------------------------
  from transformationSupport.h, not sure if they should be included here
  /* return enum code for SAGE operators */
  operatorCodeType classifyOverloadedOperator(); // transformationSupport.h

  std::string stringifyOperator (std::string name);

//--------------------------------macro ----------------------------------
//------------------------------------------------------------------------
  std::string buildMacro ( std::string s ); //transformationSupport.h

//--------------------------------access functions---------------------------
//----------------------------------get/set sth.-----------------------------
// several categories:
* get/set a direct child/grandchild node or fields
* get/set a property flag value
* get a descendent child node using preorder searching
* get an ancestor node using bottomup/reverse searching

        // SgName or string?
  std::string getFunctionName (SgFunctionCallExp* functionCallExp);
  std::string getFunctionTypeName ( SgFunctionCallExp* functionCallExpression );

    // do we need them anymore? or existing member functions are enought?
    // a generic one:
   std::string get_name (const SgNode* node);
   std::string get_name (const SgDeclarationStatement * declaration);

  // get/set some property: should moved to SgXXX as an inherent memeber function?
  // access modifier
  void  setExtern (SgFunctionDeclartion*)
  void  clearExtern()

   // similarly for other declarations and other properties
  void setExtern (SgVariableDeclaration*)
  void setPublic()
  void setPrivate()

#endif

// DQ (1/23/2013): Added support for generated a set of source sequence entries.
   std::set<unsigned int> collectSourceSequenceNumbers( SgNode* astNode );

//--------------------------------Type Traits (C++)---------------------------
      bool HasNoThrowAssign(const SgType * const inputType);
      bool HasNoThrowCopy(const SgType * const inputType);
      bool HasNoThrowConstructor(const SgType * const inputType);
      bool HasTrivialAssign(const SgType * const inputType);
      bool HasTrivialCopy(const SgType * const inputType);
      bool HasTrivialConstructor(const SgType * const inputType);
      bool HasTrivialDestructor(const SgType * const inputType);
      bool HasVirtualDestructor(const SgType * const inputType);
      bool IsBaseOf(const SgType * const inputBaseType, const SgType * const inputDerivedType);
      bool IsAbstract(const SgType * const inputType);
      bool IsClass(const SgType * const inputType);
      bool IsEmpty(const SgType * const inputType);
      bool IsEnum(const SgType * const inputType);
      bool IsPod(const SgType * const inputType);
      bool IsPolymorphic(const SgType * const inputType);
      bool IsStandardLayout(const SgType * const inputType);
      bool IsLiteralType(const SgType * const inputType);
      bool IsTrivial(const SgType * const inputType);
      bool IsUnion(const SgType * const inputType);
      SgType *  UnderlyingType(SgType *type);

// DQ (3/2/2014): Added a new interface function (used in the snippet insertion support).
//   void supportForInitializedNameLists ( SgScopeStatement* scope, SgInitializedNamePtrList & variableList );

// DQ (3/4/2014): Added support for testing two trees for equivalents using the AST iterators.
   bool isStructurallyEquivalentAST( SgNode* tree1, SgNode* tree2 );

// JP (10/14/24): Moved code to evaluate a const integer expression (like in array size definitions) to SageInterface
  struct const_int_expr_t {
    size_t value_;
    bool hasValue_;
  };
  struct const_int_expr_t evaluateConstIntegerExpression(SgExpression *expr);

// JP (9/17/14): Added function to test whether two SgType* are equivalent or not
   bool checkTypesAreEqual(SgType *typeA, SgType *typeB);


// DQ (8/31/2016): Making this a template function so that we can have it work with user defined filters.

template < class T >
bool isTemplateInstantiationFromTemplateDeclarationSatisfyingFilter (SgFunctionDeclaration* function, T* filter )
   {
  // DQ (9/1/2016): This function is called in the Call graph generation to avoid filtering out EDG normalized
  // function template instnatiations (which come from normalized template functions and member functions).
  // Note that because of the EDG normailzation the membr function is moved outside of the class, and
  // thus marked as compiler generated.  However the template instantiations are always marked as compiler
  // generated (if not specializations) and so we want to include a template instantiation that is marked
  // as compiler generated, but is from a template declaration that satisfyied a specific user defined filter.
  // The complexity of this detection is isolated here, but knowing that it must be called is more complex.
  // This function is call in the CG.C file of tests/nonsmoke/functional/roseTests/programAnalysisTests/testCallGraphAnalysis.

     bool retval = false;

#define DEBUG_TEMPLATE_NORMALIZATION_DETECTION 0

#if DEBUG_TEMPLATE_NORMALIZATION_DETECTION
     printf ("In isNormalizedTemplateInstantiation(): function = %p = %s = %s \n",function,function->class_name().c_str(),function->get_name().str());
#endif

  // Test for this to be a template instantation (in which case it was marked as
  // compiler generated but we may want to allow it to be used in the call graph,
  // if it's template was a part was defined in the current directory).
     SgTemplateInstantiationFunctionDecl*       templateInstantiationFunction       = isSgTemplateInstantiationFunctionDecl(function);
     SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(function);

     if (templateInstantiationFunction != NULL)
        {
       // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
          templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(templateInstantiationFunction->get_firstNondefiningDeclaration());
          SgTemplateFunctionDeclaration* templateFunctionDeclaration = templateInstantiationFunction->get_templateDeclaration();
          if (templateFunctionDeclaration != NULL)
             {
               retval = filter->operator()(templateFunctionDeclaration);
             }
            else
             {
             // Assume false.
             }

#if DEBUG_TEMPLATE_NORMALIZATION_DETECTION
          printf ("   --- case of templateInstantiationFunction: retval = %s \n",retval ? "true" : "false");
#endif
        }
       else
        {
          if (templateInstantiationMemberFunction != NULL)
             {
            // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
               templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(templateInstantiationMemberFunction->get_firstNondefiningDeclaration());
               SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = templateInstantiationMemberFunction->get_templateDeclaration();
               if (templateMemberFunctionDeclaration != NULL)
                  {
                    retval = filter->operator()(templateMemberFunctionDeclaration);
                  }
                 else
                  {
                 // Assume false.
                  }

#if DEBUG_TEMPLATE_NORMALIZATION_DETECTION
               printf ("   --- case of templateInstantiationMemberFunction: retval = %s \n",retval ? "true" : "false");
#endif
             }
        }

     return retval;
   }

void detectCycleInType(SgType * type, const std::string & from);

// DQ (7/14/2020): Debugging support.
void checkForInitializers( SgNode* node );

void clearSharedGlobalScopes(SgProject * project);

}// end of namespace

#endif