void
ProcessTemplateHandlingOptions::visit ( SgNode* node )
   {
  // DQ (8/19/2005): Unmark implicit template instantiations that would be output

  // printf ("node = %s \n",node->sage_class_name());

     switch (node->variantT())
        {
          case V_SgTemplateInstantiationDecl:
             {
               SgTemplateInstantiationDecl* s = isSgTemplateInstantiationDecl(node);
               if (buildImplicitTemplates == false)
                  {
                 // Mark all template class instantiations except specialized template 
                 // instantiations to NOT be output in code generation
                    if (s->get_file_info()->isOutputInCodeGeneration() == true && s->isSpecialization() == false)
                       {
                         printf ("AST Fixup: This template class will not be output within code generation \n");
                         s->get_file_info()->unsetOutputInCodeGeneration();
                       }
                    ROSE_ASSERT (s->get_file_info()->isOutputInCodeGeneration() == false || s->isSpecialization() == true);
                  }
               break;
             }

          case V_SgTemplateInstantiationFunctionDecl:
             {
               SgTemplateInstantiationFunctionDecl* s = isSgTemplateInstantiationFunctionDecl(node);
               if (buildImplicitTemplates == false)
                  {
                 // Mark all template function instantiations except specialized template 
                 // instantiations to NOT be output in code generation
                    if (s->get_file_info()->isOutputInCodeGeneration() == true && s->isSpecialization() == false)
                       {
                         printf ("AST Fixup: This template function will not be output within code generation \n");
                         s->get_file_info()->unsetOutputInCodeGeneration();
                       }
                    ROSE_ASSERT (s->get_file_info()->isOutputInCodeGeneration() == false || s->isSpecialization() == true);
                  }
               break;
             }

          case V_SgTemplateInstantiationMemberFunctionDecl:
             {
               SgTemplateInstantiationMemberFunctionDecl* s = isSgTemplateInstantiationMemberFunctionDecl(node);
               if (buildImplicitTemplates == false && buildImplicitInlineTemplates == false)
                  {
                 // Mark all template member function instantiations except specialized template 
                 // instantiations to NOT be output in code generation
                    if (s->get_file_info()->isOutputInCodeGeneration() == true && s->isSpecialization() == false)
                       {
                         printf ("AST Fixup: This template member function will not be output within code generation \n");
                         s->get_file_info()->unsetOutputInCodeGeneration();
                       }
                    ROSE_ASSERT (s->get_file_info()->isOutputInCodeGeneration() == false || s->isSpecialization() == true);
                  }
               break;
             }

          default:
             {
            // no other cases appear to be a problem!
             }
        }
   }
