PrefixSynthesizedAttribute
PrefixSuffixGenerationTraversal::evaluateSynthesizedAttribute (
     SgNode* astNode,
     PrefixInheritedAttribute inputInheritedAttribute,
     SynthesizedAttributesList inputSynthesizedAttributeList )
   {
#if 0
     printf ("@@@ In evaluateSynthesizedAttribute: astNode = %s \n",astNode->sage_class_name());
     printf ("     inputSynthesizedAttributeList.size() = %zu \n",inputSynthesizedAttributeList.size());
#endif

     return PrefixSynthesizedAttribute();
   }
SynthesizedAttribute
Traversal::evaluateSynthesizedAttribute ( SgNode* astNode, InheritedAttribute inheritedAttribute, SynthesizedAttributesList childAttributes )
   {
     SynthesizedAttribute localResult;

  // printf ("evaluateSynthesizedAttribute(): astNode = %p = %s inheritedAttribute.isFirstFile = %s \n",astNode,astNode->class_name().c_str(),inheritedAttribute.isFirstFile ? "true" : "false");

  // Accumulate any valid pointer to main on a child node and pass it to the local synthesized attribute.
     for (size_t i = 0; i < childAttributes.size(); i++)
        {
          if (childAttributes[i].main_function != NULL)
             {
               localResult.main_function = childAttributes[i].main_function;
             }
        }

     if (inheritedAttribute.isFirstFile == true)
        {
          SgGlobal* globalScope = isSgGlobal(astNode);
          if (globalScope != NULL)
             {
            // Gather all of the functions in global scope of the first file.

               vector<SgDeclarationStatement*> globalScopeDeclarationsToMove = globalScope->get_declarations();
               inheritedAttribute.statements_from_first_file = globalScopeDeclarationsToMove;

            // printf ("evaluateSynthesizedAttribute(): Gather all of the functions in global scope of the first file inheritedAttribute.statements_from_first_file.size() = %zu \n",inheritedAttribute.statements_from_first_file.size());

            // Erase the declarations in the global scope of the first file.
               globalScope->get_declarations().clear();
             }

          SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(astNode);
          if (declarationStatement != NULL && isSgGlobal(declarationStatement->get_parent()) != NULL)
             {
            // Mark as a transformation (recursively mark the whole subtree).
            // printf ("*** Mark as a transformation: declarationStatement = %p \n",declarationStatement);
               markAsTransformation(declarationStatement);
               if (declarationStatement->get_firstNondefiningDeclaration() != NULL)
                    markAsTransformation(declarationStatement->get_firstNondefiningDeclaration());
             }
        }
       else
        {
          SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(astNode);
          if (functionDeclaration != NULL && functionDeclaration->get_name() == "main")
             {
            // Save the pointer to the main function (in the second file).
               localResult.main_function = functionDeclaration;
            // printf ("Found the main function ...(saved pointer) inheritedAttribute.main_function = %p \n",localResult.main_function);
             }

       // printf ("evaluateSynthesizedAttribute(): localResult.main_function = %p \n",localResult.main_function);

       // Test for the selected insertion point in the 2nd file for the declarations gathered from the first file.
          SgGlobal* globalScope = isSgGlobal(astNode);
          if (globalScope != NULL && localResult.main_function != NULL)
             {
               printf ("evaluateSynthesizedAttribute(): Found the main function ...\n");
               vector<SgDeclarationStatement*>::iterator i = find(globalScope->get_declarations().begin(),globalScope->get_declarations().end(),localResult.main_function);
               globalScope->get_declarations().insert(i,inheritedAttribute.statements_from_first_file.begin(),inheritedAttribute.statements_from_first_file.end());
#if 0
            // Set the parents of each declaration to match the new location (avoids warning that might later be an error).
               for (size_t i = 0; i < inheritedAttribute.statements_from_first_file.size(); i++)
                  {
                    inheritedAttribute.statements_from_first_file[i]->set_parent(globalScope);
                  }
#endif
             }
        }

     return localResult;
   }
