void
MangledNameMapTraversal::visit ( SgNode* node)
   {
     ROSE_ASSERT(node != NULL);

#if 0
     printf ("MangledNameMapTraversal::visit: node = %s \n",node->class_name().c_str());
#endif

  // Keep track of the number of IR nodes visited
     numberOfNodes++;

  // DQ (7/4/2010): Optimizations:
  //   1) Only process each IR node once
  //   2) Only process declarations that we want to share (can we be selective?).

  // DQ (7/4/2010): To optimize performance, build a set of previously visited IR nodes
  // so that we only test IR nodes once to add them into the mangled name map. This 
  // should be especially important where the AST is sharing nodes since shared nodes 
  // are visited multiple times (as if they were not shared).
  // We need to tet if this actually optimizes the performance.
     if (setOfNodesPreviouslyVisited.find(node) == setOfNodesPreviouslyVisited.end())
        {
          setOfNodesPreviouslyVisited.insert(node);
        }
       else
        {
          return;
        }

     bool sharable = shareableIRnode(node);

#if 0
     printf ("MangledNameMapTraversal::visit: node = %p = %s sharable = %s \n",node,node->class_name().c_str(),sharable ? "true" : "false");
#endif

  // DQ (7/10/2010): This is a test of the AST merge to investigate robustness.
#if 1

     if (sharable == true)
        {
       // Initially we will only merge things in global scope!  Then
       // we will operate on namespaces! Then I think we are done!
       // Basically we can simplify the problem by skipping merging of things in 
       // function definitions since if the function definitions are the same they 
       // will be merged directly.

       // Keep track of the number of IR nodes that were considered sharable
          numberOfNodesSharable++;

       // Here is where we get much more specific about what is sharable!
          switch (node->variantT())
             {
            // Since we abstract out the generation of the key we can simplify this code!
#if 1
            // DQ (7/11/2010): This fails for tests/nonsmoke/functional/CompileTests/mergeAST_tests/mergeTest_06.C, I don't know why!
               case V_SgFunctionDeclaration:
#endif
#if 1
            // DQ (7/20/2010): Testing this case...
               case V_SgVariableDeclaration:
               case V_SgClassDeclaration:

            // DQ (2/10/2007): These need to be shared (but I still see "xxxxx____Lnnnn" based names)
               case V_SgTemplateInstantiationDecl:

            // DQ (2/10/2007): These should be shared
               case V_SgPragmaDeclaration:
               case V_SgTemplateInstantiationDirectiveStatement:

               case V_SgTypedefDeclaration:
               case V_SgEnumDeclaration:
               case V_SgTemplateDeclaration:
               case V_SgUsingDeclarationStatement:
               case V_SgUsingDirectiveStatement:

            // DQ (2/3/2007): Added additional declarations that we should share
               case V_SgMemberFunctionDeclaration:
               case V_SgTemplateInstantiationFunctionDecl:
               case V_SgTemplateInstantiationMemberFunctionDecl:
#endif
#if 1
            // DQ (2/3/2007): Added support for symbols
               case V_SgClassSymbol:
               case V_SgEnumFieldSymbol:
               case V_SgEnumSymbol:
               case V_SgFunctionSymbol:
               case V_SgMemberFunctionSymbol:
               case V_SgLabelSymbol:
               case V_SgNamespaceSymbol:

            // DQ (2/10/2007): This case has been a problem previously
               case V_SgTemplateSymbol:

               case V_SgTypedefSymbol:
               case V_SgVariableSymbol:

#endif
#if 0
            // DQ (7/20/2010): These nodes are a problem to merge, but also not important to merge 
            // since they are contained within associated declarations.

            // DQ (2/20/2007): Added to list so that it could be process to build the delete list
            // statement fo the SgBasicBlock have to be considerd for the delete list. However,
            // it is still not meaningful since we don't generate a unique name for the SgBasicBlock
            // so it will never be shared.
            // case V_SgBasicBlock:

               case V_SgClassDefinition:
               case V_SgTemplateInstantiationDefn:
               case V_SgFunctionDefinition:
               case V_SgVariableDefinition:
#endif
#if 1
            // DQ (5/29/2006): Added support for types
               case V_SgFunctionType:
               case V_SgMemberFunctionType:
               case V_SgModifierType:
               case V_SgPointerType:

            // DQ (5/29/2006): Added support for types
               case V_SgClassType:
               case V_SgEnumType:
               case V_SgTypedefType:

            // DQ (2/10/2007): Add this case
               case V_SgTemplateArgument:

            // DQ (3/17/2007): These should be shared, I think!
               case V_SgPragma:
            // DQ (5/20/2006): Initialized names are held in SgVariableDeclaration IR
            // nodes or other sharable structures so we don't have to share these.
            // But we have to permit them all to be shared because all pointers to 
            // them need to be reset they all need to be reset.
               case V_SgInitializedName:
#endif
#if 1
                  {
                 // DQ (7/4/2010): To improve the performance avoid regenerating the unique name for the same IR nodes when it is revisited!

                 // Make the use of false in generateUniqueName() more clear.  We need to 
                 // distinguish between defining and non-defining declarations in the generation 
                 // of unique names for the AST merge.
                 // string key = generateUniqueName(node,false);
                    bool ignoreDifferenceBetweenDefiningAndNondefiningDeclarations = false;
                    string key = SageInterface::generateUniqueName(node,ignoreDifferenceBetweenDefiningAndNondefiningDeclarations);
                    ROSE_ASSERT(key.empty() == false);
#if 1
                    SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
                    if (declaration != NULL)
                       {
                      // ROSE_ASSERT(declaration->get_symbol_from_symbol_table() != NULL);

                      // DQ (7/4/2007): Some SgDeclarationStatement IR nodes don't have a representation 
                      // in the symbol table (the list of SgInitializedName object have them instead).
                         if (isSgVariableDeclaration(declaration) == NULL && 
                             isSgVariableDefinition(declaration) == NULL && 
                             isSgUsingDeclarationStatement(declaration) == NULL && 
                             isSgUsingDirectiveStatement(declaration) == NULL && 
                             isSgTemplateInstantiationDirectiveStatement(declaration) == NULL && 
                             isSgPragmaDeclaration(declaration) == NULL)
                            {
                           // DQ (6/8/2010): Only do this test for non compiler generated variable...(e.g. __default_member_function_pointer_name 
                           // is compiler generated to handle function pointers where no member function id specified).
                              if (declaration->get_startOfConstruct()->isCompilerGenerated() == false)
                                 {
                                   SgSymbol* symbol = declaration->search_for_symbol_from_symbol_table();
                                   if (symbol == NULL)
                                      {
                                     // Output more information to support debugging!
                                        printf ("declaration = %p = %s = %s \n",declaration,declaration->class_name().c_str(),SageInterface::get_name(declaration).c_str());
                                        SgScopeStatement* scope = declaration->get_scope();
                                        ROSE_ASSERT(scope != NULL);
                                        printf ("     scope = %p = %s = %s \n",scope,scope->class_name().c_str(),SageInterface::get_name(scope).c_str());
                                        declaration->get_startOfConstruct()->display("declaration->search_for_symbol_from_symbol_table() == NULL");
                                      }
                                   ROSE_ASSERT(symbol != NULL);
                                 }
                            }
#if 0
                      // DQ (6/23/2010): Added the base type of the typedef
                         SgTypedefDeclaration* typedefDeclaration = isSgTypedefDeclaration(declaration);
                         if (typedefDeclaration != NULL)
                            {
                            }
#endif 
                       }
#endif

                    addToMap(key,node);

                 // Keep track of the number of IR nodes that were evaluated for mangled name matching
                    numberOfNodesEvaluated++;
                    break;
                  }
#endif
               default:
                  {
                 // Nothing to do here
                  }
             }
        }
#endif
   }
