Пример #1
0
NameQuerySynthesizedAttributeType
NameQuery::queryNameMemberFunctionDeclarationNames (SgNode * astNode)
{

  ROSE_ASSERT (astNode != 0);

  NameQuerySynthesizedAttributeType returnNameList;

  SgMemberFunctionDeclaration *sageMemberFunctionDeclaration =
    isSgMemberFunctionDeclaration (astNode);

  if (sageMemberFunctionDeclaration != NULL)
    {
      string name = sageMemberFunctionDeclaration->get_name ().str ();

#if DEBUG_NAMEQUERY
      printf ("In case: CLASS_DECL_STMT name = %s \n", name.c_str ());
#endif

      returnNameList.push_back (name);
    }


  return returnNameList;

}                               /* End function queryNameMemberFunctionDeclarationNames() */
// Returns true if the function declaration is declared virtual in
// some parent class, regardless of whether it is declared virtual
// in its own class.
bool isDeclaredVirtualWithinAncestor(SgFunctionDeclaration *functionDeclaration)
{
  SgMemberFunctionDeclaration *memberFunctionDeclaration =
    isSgMemberFunctionDeclaration(functionDeclaration);
  if ( memberFunctionDeclaration == NULL )
    return false;

  SgClassDefinition *classDefinition = 
    isSgClassDefinition(memberFunctionDeclaration->get_scope());
  ROSE_ASSERT(classDefinition != NULL);

  return isDeclaredVirtualWithinClassAncestry(functionDeclaration,
					      classDefinition);
}
Пример #3
0
void
CompassAnalyses::ProtectVirtualMethods::Traversal::
visit(SgNode* node)
   { 
     SgMemberFunctionDeclaration *sgmf = isSgMemberFunctionDeclaration(node);

     if( sgmf != NULL )
     {
       SgFunctionModifier sgfm = sgmf->get_functionModifier();
       SgAccessModifier sgam = 
         sgmf->get_declarationModifier().get_accessModifier();

       if( sgfm.isVirtual() == true && sgam.isPublic() == true )
       {
         output->addOutput( new CheckerOutput( node ) );
       } //if( sgfm.isVirtual() == true && sgam.isPublic() == true )
     } //if( sgmf != NULL )

     return;
   } //End of the visit function.
Пример #4
0
  NodeQuerySynthesizedAttributeType
