Beispiel #1
0
SgMemberFunctionDeclaration*
get_default_constructor(SgClassDeclaration *c) {
    SgClassDefinition *d = c->get_definition();
    if (d != NULL) {
        SgDeclarationStatementPtrList::iterator i;
        for (i = d->get_members().begin(); i != d->get_members().end(); ++i) {
            if (SgMemberFunctionDeclaration* m=isSgMemberFunctionDeclaration(*i)) {
                if (m->get_name() == c->get_name() && m->get_args().empty())
                    return m;
            }
        }
    }
    return Ir::createMemberFunctionDeclaration(c->get_name());
}
Beispiel #2
0
NameQuerySynthesizedAttributeType
NameQuery::queryNameUnionFieldNames (SgNode * astNode)
{

  ROSE_ASSERT (astNode != 0);

  NameQuerySynthesizedAttributeType returnNameList;

// SgNode *sageReturnNode = NULL;

  SgClassDefinition *sageClassDefinition = isSgClassDefinition (astNode);

  if (sageClassDefinition != NULL)
    {
      ROSE_ASSERT (sageClassDefinition->get_declaration () != NULL);
      if (sageClassDefinition->get_declaration ()->get_class_type () ==
          SgClassDeclaration::e_struct)
        {
          SgDeclarationStatementPtrList declarationStatementPtrList =
            sageClassDefinition->get_members ();

        typedef SgDeclarationStatementPtrList::iterator LI;

        for (LI i = declarationStatementPtrList.begin ();
             i != declarationStatementPtrList.end (); ++i)
          {
            SgNode *listElement = *i;

            SgVariableDeclaration *sageVariableDeclaration =
              isSgVariableDeclaration (listElement);

            if (sageVariableDeclaration != NULL)
              {


                typedef SgInitializedNamePtrList::iterator INITLI;

                SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables ();

                for (INITLI i = sageInitializedNameList.begin ();
                     i != sageInitializedNameList.end (); ++i)
                  {
                    SgInitializedName* initializedListElement = *i;
                    ROSE_ASSERT (isSgInitializedName (initializedListElement) != NULL);

                    returnNameList.push_back (initializedListElement->get_name().str());

                  }             /* End iteration over declarationStatementPtrList */

              }                 /* End iteration over declarationStatementPtrList */
          }

        }
    }

  return returnNameList;

}                               /* End function queryUnionFieldNames() */
Beispiel #3
0
  NodeQuerySynthesizedAttributeType
NodeQuery::querySolverClassFields (SgNode * astNode)
{
  ROSE_ASSERT (astNode != 0);

  NodeQuerySynthesizedAttributeType returnNodeList;

  /*  cout << "The name of the node is: \" " << astNode->sage_class_name() << "\"\n";
      SgLocatedNode* sageLocatedNode = isSgLocatedNode(astNode);
      if(sageLocatedNode != NULL){
      cout << "The filename is: " << sageLocatedNode->getFileName() << " At line number :" << sageLocatedNode->get_file_info()->get_line() << "\n";
      } */
  // SgNode *sageReturnNode = NULL;

  SgClassDefinition *sageClassDefinition = isSgClassDefinition (astNode);

  if (sageClassDefinition != NULL)
  {
    ROSE_ASSERT (sageClassDefinition->get_declaration () != NULL);
    if (sageClassDefinition->get_declaration ()->get_class_type () ==
        SgClassDeclaration::e_class)
    {
      SgDeclarationStatementPtrList declarationStatementPtrList =
        sageClassDefinition->get_members ();

      typedef SgDeclarationStatementPtrList::iterator LI;
      for (LI i = declarationStatementPtrList.begin ();
          i != declarationStatementPtrList.end (); ++i)
      {
        SgNode *listElement = *i;

        if (isSgVariableDeclaration (listElement) != NULL){
          /*    if(isSgVariableDeclaration(listElement)->get_name().str() != NULL)
                cout << "The name of the variable declaration is: \"" << isSgVariableDeclaration(listElement)->get_name().str() << "\"\n";
                else
                cout << "The name of the variable declaration is: \"\"\n";*/
          returnNodeList.push_back (listElement);
        }

      }
    }
  }
  return returnNodeList;
}                               /* End function querySolverClassFields() */
Beispiel #4
0
  NodeQuerySynthesizedAttributeType