예제 #2
0
void
FixupAstSymbolTables::visit ( SgNode* node )
   {
  // DQ (6/27/2005): Output the local symbol table from each scope.
  // printf ("node = %s \n",node->sage_class_name());

     SgScopeStatement* scope = isSgScopeStatement(node);
     if (scope != NULL)
        {
#if 0
          printf ("AST Fixup: Fixup Symbol Table for %p = %s at: \n",scope,scope->class_name().c_str());
#endif
          SgSymbolTable* symbolTable = scope->get_symbol_table();
          if (symbolTable == NULL)
             {
#if 0
               printf ("AST Fixup: Fixup Symbol Table for %p = %s at: \n",scope,scope->class_name().c_str());
               scope->get_file_info()->display("Symbol Table Location");
#endif
               SgSymbolTable* tempSymbolTable = new SgSymbolTable();
               ROSE_ASSERT(tempSymbolTable != NULL);

            // name this table as compiler generated! The name is a static member used to store 
            // state for the next_symbol() functions. It is meaningless to set these.
            // tempSymbolTable->set_name("compiler-generated symbol table");

               scope->set_symbol_table(tempSymbolTable);

            // reset the symbolTable using the get_symbol_table() member function
               symbolTable = scope->get_symbol_table();
               ROSE_ASSERT(symbolTable != NULL);

            // DQ (2/16/2006): Set this parent directly (now tested)
               symbolTable->set_parent(scope);
               ROSE_ASSERT(symbolTable->get_parent() != NULL);
             }
          ROSE_ASSERT(symbolTable != NULL);

          if (symbolTable->get_parent() == NULL)
             {
               printf ("Warning: Fixing up symbolTable, calling symbolTable->set_parent() (parent not previously set) \n");
               symbolTable->set_parent(scope);
             }
          ROSE_ASSERT(symbolTable->get_parent() != NULL);

       // Make sure that the internal hash table used in the symbol table is also present!
          if (symbolTable->get_table() == NULL)
             {
            // DQ (6/27/2005): There are a lot of these built, perhaps more than we really need!
#if 0
               printf ("AST Fixup: Building internal Symbol Table hash table (rose_hash_multimap) for %p = %s at: \n",
                    scope,scope->sage_class_name());
               scope->get_file_info()->display("Symbol Table Location");
#endif
               rose_hash_multimap* internalHashTable = new rose_hash_multimap();
               ROSE_ASSERT(internalHashTable != NULL);
               symbolTable->set_table(internalHashTable);
             }
          ROSE_ASSERT(symbolTable->get_table() != NULL);

          SgSymbolTable::BaseHashType* internalTable = symbolTable->get_table();
          ROSE_ASSERT(internalTable != NULL);


       // DQ (6/23/2011): Note: Declarations that reference types that have not been seen yet may be placed into the 
       // wronge scope, then later when we see the correct scope we have a symbol in two or more symbol tables.  The 
       // code below detects and fixes this problem.

       // DQ (6/16/2011): List of symbols we need to remove from symbol tables where they are multibily represented.
          std::vector<SgSymbol*> listOfSymbolsToRemove;

       // DQ (6/12/2011): Fixup symbol table by removing symbols that are not associated with a declaration in the current scope.
          int idx = 0;
          SgSymbolTable::hash_iterator i = internalTable->begin();
          while (i != internalTable->end())
             {
            // DQ: removed SgName casting operator to char*
            // cout << "[" << idx << "] " << (*i).first.str();
               ROSE_ASSERT ( (*i).first.str() != NULL );
               ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL );

            // printf ("Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) sage_class_name() = %s \n",
            //      idx,(*i).first.str(),(*i).second->sage_class_name());

               SgSymbol* symbol = isSgSymbol((*i).second);
               ROSE_ASSERT ( symbol != NULL );

            // We have to look at each type of symbol separately!  This is because there is no virtual function,
            // the reason for this is that each get_declaration() function returns a different type!
            // ROSE_ASSERT ( symbol->get_declaration() != NULL );
               switch(symbol->variantT())
                  {
                    case V_SgClassSymbol:
                       {
                         SgClassSymbol* classSymbol = isSgClassSymbol(symbol);
                         ROSE_ASSERT(classSymbol != NULL);
                         ROSE_ASSERT(classSymbol->get_declaration() != NULL);

                         SgDeclarationStatement* declarationToFindInScope = NULL;

                      // Search for the declaration in the associated scope.
                         declarationToFindInScope = classSymbol->get_declaration();
                         ROSE_ASSERT(declarationToFindInScope != NULL);

                         SgClassDeclaration* classDeclaration = isSgClassDeclaration(declarationToFindInScope);
                         ROSE_ASSERT(classDeclaration != NULL);

                         SgName name = classDeclaration->get_name();

                      // SgType* declarationType = declarationToFindInScope->get_type();
                         SgType* declarationType = classDeclaration->get_type();
                         ROSE_ASSERT(declarationType != NULL);

                         if (declarationToFindInScope->get_definingDeclaration() != NULL)
                            {
                              declarationToFindInScope = declarationToFindInScope->get_definingDeclaration();
                              SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(declarationToFindInScope);
                              ROSE_ASSERT(definingClassDeclaration != NULL);

                           // SgType* definingDeclarationType = declarationToFindInScope->get_type();
                              SgType* definingDeclarationType = definingClassDeclaration->get_type();
                              ROSE_ASSERT(definingDeclarationType != NULL);

                           // DQ (6/22/2011): This assertion fails for CompileTests/copyAST_tests/copytest2007_24.C
                           // A simple rule that all declarations should follow (now that we have proper global type tables).
                           // ROSE_ASSERT(definingDeclarationType == declarationType);
                              if (definingDeclarationType != declarationType)
                                 {
                                   printf ("In fixupSymbolTables.C: Note that definingDeclarationType != declarationType \n");
                                 }
                            }

                         SgNamedType* namedType = isSgNamedType(declarationType);
                         ROSE_ASSERT(namedType != NULL);

                         SgDeclarationStatement* declarationAssociatedToType = namedType->get_declaration();
                         ROSE_ASSERT(declarationAssociatedToType != NULL);
#if 0
                         printf ("Found a symbol without a matching declaration in the current scope (declList): declarationToFindInScope = %p = %s \n",declarationToFindInScope,declarationToFindInScope->class_name().c_str());
                         printf ("Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) class_name() = %s \n",idx,(*i).first.str(),(*i).second->class_name().c_str());
#endif
                         SgScopeStatement* scopeOfDeclarationToFindInScope      = declarationToFindInScope->get_scope();
                         SgScopeStatement* scopeOfDeclarationAssociatedWithType = declarationAssociatedToType->get_scope();
#if 0
                         printf ("declarationToFindInScope = %p declarationToFindInScope->get_scope() = %p = %s \n",declarationToFindInScope,declarationToFindInScope->get_scope(),declarationToFindInScope->get_scope()->class_name().c_str());
                         printf ("declarationAssociatedToType = %p declarationAssociatedToType->get_scope() = %p = %s \n",declarationAssociatedToType,declarationAssociatedToType->get_scope(),declarationAssociatedToType->get_scope()->class_name().c_str());
#endif
                         if (scopeOfDeclarationToFindInScope != scopeOfDeclarationAssociatedWithType)
                            {
                           // DQ (6/12/2011): Houston, we have a problem!  The trick is to fix it...
                           // A symbol has been placed into a scope when we could not be certain which scope it should be placed.
                           // We have a default of placing such symbols into the global scope, but it might be better to just have 
                           // a special scope where such symbols could be placed so that we could have them separate from the global 
                           // scope and then fix them up more clearly.

                           // Note that test2011_80.C still fails but the AST is at least correct (I think).
                              SgGlobal* scopeOfDeclarationToFindInScope_GlobalScope      = isSgGlobal(scopeOfDeclarationToFindInScope);
                           // SgGlobal* scopeOfDeclarationAssociatedWithType_GlobalScope = isSgGlobal(scopeOfDeclarationAssociatedWithType);

                              if (scopeOfDeclarationToFindInScope_GlobalScope != NULL)
                                 {
                                // In general which ever scope is the global scope is where the error is...???
                                // This is because when we don't know where to put a symbol (e.g. from a declaration of a pointer) we put it into global scope.
                                // There is even an agrument that this is correct as a default for C/C++, but only if it must exist (see test2011_80.C).
                                // Remove the symbol from the symbol table of the global scope.

                                   printf ("Remove the associated symbol in the current symbol table \n");

                                // DQ (6/22/2011): This assertion fails for CompileTests/copyAST_tests/copytest2007_24.C
                                // ROSE_ASSERT (declarationToFindInScope->get_scope() == declarationAssociatedToType->get_scope());
                                   if (declarationToFindInScope->get_scope() != declarationAssociatedToType->get_scope())
                                        printf ("In fixupSymbolTables.C: Note that declarationToFindInScope->get_scope() != declarationAssociatedToType->get_scope() \n");
                                 }
                                else
                                 {
                                   listOfSymbolsToRemove.push_back(classSymbol);
                                 }
                            }
                      // ROSE_ASSERT (declarationToFindInScope->get_scope() == declarationAssociatedToType->get_scope());

                         break;
                       }

                    default:
                       {
                      // It night be there are are no other types of symbols to consider...

                      // printf ("Ignoring non SgClassSymbols (fixupSymbolTables.C) symbol = %s \n",symbol->class_name().c_str());
                      // ROSE_ASSERT(false);
                       }
                  }

            // Increment iterator!
               i++;

            // Increment counter!
               idx++;
             }

       // DQ (6/18/2011): Now that we are through with the symbol table we can support removal of any 
       // identified problematic symbol without worrying about STL iterator invalidation.
          for (size_t j = 0; j < listOfSymbolsToRemove.size(); j++)
             {
            // Remove these symbols.
               SgSymbol* removeSymbol = listOfSymbolsToRemove[j];
               ROSE_ASSERT(removeSymbol != NULL);
               SgSymbolTable* associatedSymbolTable = isSgSymbolTable(removeSymbol->get_parent());
               ROSE_ASSERT(associatedSymbolTable != NULL);

               ROSE_ASSERT(associatedSymbolTable == symbolTable);

               associatedSymbolTable->remove(removeSymbol);

               printf ("Redundant symbol removed...from symbol table \n");
            // ROSE_ASSERT(false);
             }
#if 0
       // debugging
          symbolTable->print("In FixupAstSymbolTables::visit(): printing out the symbol tables");
#endif
        }
   }