NodeQuery::querySolverFunctionDeclarationFromDefinition (SgNode * astNode,
    SgNode * functionDefinition)
{


  ROSE_ASSERT (astNode != 0);

  NodeQuerySynthesizedAttributeType returnNodeList;

  // SgNode *sageReturnNode = NULL;
  SgMemberFunctionDeclaration *sageMemberFunctionDeclaration =
    isSgMemberFunctionDeclaration (astNode);

  if (sageMemberFunctionDeclaration != NULL)
    if (isSgClassDefinition (sageMemberFunctionDeclaration->get_parent ()))
      if (isSgNode (sageMemberFunctionDeclaration->get_definition ()) ==
          functionDefinition)
        returnNodeList.push_back (astNode);

  return returnNodeList;

}                               /* End function querySolverUnionFields() */
Пример #5
0
Файл: voidStar.C Проект: 8l/rose
void
CompassAnalyses::VoidStar::Traversal::
visit(SgNode* n)
{
  SgMemberFunctionDeclaration *decl = isSgMemberFunctionDeclaration(n);
  if (decl != NULL) {
    if (decl->get_declarationModifier().get_accessModifier().isPublic()) {
      if (isVoidStar(decl->get_type()->get_return_type())) {
        output->addOutput(new CheckerOutput(decl));
        return ;
      }
      const SgTypePtrList& args = decl->get_type()->get_arguments();
      for (SgTypePtrList::const_iterator i = args.begin();
           i != args.end();
           ++i) {
        if (isVoidStar(*i)) {
          output->addOutput(new CheckerOutput(decl));
          return ;
        }
      }
    }
  } //End of the visit function.
}
Пример #6
0
void
CompassAnalyses::VariableNameEqualsDatabaseName::Traversal::
visit(SgNode* node)
   { 
     if( isSgAssignInitializer(node) != NULL )
          assignExp = node;
  
     if( isSgAssignOp(node) != NULL )
          assignExp = node; 

     SgFunctionCallExp* funcCall = isSgFunctionCallExp(node);

  // See if we have a dot expression or arrow expression which
  // accesses the desired member function in the class we are looking for.
     if ( funcCall != NULL  )
        {
          SgExpression* funcExp = funcCall->get_function();

          if ( ( isSgDotExp(funcExp) != NULL ) | ( isSgArrowExp(funcExp) != NULL ) )
             {
               SgBinaryOp*     binOp = isSgBinaryOp(funcExp);
               SgExpression*   rhsOp = binOp->get_rhs_operand();
            // SgExpression*   lhsOp = binOp->get_lhs_operand();
               if ( SgMemberFunctionRefExp* funcRef = isSgMemberFunctionRefExp(rhsOp)  )
                  {
                 // std::cout << "c1\n" ;

                    SgMemberFunctionSymbol*      funcSymbol = funcRef->get_symbol();
                    ROSE_ASSERT(funcSymbol->get_declaration() != NULL);

                 // DQ (1/16/2008): Note that the defining declaration need not exist (see test2001_11.C)
                 // ROSE_ASSERT(funcSymbol->get_declaration()->get_definingDeclaration() != NULL);
                    if (funcSymbol->get_declaration()->get_definingDeclaration() != NULL)
                       {
                         SgMemberFunctionDeclaration* funcDecl   = isSgMemberFunctionDeclaration(funcSymbol->get_declaration()->get_definingDeclaration());
                         ROSE_ASSERT( funcDecl != NULL );

                         SgClassDefinition* clDef = isSgClassDefinition(funcDecl->get_scope());
                         SgClassDeclaration*          clDecl     = isSgClassDeclaration(clDef->get_declaration());  

                      // SgClassDeclaration*          clDecl     = funcDecl->get_associatedClassDeclaration();

                         ROSE_ASSERT( clDecl != NULL );
                         std::string className    = clDecl->get_name().getString();

                         ROSE_ASSERT(funcDecl != NULL);
                         std::string functionName = funcDecl->get_name().getString();
 
                      // If the class is the class we are looking for see if the member function
                      // access is to the member function we are interested in.
                      // std::cout << "className = " << className << std::endl;
                      // std::cout << "functionName = " << functionName << std::endl;

                         if ( (className == classToLookFor) && ( functionName == memberFunctionToLookFor ) )
                            {
                              SgExprListExp*         actualArgs    = funcCall->get_args();
                              SgExpressionPtrList&   actualExpArgs = actualArgs->get_expressions ();

                              ROSE_ASSERT(actualExpArgs.size() == 1);
                              Rose_STL_Container<SgNode*> nodeLst = NodeQuery::querySubTree(*actualExpArgs.begin(), V_SgStringVal);

                              ROSE_ASSERT( nodeLst.size() > 0);
                              SgStringVal* actualArg = isSgStringVal(*nodeLst.begin());
                              ROSE_ASSERT(actualArg != NULL);

                              std::string  stringArg = actualArg->get_value();

                              std::cout << "arg:" << stringArg << std::endl;

                              std::string varName;

                           // SgInitializedName* initName = NULL; 
                              if ( SgAssignInitializer* assignInit =  isSgAssignInitializer(assignExp) )
                                 {
                                   SgInitializedName* initName = isSgInitializedName(assignInit->get_parent());
                                   ROSE_ASSERT(initName != NULL);
                                 
                                   varName = initName->get_name().getString();
                                 }
                                else
                                 {
                                   if ( SgAssignOp* assignOp = isSgAssignOp(assignExp) )
                                      {
                                        SgExpression*     lhsOp  = assignOp->get_lhs_operand();
                                        SgVarRefExp*      varRef = isSgVarRefExp(lhsOp);
                                        ROSE_ASSERT(varRef!=NULL);
                                        SgVariableSymbol* varSymbol = varRef->get_symbol();
                                        ROSE_ASSERT(varSymbol != NULL);
                                        SgInitializedName* initName = varSymbol->get_declaration();
                                        varName = initName->get_name().getString();
                                      }
                                 }
 
                              if (varName != "")
                                 {
                                // we are only interested in the part of the argument after the last ":"
                                // Database scopes in ALE3D are separated by ":"

                                   size_t posCol = stringArg.find_last_of(':');
                                 
                                   if (posCol != std::string::npos)
                                        stringArg = stringArg.substr(posCol+1);

                                 //Find violations to the rule
                                   if ( stringArg != varName)
                                      {
                                        output->addOutput(new CheckerOutput(assignExp));
                                        std::cout << "violation" << varName << std::endl;
                                      }
                                     else 
                                      {
                                        std::cout << "non=violation" << varName << std::endl;
                                      }
                                 }
                            }
                       }
                  }
             } 
        }
   } // End of the visit function.
int
main( int argc, char * argv[] )
   {
  // Initialize and check compatibility. See rose::initialize
     ROSE_INITIALIZE;

  // Build the AST used by ROSE
     SgProject* project = frontend(argc,argv);

  // Build a list of functions within the AST
     Rose_STL_Container<SgNode*> memberFunctionDeclarationList = NodeQuery::querySubTree (project,V_SgMemberFunctionDeclaration);

     int counter = 0;
     for (Rose_STL_Container<SgNode*>::iterator i = memberFunctionDeclarationList.begin(); i != memberFunctionDeclarationList.end(); i++)
        {
       // Build a pointer to the current type so that we can call the get_name() member function.
          SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(*i);
          ROSE_ASSERT(memberFunctionDeclaration != NULL);

          if (memberFunctionDeclaration->get_functionModifier().isVirtual() == true)
             {
               printf ("Virtual Member Function #%2d name is %s at line %d \n",
                    counter++,memberFunctionDeclaration->get_name().str(),
                    memberFunctionDeclaration->get_file_info()->get_line());
             }
            else
             {
               printf ("Non-virtual Member Function #%2d name is %s at line %d \n",
                    counter++,memberFunctionDeclaration->get_name().str(),
                    memberFunctionDeclaration->get_file_info()->get_line());
             }
        }

     Rose_STL_Container<SgNode*> memberFunctionRefExpList = NodeQuery::querySubTree (project,V_SgMemberFunctionRefExp);
     counter = 0;
     for (Rose_STL_Container<SgNode*>::iterator i = memberFunctionRefExpList.begin(); i != memberFunctionRefExpList.end(); i++)
        {
       // Build a pointer to the current type so that we can call the get_name() member function.
          SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(*i);
          ROSE_ASSERT(memberFunctionRefExp != NULL);
          SgFunctionSymbol* functionSymbol = memberFunctionRefExp->get_symbol();
          ROSE_ASSERT(functionSymbol != NULL);
          SgDeclarationStatement* declaration = functionSymbol->get_declaration();
          ROSE_ASSERT(declaration != NULL);
          SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(declaration);
          ROSE_ASSERT(memberFunctionDeclaration != NULL);

          SgMemberFunctionDeclaration* nondefiningMemberFunctionDeclaration = isSgMemberFunctionDeclaration(memberFunctionDeclaration->get_firstNondefiningDeclaration());
          if (nondefiningMemberFunctionDeclaration->get_functionModifier().isVirtual() == true)
             {
               printf ("Virtual function call #%2d name is %s at line %d MemberDeclaration at line = %d \n",
                    counter++,nondefiningMemberFunctionDeclaration->get_name().str(),
                    memberFunctionRefExp->get_file_info()->get_line(),
                    nondefiningMemberFunctionDeclaration->get_file_info()->get_line());
             }
            else
             {
               printf ("Non-virtual function call #%2d name is %s at line %d MemberDeclaration at line = %d \n",
                    counter++,nondefiningMemberFunctionDeclaration->get_name().str(),
                    memberFunctionRefExp->get_file_info()->get_line(),
                    nondefiningMemberFunctionDeclaration->get_file_info()->get_line());
             }
        }

     return 0;
   }