Ejemplo n.º 2
0
void
fixupInstantiatedTemplates ( SgProject* project )
   {
  // DQ (7/12/2005): Introduce tracking of performance of ROSE.
     TimingPerformance timer ("AST Object Code Generation (fixupInstantiatedTemplates): time (sec) = ");

  // DQ (9/6/2005): I think these operations have been superseded
  // by the AST post processing mechanism which is more complete.
     printf ("In fixupInstantiatedTemplates(): I think this may be dead code! \n");
     ROSE_ASSERT(false);

  // This must be done prior to the unparsing of the SAGE III AST, so that any transformations
  // (new function prototypes for the specialized template function) can be inserted before we 
  // unparse the final code!  Could be done in AST fixup!  Not clear if it should be done in
  // the EDG/SAGE III connection!  It is currently called from the backend() function just 
  // before the unparser!

  // Add forward references for instantiated template functions and member functions 
  // (which are by default defined at the bottom of the file (but should be declared 
  // at the top once we know what instantiations should be built)).  They must be 
  // defined at the bottom since they could call other functions not yet declared in 
  // the file.  Note that this fixup is required since we have skipped the class template 
  // definitions which would contain the declarations that we are generating.  We might 
  // need that as a solution at some point if this fails to be sufficently robust.

  // Build a lists of intatiatied templates
     Rose_STL_Container<SgNode*> classList          = NodeQuery::querySubTree (project,V_SgTemplateInstantiationDecl);
     Rose_STL_Container<SgNode*> functionList       = NodeQuery::querySubTree (project,V_SgTemplateInstantiationFunctionDecl);
     Rose_STL_Container<SgNode*> memberFunctionList = NodeQuery::querySubTree (project,V_SgTemplateInstantiationMemberFunctionDecl);

#if 1
     printf ("In fixupInstantiatedTemplates SgTemplateInstantiationDecl:               classList.size()          = %ld \n",classList.size());
     printf ("In fixupInstantiatedTemplates SgTemplateInstantiationFunctionDecl:       functionList.size()       = %ld \n",functionList.size());
     printf ("In fixupInstantiatedTemplates SgTemplateInstantiationMemberFunctionDecl: memberFunctionList.size() = %ld \n",memberFunctionList.size());
#endif

  // These are not handled yet!
  // ROSE_ASSERT(classList.size()    == 0);
  // ROSE_ASSERT(functionList.size() == 0);

     Rose_STL_Container<SgNode*>::iterator functionIndex = functionList.begin();
     while ( functionIndex != functionList.end() )
        {
       // SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
          SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDeclaration = 
               isSgTemplateInstantiationFunctionDecl(*functionIndex);
          ROSE_ASSERT (templateInstantiationFunctionDeclaration != NULL);

       // printf ("SgTemplateInstantiationFunctionDecl: *i = %p = %s \n",*functionIndex,(*functionIndex)->unparseToString().c_str());

       // Mark this function as a specialization, since we have transformed it into one when we converted the
       // name format (e.g.from  __A45_ to A<int>).  The handling of templates in ROSE is one of converting
       // the templae instantiations (generated by EDG) into explicit template specializations so that they
       // can be operated upon within ROSE (for translation/optimization).
          printf ("Error in fixupInstantiatedTemplates (function templates): It is now an error to mark something that was not explicitly a specialization in the original source code as a specialization ... \n");
          templateInstantiationFunctionDeclaration->set_specialization(SgTemplateInstantiationFunctionDecl::e_specialization);

          bool generateForwardDeclarationForFunction = (templateInstantiationFunctionDeclaration->isForward() == false);

          if ( generateForwardDeclarationForFunction == true )
             {
            // This is just a regular member function inside of a templated class (or a class nested in a templated class)
            // it's associated template declaration will not have the template text (appears to be lost in EDG), but it 
            // is not essential if we unparse the instantated template for the member function.

            // This is the instantiate template member function definition, the steps are:
            //    1) Build a forward declaration for the instantiated template (member function).
            //    2) Place the new forward declaration after the class containing the templated member function.
             }

          functionIndex++;
        }

     Rose_STL_Container<SgNode*>::iterator classIndex = classList.begin();
     while ( classIndex != classList.end() )
        {
          SgTemplateInstantiationDecl* templateInstantiationClassDeclaration = 
               isSgTemplateInstantiationDecl(*classIndex);
          ROSE_ASSERT (templateInstantiationClassDeclaration != NULL);

       // printf ("SgTemplateInstantiationDecl: *i = %p = %s \n",*classIndex,(*classIndex)->unparseToString().c_str());

#if 0
          printf ("In fixupInstantiatedTemplates: templateInstantiationClassDeclaration = %p compilerGenerated = %s \n",
                  templateInstantiationClassDeclaration,
                  templateInstantiationClassDeclaration->get_file_info()->isCompilerGenerated() ? "true" : "false");
          templateInstantiationClassDeclaration->get_file_info()->display("In fixupInstantiatedTemplates: templateInstantiationClassDeclaration");
#endif

       // Mark this class as a specialization, since we have transformed it into one when we converted the
       // name format (e.g.from  __A45_ to A<int>).  The handling of templates in ROSE is one of converting
       // the templae instantiations (generated by EDG) into explicit template specializations so that they
       // can be operated upon within ROSE (for translation/optimization).
          printf ("Error in fixupInstantiatedTemplates (class templates): It is now an error to mark something that was not explicitly a specialization in the original source code as a specialization ... \n");
          templateInstantiationClassDeclaration->set_specialization(SgTemplateInstantiationDecl::e_specialization);

          bool generateForwardDeclarationForClass = (templateInstantiationClassDeclaration->isForward() == false);

          if ( generateForwardDeclarationForClass == true )
             {
            // Nothing to do in this case since EDG should have already instered the forward class declaration!
             }

          classIndex++;
        }

  // Loop over the SgTemplateInstantiationMemberFunction objects and insert a function prototype.
  // We need the function prototypes because the template instatiation function definitions appear 
  // at the end of the file!
     Rose_STL_Container<SgNode*>::iterator i = memberFunctionList.begin();
     while ( i != memberFunctionList.end() )
        {
       // SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
          SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = 
               isSgTemplateInstantiationMemberFunctionDecl(*i);
          ROSE_ASSERT (templateInstantiationMemberFunctionDeclaration != NULL);
#if 0
          printf ("templateInstantiationMemberFunctionDeclaration->isTemplateFunction() == %s \n",
               templateInstantiationMemberFunctionDeclaration->isTemplateFunction() ? "true" : "false");
#endif
       // Mark this function as a specialization, since we have transformed it into one when we converted the
       // name formate (e.g.from  __A45_ to A<int>).  The handling of templates in ROSE is one of converting
       // the templae instantiations (generated by EDG) into explicit template specializations so that they
       // can be operated upon within ROSE (for translation/optimization).
       // If this is not a truely templated function then it can't be a specialization!
       // if it is not a templated function then is is likely just a member function of a templated class.
          if (templateInstantiationMemberFunctionDeclaration->isTemplateFunction() == true)
             {
               printf ("Error in fixupInstantiatedTemplates (member function templates): It is now an error to mark something that was not explicitly a specialization in the original source code as a specialization ... \n");
               templateInstantiationMemberFunctionDeclaration->set_specialization(SgTemplateInstantiationMemberFunctionDecl::e_specialization);
             }
#if 0
       // DQ (9/5/2005): Updated comment.
       // DQ (5/31/2005): Commented out since the class declaration itself is the forward declaration 
       // for the member function. I don't think we need another one!  Actually we do but this is now 
       // handled within ROSE/src/frontend/SageIII/astPostProcessing/ files.

          bool generateForwardDeclarationForInlinedMemberFunction = 
               (templateInstantiationMemberFunctionDeclaration->isForward() == false) &&
               (templateInstantiationMemberFunctionDeclaration->isTemplateFunction() == false);

          if ( generateForwardDeclarationForInlinedMemberFunction == true )
             {
            // This is just a regular member function inside of a templated class (or a class nested in a templated class)
            // it's associated template declaration will not have the templae text (appears to be lost in EDG), but it 
            // is not essential if we unparse the instantated template for the member function.

               printf ("For inlined template member functions get the templateDeclaration from the class declaration \n");

            // This is the instantiate template member function definition, the steps are:
            //    1) Build a forward declaration for the instantiated template (member function).
            //    2) Place the new forward declaration after the class containing the templated member function.

               printf ("SgTemplateInstantiationMemberFunctionDecl: *i = %p = %s \n",*i,(*i)->unparseToString().c_str());

            // Call the AST's copy mechanism
               SgShallowCopy shallow;
               SgNode * forwardDeclarationNode = templateInstantiationMemberFunctionDeclaration->copy(shallow);
               SgTemplateInstantiationMemberFunctionDecl* forwardDeclaration = isSgTemplateInstantiationMemberFunctionDecl(forwardDeclarationNode);
               ROSE_ASSERT(forwardDeclaration != NULL);

            // find the template declaration of the class contining the member function
               SgClassDeclaration* classDeclaration = templateInstantiationMemberFunctionDeclaration->get_class_scope()->get_declaration();
               ROSE_ASSERT(classDeclaration != NULL);
               SgTemplateInstantiationDecl* templateInstantiationDeclaration = isSgTemplateInstantiationDecl(classDeclaration);
               ROSE_ASSERT(templateInstantiationDeclaration != NULL);
               SgTemplateDeclaration* templateDeclaration = templateInstantiationDeclaration->get_templateDeclaration();
               ROSE_ASSERT (templateDeclaration != NULL);

            // Reset the file info object so that we can mark this as compiler generated (copy builds a new Sg_File_Info object)
            // ROSE_ASSERT (forwardDeclaration->get_file_info() != NULL);
            // forwardDeclaration->set_file_info(new Sg_File_Info(*(forwardDeclaration->get_file_info())));
               ROSE_ASSERT(forwardDeclaration->get_file_info() != templateInstantiationMemberFunctionDeclaration->get_file_info());

            // Both of these may be set (implemented as bit flags internally)
               forwardDeclaration->get_file_info()->setCompilerGenerated();
               forwardDeclaration->get_file_info()->setTransformation();

            // Remove the shallow copy of the function definition
               forwardDeclaration->set_definition(NULL);

            // Mark the declaration as a forward declarations
               forwardDeclaration->setForward();

            // Mark this function as a specialization (should be done within copy function)
            // forwardDeclaration->set_specialization(SgTemplateInstantiationMemberFunctionDecl::e_specialization);

               ROSE_ASSERT(forwardDeclaration->isSpecialization() == true);
               ROSE_ASSERT(forwardDeclaration->isPartialSpecialization() == false);

            // Now insert the forwardDeclaration after the templateDeclaration!
            // templateDeclaration.insert_statement(forwardDeclaration,true);
               SgScopeStatement* templateDeclarationScope = templateDeclaration->get_scope();
               ROSE_ASSERT (templateDeclarationScope != NULL);
               printf ("BEFORE loop: Insert before: templateDeclarationScope = %p = %s \n",templateDeclarationScope,templateDeclarationScope->sage_class_name());

            // Trace back through the scopes to find a non class declaration scope into which to put the forward declaration
            // Does this then work with nested template classes?????
               while (isSgTemplateInstantiationDefn(templateDeclarationScope) != NULL)
                  {
                    templateDeclarationScope = templateDeclarationScope->get_scope();
                    printf ("In loop templateDeclarationScope = %p = %s \n",templateDeclarationScope,templateDeclarationScope->sage_class_name());
                  }

               ROSE_ASSERT (templateDeclarationScope != NULL);
               printf ("AFTER loop: Insert before: templateDeclarationScope = %p = %s \n",templateDeclarationScope,templateDeclarationScope->sage_class_name());

               templateDeclaration->get_file_info()->display("templateDeclaration");
               templateDeclarationScope->get_file_info()->display("templateDeclarationScope");

               int insertBeforeStatement = false;
            // printf ("Calling templateDeclarationScope->insert_statement() \n");
            // templateDeclaration->insert_statement ( templateDeclaration, forwardDeclaration, insertBeforeStatement );
               SgTemplateInstantiationDefn *templateClassDefinition = isSgTemplateInstantiationDefn(templateDeclarationScope);
               if (templateClassDefinition != NULL)
                  {
                    SgDeclarationStatementPtrList::iterator start = templateClassDefinition->get_members().begin();
                    SgDeclarationStatementPtrList::iterator end   = templateClassDefinition->get_members().end();

                    printf ("templateDeclaration unparsed = %s \n",templateDeclaration->unparseToString().c_str());
                    printf ("templateDeclaration name = %s string = %s \n",
                         templateDeclaration->get_name().str(),templateDeclaration->get_string().str());

                    for (SgDeclarationStatementPtrList::iterator i = start; i != end; i++)
                       {
                         string s = (*i)->unparseToString();
                         printf ("(*i)->unparseToString() = %s \n",s.c_str());
                       }

                    ROSE_ASSERT(find(start,end,templateInstantiationMemberFunctionDeclaration) != end);
                    templateDeclarationScope->insert_statement ( templateInstantiationMemberFunctionDeclaration, forwardDeclaration, insertBeforeStatement );
                  }
                 else
                  {
                 // ROSE_ASSERT(find(templateDeclarationScope->get_members().begin(),templateDeclarationScope->get_members().end(),templateDeclaration) != templateDeclarationScope->get_members().end() );
                    templateDeclarationScope->insert_statement ( templateDeclaration, forwardDeclaration, insertBeforeStatement );
                  }

               printf ("forwardDeclaration = %s \n",forwardDeclaration->unparseToString().c_str());

            // printf ("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD \n");
            // printf ("Exiting after construction of forward declaration for template instantiation! \n");
            // ROSE_ASSERT (false);
             }
            else
             {
            // This is a forward declaration (does it have the template arguments!)
               printf ("SgTemplateInstantiationMemberFunctionDecl: (forward) *i = %p = %s \n",*i,(*i)->unparseToString().c_str());
             }
#endif
          i++;
        }
   }