void fixupAstDeclarationScope( SgNode* node )
   {
  // This function was designed to fixup what I thought were inconsistancies in how the 
  // defining and some non-defining declarations associated with friend declarations had 
  // their scope set.  I now know this this was not a problem, but it is helpful to enforce the
  // consistancy.  It might also be useful to process declarations with scopes set to 
  // namespace definitions, so that the namespace definition can be normalized to be 
  // consistant across all of the different re-entrant namespace definitions.  This is 
  // possible within the new namespace support in ROSE.

     TimingPerformance timer ("Fixup declaration scopes:");

  // This simplifies how the traversal is called!
     FixupAstDeclarationScope astFixupTraversal;

  // DQ (1/29/2007): This traversal now uses the memory pool (so that we will visit declaration hidden in types (e.g. SgClassType)
  // SgClassType::traverseMemoryPoolNodes(v);
     astFixupTraversal.traverseMemoryPool();

  // Now process the map of sets of declarations.
     std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* > & mapOfSets = astFixupTraversal.mapOfSets;

#if 0
     printf ("In fixupAstDeclarationScope(): mapOfSets.size() = %" PRIuPTR " \n",mapOfSets.size());
#endif

     std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* >::iterator i = mapOfSets.begin();
     while (i != mapOfSets.end())
        {
          SgDeclarationStatement* firstNondefiningDeclaration = i->first;

       // DQ (3/2/2015): Added assertion.
          ROSE_ASSERT(firstNondefiningDeclaration != NULL);

       // DQ (3/2/2015): Added assertion.
          ROSE_ASSERT(firstNondefiningDeclaration->get_firstNondefiningDeclaration() != NULL);
 
       // DQ (3/2/2015): Make this assertion a warning: fails in outlining example seq7a_test2006_78.C.
       // ROSE_ASSERT(firstNondefiningDeclaration == firstNondefiningDeclaration->get_firstNondefiningDeclaration());
          if (firstNondefiningDeclaration != firstNondefiningDeclaration->get_firstNondefiningDeclaration())
             {
               printf ("WARNING: In fixupAstDeclarationScope(): firstNondefiningDeclaration != firstNondefiningDeclaration->get_firstNondefiningDeclaration() \n");
               printf ("   --- firstNondefiningDeclaration = %p = %s \n",
                    firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str());
               printf ("   --- firstNondefiningDeclaration->get_firstNondefiningDeclaration() = %p = %s \n",
                    firstNondefiningDeclaration->get_firstNondefiningDeclaration(),firstNondefiningDeclaration->get_firstNondefiningDeclaration()->class_name().c_str());
             }

          SgScopeStatement* correctScope = firstNondefiningDeclaration->get_scope();
          ROSE_ASSERT(correctScope != NULL);

#if 0
          printf ("In FixupAstDeclarationScope::visit(): node = %p = %s firstNondefiningDeclaration = %p correctScope = %p = %s \n",node,node->class_name().c_str(),firstNondefiningDeclaration,correctScope,correctScope->class_name().c_str());
#endif

          std::set<SgDeclarationStatement*>* declarationSet = i->second;
          ROSE_ASSERT(declarationSet != NULL);

#if 0
          printf ("In fixupAstDeclarationScope(): mapOfSets[%p]->size() = %" PRIuPTR " \n",firstNondefiningDeclaration,mapOfSets[firstNondefiningDeclaration]->size());
#endif

          std::set<SgDeclarationStatement*>::iterator j = declarationSet->begin();
          while (j != declarationSet->end())
             {
               SgScopeStatement* associatedScope = (*j)->get_scope();
               ROSE_ASSERT(associatedScope != NULL);

            // DQ (6/11/2013): This is triggered by namespace definition scopes that are different 
            // due to re-entrant namespace declarations.  We should maybe fix this.
            // TV (7/22/13): This is also triggered when for global scope accross files.
               if (associatedScope != correctScope)
                  {
                 // DQ (1/30/2014): Cleaning up some output spew.
                    if (SgProject::get_verbose() > 0)
                       {
                         mprintf ("WARNING: This is the wrong scope (declaration = %p = %s): associatedScope = %p = %s correctScope = %p = %s \n",
                              *j,(*j)->class_name().c_str(),associatedScope,associatedScope->class_name().c_str(),correctScope,correctScope->class_name().c_str());
                       }
#if 0
                    printf ("Make this an error for now! \n");
                    ROSE_ASSERT(false);
#endif
                  }

               j++;
             }

          i++;
        }

#if 0
     printf ("Leaving fixupAstDeclarationScope() node = %p = %s \n",node,node->class_name().c_str());
#endif
   }