Пример #8
0
//-----------------------------------------------------------------------------
// Functions required by the tree traversal mechanism
ClasshierarchyInhAttr
ClasshierarchyTraversal::evaluateInheritedAttribute (
                SgNode* astNode,
                ClasshierarchyInhAttr inheritedAttribute )
{
        GlobalDatabaseConnection *gdb;    // db connection
        //long funcId;                                                                                  // id of a function declaration
        Classhierarchy *classhier = getClasshierarchy();
        gdb = getDB();  

        switch(astNode->variantT())
        {

                case V_SgMemberFunctionDeclaration: {
                        SgMemberFunctionDeclaration *funcDec = isSgMemberFunctionDeclaration( astNode );
                        //funcDec = funcDef->get_declaration();
                        //if(isSgMemberFunctionDeclaration(funcDec)) {
                                // add to class hierarchy if member function definition
                                //if(isSgMemberFunctionDeclaration()) {
                                //cerr << " adding CHvinf for MembFunc " << endl;
                                SgClassDefinition *classDef = isSgClassDefinition( funcDec->get_scope() );
                                //assert(classDef);
                                if(classDef) {
                                        string classname = classDef->get_qualified_name().str();
                                        // get the classhier. vertex
                                        Classhierarchy::dbgVertex chVert = 0; //?? init necessary
                                        bool foundClass = false;
                                        Classhierarchy::dbgVertexIterator chvi,chvend;
                                        boost::tie(chvi,chvend) = boost::vertices( *getClasshierarchy() );
                                        for(; chvi!=chvend; chvi++) {
                                                if( boost::get( vertex_dbg_data,  *getClasshierarchy() , *chvi).get_typeName() == classname ) {
                                                        chVert = *chvi;
                                                        foundClass = true;
                                                }
                                        }
                                        if(foundClass) {
                                                property_map< Classhierarchy::dbgType, boost::vertex_classhierarchy_t>::type chMap = boost::get( boost::vertex_classhierarchy, *getClasshierarchy() );
                                                chMap[ chVert ].defined.insert( funcDec );
                                                //get type?
                                                //cerr << " added! "; // debug
                                        }
                                }

                        //}
                        cerr << " found V_SgMemberFunctionDeclaration done for " <<funcDec->get_mangled_name().str()<< " " << endl; // debug
                        } break;

                case V_SgClassDefinition: {
                        cerr << " found V_SgClassDef of "; // debug
                        SgClassDefinition *classDef = isSgClassDefinition( astNode );
                        assert( classDef );
                        SgName classname = classDef->get_qualified_name();

                        // make db entry
                        long typeId = UNKNOWNID;
                        typesTableAccess types( gdb );
                        typesRowdata newtype( typeId, getProjectId(), classname.str() );
                        typeId = types.retrieveCreateByColumn( &newtype, "typeName", newtype.get_typeName(), newtype.get_projectId() );
                        cerr << classname.str()<< ", id:" << newtype.get_id() << endl; // debug
                        //classhier->addNode( newtype, newtype.get_typeName() );
                        //classhier->insertWithName( newtype, newtype.get_typeName() );
                        classhier->insertVertex( newtype, newtype.get_typeName() );

                        SgBaseClassList inherits = classDef->get_inheritances();
                        for( SgBaseClassList::iterator i=inherits.begin(); i!=inherits.end(); i++) {
                                SgClassDeclaration *parentDecl = (*i).get_base_class();
                                cerr << " found inheritance from " ; // debug
                                assert( parentDecl );

                                // add new edge
                                typesRowdata partype( UNKNOWNID, getProjectId(), parentDecl->get_name().str() ); // MANGLE
                                long parentId = types.retrieveCreateByColumn( &partype, "typeName", partype.get_typeName(), partype.get_projectId() );
                                cerr << parentDecl->get_name().str() << ", id: " << parentId << endl;

                                // add to class hierarchy graph, allow only one edge per inheritance
                                //A classhier->addNode( partype, partype.get_typeName() );
                                //A classhier->addEdge( newtype, partype, false );
                                classhier->insertEdge( newtype, partype );
                        }
                        
                        } break;

        } // switch node type


        // Note that we have to use a particular constructor (to pass on context information about source code position).
        // This allows the Rewrite mechanism to position new source code relative to the current position using a simple interface.
        ClasshierarchyInhAttr returnAttribute(inheritedAttribute,astNode);
        // FIXME why not return inheritedAttribute???

        return returnAttribute;
}
int main(int argc, char **argv)
{
  SgProject *project = frontend(argc, argv);
  
  // Instantiate a class hierarchy wrapper.
  ClassHierarchyWrapper classHierarchy( project );

#if 0
  std::list<SgNode *> nodes2 = NodeQuery::querySubTree(project,
						      V_SgVariableDefinition);

  for (std::list<SgNode *>::iterator it = nodes2.begin();
       it != nodes2.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgVariableDefinition *varDefn =
      isSgVariableDefinition(n);
    ROSE_ASSERT(varDefn != NULL);

    std::cout << "Var defn: " << varDefn->unparseToCompleteString() << std::endl;

  }

  std::list<SgNode *> nodes1 = NodeQuery::querySubTree(project,
						      V_SgVariableDeclaration);

  for (std::list<SgNode *>::iterator it = nodes1.begin();
       it != nodes1.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgVariableDeclaration *varDecl =
      isSgVariableDeclaration(n);
    ROSE_ASSERT(varDecl != NULL);

    SgInitializedNamePtrList &variables =
      varDecl->get_variables();
    SgInitializedNamePtrList::iterator varIter;
    for (varIter = variables.begin(); 
	 varIter != variables.end(); ++varIter) {
      
      SgNode *var = *varIter;
      ROSE_ASSERT(var != NULL);
      
      SgInitializedName *initName =
	isSgInitializedName(var);
      ROSE_ASSERT(initName != NULL);
      
      if ( isSgClassType(initName->get_type()) ) {

	SgClassType *classType = isSgClassType(initName->get_type());
	ROSE_ASSERT(classType != NULL);

	SgDeclarationStatement *declStmt = classType->get_declaration();
	ROSE_ASSERT(declStmt != NULL);
	
	SgClassDeclaration *classDeclaration = isSgClassDeclaration(declStmt);
	ROSE_ASSERT(classDeclaration != NULL);
      
	//	std::cout << "From var decl got: " << classDeclaration->unparseToCompleteString() << std::endl;

	SgClassDefinition *classDefinition =
	  classDeclaration->get_definition();
	if ( classDefinition != NULL ) {
	  std::cout << "From var decl got: " << classDefinition->unparseToCompleteString() << std::endl;
	}

      }

    }
    

  }

  std::list<SgNode *> nodes = NodeQuery::querySubTree(project,
						      V_SgClassDeclaration);

  for (std::list<SgNode *>::iterator it = nodes.begin();
       it != nodes.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgClassDeclaration *classDeclaration1 =
      isSgClassDeclaration(n);
    ROSE_ASSERT(classDeclaration1 != NULL);

    SgDeclarationStatement *definingDecl =
      classDeclaration1->get_definingDeclaration();
    if ( definingDecl == NULL )
      continue;
    
    SgClassDeclaration *classDeclaration =
      isSgClassDeclaration(definingDecl);
    ROSE_ASSERT(classDeclaration != NULL);


    SgClassDefinition *classDefinition =
      classDeclaration->get_definition();
    ROSE_ASSERT(classDefinition != NULL);

    std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl;

    SgClassDefinitionPtrList subclasses = 
      classHierarchy.getSubclasses(classDefinition);

    // Iterate over all subclasses.
    for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin();
	 subclassIt != subclasses.end(); ++subclassIt) {
      
      SgClassDefinition *subclass = *subclassIt;
      ROSE_ASSERT(subclass != NULL);
      
      std::cout << "subclass" << std::endl;

    }

  }