ChildUses DefsAndUsesTraversal::evaluateSynthesizedAttribute(SgNode* node, SynthesizedAttributesList attrs)
{
    if (StaticSingleAssignment::getDebug())
    {
        cout << "---------<" << node->class_name() << node << ">-------" << node << endl;
    }

    //We want to propagate the def/use information up from the varRefs to the higher expressions.
    if (SgInitializedName * initName = isSgInitializedName(node))
    {
        VarUniqueName * uName = StaticSingleAssignment::getUniqueName(node);
        ROSE_ASSERT(uName);

        //Add this as a def, unless this initialized name is a preinitialization of a parent class. For example,
        //in the base of B : A(3) { ... } where A is a superclass of B, an initialized name for A appears.
        //Clearly, the initialized name for the parent class is not a real variable
        if (initName->get_preinitialization() != SgInitializedName::e_virtual_base_class
                && initName->get_preinitialization() != SgInitializedName::e_nonvirtual_base_class)
        {
            ssa->getOriginalDefTable()[node].insert(uName->getKey());

            if (StaticSingleAssignment::getDebug())
            {
                cout << "Defined " << uName->getNameString() << endl;
            }
        }

        return ChildUses();
    }
    
    //Variable references are where all uses originate
    else if (isSgVarRefExp(node))
    {
        //Get the unique name of the def.
        VarUniqueName * uName = StaticSingleAssignment::getUniqueName(node);

        //In some cases, a varRef isn't actually part of a variable name. For example,
        //foo().x where foo returns a structure. x is an SgVarRefExp, but is not part of a variable name.
        if (uName == NULL)
        {
            return ChildUses();
        }

        //Add this as a use. If it's not a use (e.g. target of an assignment), we'll fix it up later.
        ssa->getLocalUsesTable()[node].insert(uName->getKey());

        if (StaticSingleAssignment::getDebug())
        {
            cout << "Found use for " << uName->getNameString() << " at " << node->cfgForBeginning().toStringForDebugging() << endl;
        }

        //This varref is both the only use in the subtree and the current variable
        return ChildUses(node, isSgVarRefExp(node));
    }
    
    //Catch all types of Binary Operations
    else if (SgBinaryOp * binaryOp = isSgBinaryOp(node))
    {
        ROSE_ASSERT(attrs.size() == 2 && "Error: BinaryOp without exactly 2 children.");
        ChildUses& lhs = attrs[0];
        ChildUses& rhs = attrs[1];

        //If we have an assigning operation, we want to list everything on the LHS as being defined
        //Otherwise, everything is being used.
        vector<SgNode*> uses;
        switch (binaryOp->variantT())
        {
                //All the binary ops that define the LHS
            case V_SgAndAssignOp:
            case V_SgDivAssignOp:
            case V_SgIorAssignOp:
            case V_SgLshiftAssignOp:
            case V_SgMinusAssignOp:
            case V_SgModAssignOp:
            case V_SgMultAssignOp:
            case V_SgPlusAssignOp:
            case V_SgPointerAssignOp:
            case V_SgRshiftAssignOp:
            case V_SgXorAssignOp:
            case V_SgAssignOp:
            {
                //All the uses from the RHS are propagated
                uses.insert(uses.end(), rhs.getUses().begin(), rhs.getUses().end());

                //All the uses from the LHS are propagated, unless we're an assign op
                uses.insert(uses.end(), lhs.getUses().begin(), lhs.getUses().end());

                SgVarRefExp* currentVar = lhs.getCurrentVar();

                if (currentVar != NULL)
                {
                    vector<SgNode*>::iterator currVarUse = find(uses.begin(), uses.end(), currentVar);

                    //An assign op doesn't use the var it's defining. So, remove that var from the uses
                    if (isSgAssignOp(binaryOp))
                    {
                        if (currVarUse != uses.end())
                        {
                            uses.erase(currVarUse);
                        }

                        //Also remove the use from the varRef node, because it's not really a use.
                        ssa->getLocalUsesTable()[currentVar].clear();
                    }
                        //All the other ops always use the var they're defining (+=, -=, /=, etc)
                    else
                    {
                        if (currVarUse == uses.end())
                        {
                            uses.push_back(currentVar);
                        }
                    }
                }

                //Set all the uses as being used at this node
                addUsesToNode(binaryOp, uses);

                //Set the current var as being defined here
                //It's possible that the LHS has no variable references. For example,
                //foo() = 3, where foo() returns a reference
                if (currentVar != NULL)
                {
                    addDefForVarAtNode(currentVar, binaryOp);
                }

                return ChildUses(uses, currentVar);
            }
                //Otherwise cover all the non-defining Ops
            default:
            {
                //We want to set all the varRefs as being used here
                std::vector<SgNode*> uses;
                uses.insert(uses.end(), lhs.getUses().begin(), lhs.getUses().end());
                uses.insert(uses.end(), rhs.getUses().begin(), rhs.getUses().end());

                //Set all the uses as being used here.
                addUsesToNode(binaryOp, uses);

                //Propagate the current variable up. The rhs variable is the one that could be potentially defined up the tree
                return ChildUses(uses, rhs.getCurrentVar());
            }
        }
    }
    
    //Catch all unary operations here.
    else if (isSgUnaryOp(node))
    {
        SgUnaryOp* unaryOp = isSgUnaryOp(node);

        //Now handle the uses. All unary operators use everything in their operand
        std::vector<SgNode*> uses;
        if (isSgAddressOfOp(unaryOp) && isSgPointerMemberType(unaryOp->get_type()))
        {
            //SgAddressOfOp is special; it's not always a use of its operand. When creating a reference to a member variable,
            //we create reference without providing a variable instance. For example,
            //          struct foo { int bar; };
            //
            //          void test()
            //          {
            //                  int foo::*v = &foo::bar;  <---- There is no use of foo.bar on this line
            //                  foo b;
            //                  b.*v = 3;
            //          }
            //In this case, there are no uses in the operand. We also want to delete any uses for the children
            vector<SgNode*> successors = SageInterface::querySubTree<SgNode > (unaryOp);

            foreach(SgNode* successor, successors)
            {
                ssa->getLocalUsesTable()[successor].clear();
            }
        }
        else
        {
            //Guard against unary ops that have no children (exception rethrow statement)
            if (attrs.size() > 0)