NodeQuery::querySolverUnionFields (SgNode * astNode)
{


  ROSE_ASSERT (astNode != 0);

  NodeQuerySynthesizedAttributeType returnNodeList;

  // SgNode *sageReturnNode = NULL;

  SgClassDefinition *sageClassDefinition = isSgClassDefinition (astNode);

  if (sageClassDefinition != NULL)
  {
    ROSE_ASSERT (sageClassDefinition->get_declaration () != NULL);
    if (sageClassDefinition->get_declaration ()->get_class_type () ==
        SgClassDeclaration::e_union)
    {
      SgDeclarationStatementPtrList declarationStatementPtrList =
        sageClassDefinition->get_members ();

      typedef SgDeclarationStatementPtrList::iterator LI;

      for (LI i = declarationStatementPtrList.begin ();
          i != declarationStatementPtrList.end (); ++i)
      {
        SgNode *listElement = *i;

        if (isSgVariableDeclaration (listElement) != NULL)
          returnNodeList.push_back (listElement);

      }

    }
  }


  return returnNodeList;

}                               /* End function querySolverUnionFields() */
Beispiel #5
0
void fixupEdgBugDuplicateVariablesInAST()
   {
  // DQ (3/11/2006): Introduce tracking of performance of ROSE.
     TimingPerformance timer1 ("Fixup known EDG bug where some variable declarations are dropped from the source sequence lists:");

     std::set<SgVariableDeclaration*> declarations_to_remove;

  // Loop over all variables added using the convert_field_use() function.
     std::set<SgVariableDeclaration*>::iterator i = nodesAddedWithinFieldUseSet.begin();
     while (i != nodesAddedWithinFieldUseSet.end())
        {
          SgVariableDeclaration* var_decl = *i;
          SgName name = var_decl->get_variables()[0]->get_name();

          SgClassDefinition* classDefinition = isSgClassDefinition(var_decl->get_parent());
          ROSE_ASSERT(classDefinition != NULL);

          std::vector<SgDeclarationStatement*> & members = classDefinition->get_members();

       // Loop over all data members in the class.
          std::vector<SgDeclarationStatement*>::iterator j = members.begin();
          while (j != members.end())
             {
               SgVariableDeclaration* possible_matching_variable_declaration = isSgVariableDeclaration(*j);
               if (possible_matching_variable_declaration != NULL && possible_matching_variable_declaration != var_decl)
                  {
                    if (possible_matching_variable_declaration->get_variables()[0]->get_name() == name)
                       {
#if 0
                         printf ("matching variable declaration found for name = %s \n",name.str());
#endif
                         declarations_to_remove.insert(var_decl);
                       }
                  }
 
               j++;
             }

          i++;
        }

  // Now remove all of the variable declarations that we detected to be duplicates.
     std::set<SgVariableDeclaration*>::iterator k = declarations_to_remove.begin();
     while (k != declarations_to_remove.end())
        {
          SgDeclarationStatement* var_decl = *k;

          SgClassDefinition* classDefinition = isSgClassDefinition(var_decl->get_parent());
          ROSE_ASSERT(classDefinition != NULL);

          std::vector<SgDeclarationStatement*> myvector;
          myvector.push_back(*k);

          std::vector<SgDeclarationStatement*> & members = classDefinition->get_members();

       // members.erase(*k);
       // members.erase(myvector.begin(),myvector.end());

       // This is the remove/erase idiom.
          members.erase(remove(members.begin(), members.end(), *k), members.end());

          k++;
        }

   }