#endif
#if 1
#if 0
  std::list<SgNode *> nodes = NodeQuery::querySubTree(project,
						      V_SgClassDefinition);

  for (std::list<SgNode *>::iterator it = nodes.begin();
       it != nodes.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgClassDefinition *classDefinition =
      isSgClassDefinition(n);
    ROSE_ASSERT(classDefinition != NULL);

    std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl;

    SgClassDefinitionPtrList subclasses = 
      classHierarchy.getSubclasses(classDefinition);

    // Iterate over all subclasses.
    for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin();
	 subclassIt != subclasses.end(); ++subclassIt) {
      
      SgClassDefinition *subclass = *subclassIt;
      ROSE_ASSERT(subclass != NULL);
      
      std::cout << "subclass" << std::endl;

    }

  }
#else
  // Collect all function/method invocations.
  std::list<SgNode *> nodes = NodeQuery::querySubTree(project,
						      V_SgFunctionCallExp);

  unsigned int numCallSites = 0;
  unsigned int numMonomorphicCallSites = 0;
  unsigned int numPossibleResolutions = 0;

  // Visit each call site.
  for (std::list<SgNode *>::iterator it = nodes.begin();
       it != nodes.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgFunctionCallExp *functionCallExp =
      isSgFunctionCallExp(n);
    ROSE_ASSERT(functionCallExp != NULL);

    // We are only interested in examining method invocations.
    bool isDotExp = false;
    bool isLhsRefOrPtr = false;

    //    std::cout << "method?: " << functionCallExp->unparseToCompleteString() << std::endl;

    if ( !isMethodCall(functionCallExp, isDotExp, isLhsRefOrPtr) )
      continue;
    
    //    std::cout << "method: " << functionCallExp->unparseToCompleteString() << std::endl;

    numCallSites++;

    if ( isDotExp && !isLhsRefOrPtr ) {
      // If this is a dot expression (i.e., a.foo()), we can
      // statically determine its type-- unless the left-hand
      // side is a reference type.
      numMonomorphicCallSites++;
      numPossibleResolutions++;
      //      std::cout << "dot: " << functionCallExp->unparseToCompleteString() << std::endl;
      continue;
    }

    //    std::cout << "methodPtr: " << functionCallExp->unparseToCompleteString() << std::endl;

    // Retrieve the static function declaration.
    SgFunctionDeclaration *functionDeclaration = 
      getFunctionDeclaration(functionCallExp);

    // Ensure it is actually a method declaration.
    SgMemberFunctionDeclaration *memberFunctionDeclaration =
      isSgMemberFunctionDeclaration(functionDeclaration);
    ROSE_ASSERT(memberFunctionDeclaration != NULL);

    unsigned int numResolutionsForMethod = 0;

    // Certainly can be resolved to the static method (unless it
    // is pure virtual).
    if ( !isPureVirtual(memberFunctionDeclaration) ) {
      numResolutionsForMethod++;
    }

#if 0
    if ( ( isVirtual(functionDeclaration) ) ||
	 ( isDeclaredVirtualWithinAncestor(functionDeclaration) ) ) {
#else
      if ( isVirtual(functionDeclaration) ) {
#endif      
      //      std::cout << "tracking: " << functionDeclaration->unparseToString() << std::endl;

      SgClassDefinition *classDefinition = 
	isSgClassDefinition(memberFunctionDeclaration->get_scope());
      ROSE_ASSERT(classDefinition != NULL);
      
      SgClassDefinitionPtrList subclasses = 
	classHierarchy.getSubclasses(classDefinition);

      // Iterate over all subclasses.
      for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin();
	   subclassIt != subclasses.end(); ++subclassIt) {

	SgClassDefinition *subclass = *subclassIt;
	ROSE_ASSERT(subclass != NULL);

	//	std::cout << "subclass" << std::endl;

	// Iterate over all of the methods defined in this subclass.
	SgDeclarationStatementPtrList &decls =
	  subclass->get_members();
	for (SgDeclarationStatementPtrList::iterator declIter = decls.begin();
	     declIter != decls.end(); ++declIter) {

	  SgDeclarationStatement *declStmt = *declIter;
	  ROSE_ASSERT(declStmt != NULL);

	  SgMemberFunctionDeclaration *method =
	    isSgMemberFunctionDeclaration(declStmt);
	  if ( method == NULL ) {
	    continue;
	  }

	  //	  std::cout << "checking overrides" << std::endl;
	  // Determine whether subclass of the class defining this
	  // method overrides the method.
#if 1
	  if ( matchingFunctions(method,
				       memberFunctionDeclaration) ) {
	    //	    std::cout << "overries" << std::endl;
	    // Do not consider a pure virtual method to be an 
	    // overriding method (since it can not be invoked).
	    if ( !isPureVirtual(method) ) {
	      numResolutionsForMethod++;
	    }
	  }
#else
	  if ( methodOverridesVirtualMethod(method, 
					    memberFunctionDeclaration) ) {
	    //	    std::cout << "overries" << std::endl;
	    numResolutionsForMethod++;
	  }
#endif
	}

      }

      if ( numResolutionsForMethod <= 1 )
	numMonomorphicCallSites++;
      numPossibleResolutions += numResolutionsForMethod;

      if ( ( numResolutionsForMethod ) > 1 ) {
	std::cout << "Method invocation has " << numResolutionsForMethod << " possible resolutions " << std::endl;
	std::cout << functionCallExp->unparseToCompleteString() << std::endl;
      }
    }

  }