Beispiel #6
0
StructLayoutInfo NonpackedTypeLayoutGenerator::layoutType(SgType* t) const {
  switch (t->variantT()) {
    case V_SgClassType: { // Also covers structs and unions
      SgClassDeclaration* decl = isSgClassDeclaration(isSgClassType(t)->get_declaration());
      ROSE_ASSERT (decl);
      decl = isSgClassDeclaration(decl->get_definingDeclaration());
      ROSE_ASSERT (decl);
      SgClassDefinition* def = decl->get_definition();
      ROSE_ASSERT (def);
      StructLayoutInfo layout;
      size_t currentOffset = 0;
      const SgBaseClassPtrList& bases = def->get_inheritances();
      for (SgBaseClassPtrList::const_iterator i = bases.begin();
           i != bases.end(); ++i) {
        SgBaseClass* base = *i;
        SgClassDeclaration* basecls = base->get_base_class();
        layoutOneField(basecls->get_type(), base, false, currentOffset, layout);
      }
      const SgDeclarationStatementPtrList& body = def->get_members();
      bool isUnion = (decl->get_class_type() == SgClassDeclaration::e_union);
      for (SgDeclarationStatementPtrList::const_iterator i = body.begin();
           i != body.end(); ++i) {
        SgDeclarationStatement* mem = *i;
        SgVariableDeclaration* vardecl = isSgVariableDeclaration(mem);
        SgClassDeclaration* classdecl = isSgClassDeclaration(mem);
        bool isUnnamedUnion = classdecl ? classdecl->get_isUnNamed() : false;
        if (vardecl) {
          if (!vardecl->get_declarationModifier().isDefault()) continue; // Static fields and friends
          ROSE_ASSERT (!vardecl->get_bitfield());
          const SgInitializedNamePtrList& vars = isSgVariableDeclaration(mem)->get_variables();
          for (SgInitializedNamePtrList::const_iterator j = vars.begin();
               j != vars.end(); ++j) {
            SgInitializedName* var = *j;
            layoutOneField(var->get_type(), var, isUnion, currentOffset, layout);
          }
        } else if (isUnnamedUnion) {
          layoutOneField(classdecl->get_type(), classdecl, isUnion, currentOffset, layout);
        } // else continue;
      }
      if (layout.alignment != 0 && layout.size % layout.alignment != 0) {
        size_t paddingNeeded = layout.alignment - (layout.size % layout.alignment);
        if (!isUnion) {
          layout.fields.push_back(StructLayoutEntry(NULL, layout.size, paddingNeeded));
        }
        layout.size += paddingNeeded;
      }
      return layout;
    }
    case V_SgArrayType: {
      StructLayoutInfo layout = this->beginning->layoutType(isSgArrayType(t)->get_base_type());
      layout.fields.clear();
      SgExpression* numElements = isSgArrayType(t)->get_index();

      //Adjustment for UPC array like a[100*THREADS],treat it as a[100]
      // Liao, 8/7/2008
      if (isUpcArrayWithThreads(isSgArrayType(t)))
      {
        SgMultiplyOp* multiply = isSgMultiplyOp(isSgArrayType(t)->get_index());
        ROSE_ASSERT(multiply);

     // DQ (9/26/2011): Do constant folding if required.
     // SageInterface::constantFolding(multiply);

        numElements = multiply->get_lhs_operand();
      }  
      if (!isSgValueExp(numElements)) {
        cerr << "Error: trying to compute static size of an array with non-constant size" << endl;
        abort();
      }
      layout.size *= SageInterface::getIntegerConstantValue(isSgValueExp(numElements));
      return layout;
    }
    case V_SgTypeComplex: {
    //"Each complex type has the same representation and alignment requirements as 
    //an array type containing exactly two elements of the corresponding real type"
      StructLayoutInfo layout = this->beginning->layoutType(isSgTypeComplex(t)->get_base_type());
      layout.size *= 2;
      return layout;
    }
    case V_SgTypeImaginary: {
      StructLayoutInfo layout = this->beginning->layoutType(isSgTypeImaginary(t)->get_base_type());
      return layout;
    }

    default: return ChainableTypeLayoutGenerator::layoutType(t);
  }
}
void
InsertFortranContainsStatement::visit ( SgNode* node )
   {
  // DQ (10/3/2008): This bug in OFP is now fixed so no fixup is required.
     printf ("Error: fixup of contains statement no longer required. \n");
     ROSE_ASSERT(false);

  // DQ (11/24/2007): Output the current IR node for debugging the traversal of the Fortran AST.
     ROSE_ASSERT(node != NULL);
#if 0
     Sg_File_Info* fileInfo = node->get_file_info();

     printf ("node = %s fileInfo = %p \n",node->class_name().c_str(),fileInfo);
     if (fileInfo != NULL)
        {
          bool isCompilerGenerated = fileInfo->isCompilerGenerated();
          std::string filename = fileInfo->get_filenameString();
          int line_number = fileInfo->get_line();
          int column_number = fileInfo->get_line();

          printf ("--- isCompilerGenerated = %s position = %d:%d filename = %s \n",isCompilerGenerated ? "true" : "false",line_number,column_number,filename.c_str());
        }
#endif

     SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(node);

  // This is for handling where CONTAINS is required in a function
     if (functionDefinition != NULL)
        {
          SgBasicBlock* block = functionDefinition->get_body();
          SgStatementPtrList & statementList = block->get_statements();
          SgStatementPtrList::iterator i = statementList.begin();

          bool firstFunctionDeclaration = false;
          bool functionDeclarationSeen  = false;

          while (i != statementList.end() && firstFunctionDeclaration == false)
             {
               SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);

            // DQ (1/20/2008): Note that entry statements should not cause introduction of a contains statement!
               if (isSgEntryStatement(functionDeclaration) != NULL)
                    functionDeclaration = NULL;

               if (functionDeclaration != NULL)
                  {
                    firstFunctionDeclaration = functionDeclarationSeen == false;
                    functionDeclarationSeen  = true;

                    if (firstFunctionDeclaration == true)
                       {
                      // Insert a CONTAINS statement.
                      // printf ("Building a contains statement (in function) \n");
                         SgContainsStatement* containsStatement = new SgContainsStatement();
                         SageInterface::setSourcePosition(containsStatement);
                         containsStatement->set_definingDeclaration(containsStatement);

                         block->get_statements().insert(i,containsStatement);
                         containsStatement->set_parent(block);
                         ROSE_ASSERT(containsStatement->get_parent() != NULL);
                       }
                  }

               i++;
             }
        }

#if 0
  // OFP now has better support for the CONTAINS statement so this code is not longer required.

  // The use of CONTAINS in modules appears to be handled by OFP, so no fixup is required.
     SgClassDefinition* classDefinition = isSgClassDefinition(node);

  // This is for handling where CONTAINS is required in a module
     if (classDefinition != NULL)
        {
          SgDeclarationStatementPtrList & statementList = classDefinition->get_members();
          SgDeclarationStatementPtrList::iterator i = statementList.begin();

          bool firstFunctionDeclaration = false;
          bool functionDeclarationSeen  = false;

          while (i != statementList.end() && firstFunctionDeclaration == false)
             {
               printf ("InsertFortranContainsStatement: *i in statementList in module = %p = %s \n",*i,(*i)->class_name().c_str());

               SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
               if (functionDeclaration != NULL)
                  {
                    firstFunctionDeclaration = functionDeclarationSeen == false;
                    functionDeclarationSeen  = true;

                    if (firstFunctionDeclaration == true)
                       {
                      // Insert a CONTAINS statement.
                      // printf ("Building a contains statement (in module) \n");
                         SgContainsStatement* containsStatement = new SgContainsStatement();
                         SageInterface::setSourcePosition(containsStatement);
                         containsStatement->set_definingDeclaration(containsStatement);

                      // This insert function does not set the parent (unlike for SgBasicBlock)
                         classDefinition->get_members().insert(i,containsStatement);
                         containsStatement->set_parent(classDefinition);
                         ROSE_ASSERT(containsStatement->get_parent() != NULL);
                       }
                  }

               i++;
             }
        }
#endif
   }
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;
}