#endif
#endif
  return 0;
}
bool isDeclaredVirtualWithinClassAncestry(SgFunctionDeclaration *functionDeclaration, SgClassDefinition *classDefinition)
{
  SgType *functionType =
    functionDeclaration->get_type();
  ROSE_ASSERT(functionType != NULL);

  // Look in each of the class' parent classes.
  SgBaseClassPtrList & baseClassList = classDefinition->get_inheritances(); 
  for (SgBaseClassPtrList::iterator i = baseClassList.begin(); 
       i != baseClassList.end(); ++i) {
 
    SgBaseClass *baseClass = *i;
    ROSE_ASSERT(baseClass != NULL);

    SgClassDeclaration *classDeclaration = baseClass->get_base_class(); 
    ROSE_ASSERT(classDeclaration != NULL);

    SgDeclarationStatement *definingDecl =
      classDeclaration->get_definingDeclaration();
    if ( definingDecl == NULL )
      continue;
    
    SgClassDeclaration *definingClassDeclaration =
      isSgClassDeclaration(definingDecl);
    ROSE_ASSERT(classDeclaration != NULL);

    SgClassDefinition *parentClassDefinition =
      definingClassDeclaration->get_definition();

    if ( parentClassDefinition == NULL )
      continue;

    // Visit all methods in the parent class.
    SgDeclarationStatementPtrList &members = 
      parentClassDefinition->get_members(); 

    bool isDeclaredVirtual = false;

    for (SgDeclarationStatementPtrList::iterator it = members.begin(); 
	 it != members.end(); ++it) { 
    
      SgDeclarationStatement *declarationStatement = *it; 
      ROSE_ASSERT(declarationStatement != NULL);
      
      switch(declarationStatement->variantT()) {
      
      case V_SgMemberFunctionDeclaration:
	{
	  SgMemberFunctionDeclaration *memberFunctionDeclaration =  
	    isSgMemberFunctionDeclaration(declarationStatement); 

	  if ( isVirtual(memberFunctionDeclaration) ) {

	    SgType *parentMemberFunctionType =
	      memberFunctionDeclaration->get_type();
	    ROSE_ASSERT(parentMemberFunctionType != NULL);

	    if ( parentMemberFunctionType == functionType ) {
	      return true;
	    }

	  }
	  break;

	}
      default:
	{
	  break;
	}

      }

    }

    if ( isDeclaredVirtualWithinClassAncestry(functionDeclaration, 
					      parentClassDefinition) ) {
      return true;
    }

  }

  return false;
}
Пример #11
0
void
ProcTraversal::visit(SgNode *node) {
    if (isSgFunctionDeclaration(node)) {
        SgFunctionDeclaration *decl = isSgFunctionDeclaration(node);
        if (decl->get_definition() != NULL) {
            /* collect statistics */
            //AstNumberOfNodesStatistics anons;
            //anons.traverse(decl, postorder);
            //original_ast_nodes += anons.get_numberofnodes();
            //original_ast_statements += anons.get_numberofstatements();

            /* do the real work */
            Procedure *proc = new Procedure();
            proc->procnum = procnum++;
            proc->decl = decl;
            proc->funcsym
                = isSgFunctionSymbol(decl->get_symbol_from_symbol_table());
            if (proc->funcsym == NULL)
            {
#if 0
                std::cout
                        << std::endl
                        << "*** NULL function symbol for declaration "
                        << decl->unparseToString()
                        << std::endl
                        << "symbol: "
                        << (void *) decl->get_symbol_from_symbol_table()
                        << (decl->get_symbol_from_symbol_table() != NULL ?
                            decl->get_symbol_from_symbol_table()->class_name()
                            : "")
                        << std::endl
                        << "first nondef decl: "
                        << (void *) decl->get_firstNondefiningDeclaration()
                        << " sym: "
                        << (decl->get_firstNondefiningDeclaration() != NULL ?
                            (void *) decl->get_firstNondefiningDeclaration()
                            ->get_symbol_from_symbol_table()
                            : (void *) NULL)
                        << std::endl;
#endif
                if (decl->get_firstNondefiningDeclaration() != NULL)
                {
                    proc->funcsym = isSgFunctionSymbol(decl
                                                       ->get_firstNondefiningDeclaration()
                                                       ->get_symbol_from_symbol_table());
                }
            }
            assert(proc->funcsym != NULL);
            // GB (2008-05-14): We need two parameter lists: One for the names of the
            // variables inside the function definition, which is
            // decl->get_parameterList(), and one that contains any default arguments
            // the function might have. The default arguments are supposedly
            // associated with the first nondefining declaration.
            proc->params = decl->get_parameterList();
            SgDeclarationStatement *fndstmt = decl->get_firstNondefiningDeclaration();
            SgFunctionDeclaration *fnd = isSgFunctionDeclaration(fndstmt);
            if (fnd != NULL && fnd != decl)
                proc->default_params = fnd->get_parameterList();
            else
                proc->default_params = proc->params;

            SgMemberFunctionDeclaration *mdecl
                = isSgMemberFunctionDeclaration(decl);
            if (mdecl) {
                proc->class_type = isSgClassDefinition(mdecl->get_scope());
                std::string name = proc->class_type->get_mangled_name().str();
                name += "::";
                name += decl->get_name().str();
                std::string mname = proc->class_type->get_mangled_name().str();
                mname += "::";
                mname += decl->get_mangled_name().str();
                proc->memberf_name = name;
                proc->mangled_memberf_name = mname;
                proc->name = decl->get_name().str();
                proc->mangled_name = decl->get_mangled_name().str();
                // GB (2008-05-26): Computing a single this symbol for each
                // procedure. Thus, this symbol can also be compared by pointer
                // equality (as is the case for all other symbols). While we're at it,
                // we also build a VarRefExp for this which can be used everywhere the
                // this pointer occurs.
                proc->this_type = Ir::createPointerType(
                                      proc->class_type->get_declaration()->get_type());
                proc->this_sym = Ir::createVariableSymbol("this", proc->this_type);
                proc->this_exp = Ir::createVarRefExp(proc->this_sym);
            } else {
                proc->name = decl->get_name().str();
                proc->mangled_name = decl->get_mangled_name().str();
                proc->class_type = NULL;
                proc->memberf_name = proc->mangled_memberf_name = "";
                proc->this_type = NULL;
                proc->this_sym = NULL;
                proc->this_exp = NULL;
                // GB (2008-07-01): Better resolution of calls to static functions.
                // This only makes sense for non-member functions.
                SgStorageModifier &sm =
                    (fnd != NULL ? fnd : decl)->get_declarationModifier().get_storageModifier();
                proc->isStatic = sm.isStatic();
                // Note that we query the first nondefining declaration for the
                // static modifier, but we save the file of the *defining*
                // declaration. This is because the first declaration might be in
                // some header file, but for call resolution, the actual source
                // file with the definition is relevant.
                // Trace back to the enclosing file node. The definition might be
                // included in foo.c from bar.c, in which case the Sg_File_Info
                // would refer to bar.c; but for function call resolution, foo.c is
                // the relevant file.
                SgNode *p = decl->get_parent();
                while (p != NULL && !isSgFile(p))
                    p = p->get_parent();
                proc->containingFile = isSgFile(p);
            }
            proc_map.insert(std::make_pair(proc->name, proc));
            mangled_proc_map.insert(std::make_pair(proc->mangled_name, proc));
            std::vector<SgVariableSymbol* >* arglist
                = new std::vector<SgVariableSymbol* >();
            SgVariableSymbol *this_var = NULL, *this_temp_var = NULL;
            if (mdecl
                    || decl->get_parameterList() != NULL
                    && !decl->get_parameterList()->get_args().empty()) {
                proc->arg_block
                    = new BasicBlock(node_id, INNER, proc->procnum);
                if (mdecl) {
                    // GB (2008-05-26): We now compute the this pointer right at the
                    // beginning of building the procedure.
                    // this_var = Ir::createVariableSymbol("this", this_type);
                    this_var = proc->this_sym;
                    // std::string varname
                    //   = std::string("$") + proc->name + "$this";
                    // this_temp_var = Ir::createVariableSymbol(varname, proc->this_type);
                    this_temp_var = global_this_variable_symbol;
                    ParamAssignment* paramAssignment
                        = Ir::createParamAssignment(this_var, this_temp_var);
                    proc->arg_block->statements.push_back(paramAssignment);
                    arglist->push_back(this_var);
                    if (proc->name.find('~') != std::string::npos) {
                        arglist->push_back(this_temp_var);
                    }
                }
                SgInitializedNamePtrList params
                    = proc->params->get_args();
                SgInitializedNamePtrList::const_iterator i;
#if 0
                int parnum = 0;
                for (i = params.begin(); i != params.end(); ++i) {
                    SgVariableSymbol *i_var = Ir::createVariableSymbol(*i);
                    std::stringstream varname;
                    // varname << "$" << proc->name << "$arg_" << parnum++;
                    SgVariableSymbol* var =
                        Ir::createVariableSymbol(varname.str(),(*i)->get_type());
                    proc->arg_block->statements.push_back(Ir::createParamAssignment(i_var, var));
                    arglist->push_back(i_var);
                }
#else
                // GB (2008-06-23): Trying to replace all procedure-specific argument
                // variables by a global list of argument variables. This means that at
                // this point, we do not necessarily need to build a complete list but
                // only add to the CFG's argument list if it is not long enough.
                size_t func_params = params.size();
                size_t global_args = global_argument_variable_symbols.size();
                std::stringstream varname;
                while (global_args < func_params)
                {
                    varname.str("");
                    varname << "$tmpvar$arg_" << global_args++;
                    SgVariableSymbol *var
                        = Ir::createVariableSymbol(varname.str(),
                                                   global_unknown_type);
                    program->global_map[varname.str()]
                        = std::make_pair(var, var->get_declaration());
                    global_argument_variable_symbols.push_back(var);
                }
                // now create the param assignments
                size_t j = 0;
                for (i = params.begin(); i != params.end(); ++i)
                {
                    SgVariableSymbol *i_var = Ir::createVariableSymbol(params[j]);
                    SgVariableSymbol *var = global_argument_variable_symbols[j];
                    j++;
                    proc->arg_block->statements.push_back(
                        Ir::createParamAssignment(i_var, var));
                    arglist->push_back(i_var);
                }
#if 0
                // replace the arglist allocated above by the new one; this must be
                // fixed for this pointers!
                delete arglist;
                arglist = &global_argument_variable_symbols;
#endif
#endif
            } else {
                proc->arg_block = NULL;
            }
            /* If this is a constructor, call default constructors
             * of all base classes. If base class constructors are
             * called manually, these calls will be removed later. */
            if (mdecl
                    && strcmp(mdecl->get_name().str(),
                              proc->class_type->get_declaration()->get_name().str()) == 0
                    && proc->class_type != NULL) {
                SgBaseClassPtrList::iterator base;
                for (base = proc->class_type->get_inheritances().begin();
                        base != proc->class_type->get_inheritances().end();
                        ++base) {
                    SgClassDeclaration* baseclass = (*base)->get_base_class();
                    SgVariableSymbol *lhs
                        = Ir::createVariableSymbol("$tmpvar$" + baseclass->get_name(),
                                                   baseclass->get_type());
                    program->global_map["$tmpvar$" + baseclass->get_name()]
                        = std::make_pair(lhs, lhs->get_declaration());
                    SgMemberFunctionDeclaration* fd=get_default_constructor(baseclass);
                    assert(fd);
                    SgType* basetype=baseclass->get_type();
                    assert(basetype);
                    SgConstructorInitializer *sci
                        = Ir::createConstructorInitializer(fd,basetype);
                    ArgumentAssignment* a
                        = Ir::createArgumentAssignment(lhs, sci);
                    proc->arg_block->statements.push_back(a);

                    // std::string this_called_varname
                    //   = std::string("$") + baseclass->get_name() + "$this";
                    SgVariableSymbol *this_called_var
                    // = Ir::createVariableSymbol(this_called_varname,
                    //                            baseclass->get_type());
                        = global_this_variable_symbol;
                    ReturnAssignment* this_ass
                        = Ir::createReturnAssignment(this_var, this_called_var);
                    proc->arg_block->statements.push_back(this_ass);
                }
            }
            if (mdecl && mdecl->get_CtorInitializerList() != NULL
                    && !mdecl->get_CtorInitializerList()->get_ctors().empty()) {
                SgInitializedNamePtrList cis
                    = mdecl->get_CtorInitializerList()->get_ctors();
                SgInitializedNamePtrList::const_iterator i;
                if (proc->arg_block == NULL) {
                    proc->arg_block = new BasicBlock(node_id, INNER, proc->procnum);
                }
                for (i = cis.begin(); i != cis.end(); ++i) {
                    SgVariableSymbol* lhs = Ir::createVariableSymbol(*i);
                    SgAssignInitializer *ai
                        = isSgAssignInitializer((*i)->get_initializer());
                    SgConstructorInitializer *ci
                        = isSgConstructorInitializer((*i)->get_initializer());
                    /* TODO: other types of initializers */
                    if (ai) {
                        SgClassDeclaration *class_decl
                            = proc->class_type->get_declaration();
                        // GB (2008-05-26): We now compute the this pointer right at the
                        // beginning of building the procedure.
                        // SgVarRefExp* this_ref
                        //   = Ir::createVarRefExp("this",
                        //                         Ir::createPointerType(class_decl->get_type()));
                        SgVarRefExp* this_ref = proc->this_exp;
                        SgArrowExp* arrowExp
                            = Ir::createArrowExp(this_ref,Ir::createVarRefExp(lhs));
                        // GB (2008-03-17): We need to handle function calls in
                        // initializers. In order to be able to build an argument
                        // assignment, we need to know the function's return variable, so
                        // the expression labeler must be called on it. The expression
                        // number is irrelevant, however, as it does not appear in the
                        // return variable.
                        if (isSgFunctionCallExp(ai->get_operand_i())) {
#if 0
                            ExprLabeler el(0 /*expnum*/);
                            el.traverse(ai->get_operand_i(), preorder);
                            // expnum = el.get_expnum();
#endif
                            // GB (2008-06-25): There is now a single global return
                            // variable. This may or may not mean that we can simply ignore
                            // the code above. I don't quite understand why this labeling
                            // couldn't be done later on, and where its result was used.
                        }
                        ArgumentAssignment* argumentAssignment
                            = Ir::createArgumentAssignment(arrowExp,ai->get_operand_i());
                        proc->arg_block->statements.push_back(argumentAssignment);
                    } else if (ci) {
                        /* if this is a call to a base class's
                         * constructor, remove the call we generated
                         * before */
                        SgStatement* this_a = NULL;
                        SgClassDeclaration* cd = ci->get_class_decl();
                        std::deque<SgStatement *>::iterator i;
                        for (i = proc->arg_block->statements.begin();
                                i != proc->arg_block->statements.end();
                                ++i) {
                            ArgumentAssignment* a
                                = dynamic_cast<ArgumentAssignment *>(*i);
                            if (a && isSgConstructorInitializer(a->get_rhs())) {
                                SgConstructorInitializer* c
                                    = isSgConstructorInitializer(a->get_rhs());
                                std::string c_decl_name = c->get_class_decl()->get_name().str();
                                std::string cd_name = cd->get_name().str();
                                // if (c->get_class_decl()->get_name() == cd->get_name()) {
                                if (c_decl_name == cd_name) {
#if 0
                                    // erase the following assignment
                                    // of the this pointer as well
                                    this_a = *proc->arg_block->statements.erase(i+1);
                                    proc->arg_block->statements.erase(i);
#endif
                                    // GB (2008-03-28): That's an interesting piece of code, but
                                    // it might be very mean to iterators. At least it is hard to
                                    // see whether it is correct. So let's try it like this:
                                    // erase i; we get an iterator back, which refers to the next
                                    // element. Save that element as this_a, and then erase.
                                    std::deque<SgStatement *>::iterator this_pos;
                                    this_pos = proc->arg_block->statements.erase(i);
                                    this_a = *this_pos;
                                    proc->arg_block->statements.erase(this_pos);
                                    // Good. Looks like this fixed a very obscure bug.
                                    break;
                                }
                            }
                        }
                        /* now add the initialization */
                        proc->arg_block->statements.push_back(Ir::createArgumentAssignment(lhs, ci));
                        if (this_a != NULL)
                            proc->arg_block->statements.push_back(this_a);
                    }
                }
            }
            proc->entry = new CallBlock(node_id++, START, proc->procnum,
                                        new std::vector<SgVariableSymbol *>(*arglist),
                                        (proc->memberf_name != ""
                                         ? proc->memberf_name
                                         : proc->name));
            proc->exit = new CallBlock(node_id++, END, proc->procnum,
                                       new std::vector<SgVariableSymbol *>(*arglist),
                                       (proc->memberf_name != ""
                                        ? proc->memberf_name
                                        : proc->name));
            proc->entry->partner = proc->exit;
            proc->exit->partner = proc->entry;
            proc->entry->call_target = Ir::createFunctionRefExp(proc->funcsym);
            proc->exit->call_target = Ir::createFunctionRefExp(proc->funcsym);
            /* In constructors, insert an assignment $A$this = this
             * at the end to make sure that the 'this' pointer can be
             * passed back to the calling function uncobbled. */
            proc->this_assignment = NULL;
            if (mdecl) {
                SgMemberFunctionDeclaration* cmdecl
                    = isSgMemberFunctionDeclaration(mdecl->get_firstNondefiningDeclaration());
                // if (cmdecl && cmdecl->get_specialFunctionModifier().isConstructor()) {
                proc->this_assignment
                    = new BasicBlock(node_id++, INNER, proc->procnum);
                ReturnAssignment* returnAssignment
                    = Ir::createReturnAssignment(this_temp_var, this_var);
                proc->this_assignment->statements.push_back(returnAssignment);
                add_link(proc->this_assignment, proc->exit, NORMAL_EDGE);
                // }
            }
            std::stringstream varname;
            // varname << "$" << proc->name << "$return";
            // proc->returnvar = Ir::createVariableSymbol(varname.str(),
            //                                            decl->get_type()->get_return_type());
            proc->returnvar = global_return_variable_symbol;
            procedures->push_back(proc);
            if(getPrintCollectedFunctionNames()) {
                std::cout << (proc->memberf_name != ""
                              ? proc->memberf_name
                              : proc->name)
                          << " " /*<< proc->decl << std::endl*/;
            }
            if (proc->arg_block != NULL)
            {
                proc->arg_block->call_target
                    = Ir::createFunctionRefExp(proc->funcsym);
            }
            // delete arglist;
        }
    }
}