Пример #1
0
void
DetectHiddenOriginalExpressionTreeTraversal::visit ( SgNode* node )
   {
  // We only want to search for original expression trees where they can be hidden.

     ROSE_ASSERT(node != NULL);

     SgArrayType* arrayType = isSgArrayType(node);
     if (arrayType != NULL)
        {
#if 0
          printf ("Found an array type arrayType = %p (looking for original expression tree) \n",arrayType);
#endif
          SgExpression* index = arrayType->get_index();
          if (index != NULL)
             {
               DetectOriginalExpressionTreeTraversal t;
               t.traverse(index,preorder);
             }
        }

#if 0
  // DQ (9/18/2011): This code will not work since the bitfile data member in SgVariableDefinition is a SgUnsignedLongVal instead of a SgExpression.
     SgVariableDefinition* variableDefinition = isSgVariableDefinition(node);
     if (variableDefinition != NULL)
        {
#if 0
          printf ("Found a SgVariableDefinition (looking for original expression tree) \n");
#endif
          SgExpression* bitfieldExp = variableDefinition->get_bitfield();
          if (bitfieldExp != NULL)
             {
               DetectOriginalExpressionTreeTraversal t;
               t.traverse(bitfieldExp,preorder);
             }
        }
#endif
   }
Пример #2
0
bool ClangToSageTranslator::VisitFieldDecl(clang::FieldDecl * field_decl, SgNode ** node) {
#if DEBUG_VISIT_DECL
    std::cerr << "ClangToSageTranslator::VisitFieldDecl" << std::endl;
#endif  
    bool res = true;
    
    SgName name(field_decl->getNameAsString());

    SgType * type = buildTypeFromQualifiedType(field_decl->getType());

    clang::Expr * init_expr = field_decl->getInClassInitializer();
    SgNode * tmp_init = Traverse(init_expr);
    SgExpression * expr = isSgExpression(tmp_init);
    // TODO expression list if aggregated initializer !
    if (tmp_init != NULL && expr == NULL) {
        std::cerr << "Runtime error: not a SgInitializer..." << std::endl;
        res = false;
    }
    SgInitializer * init = expr != NULL ? SageBuilder::buildAssignInitializer_nfi(expr, expr->get_type()) : NULL;
    if (init != NULL)
        applySourceRange(init, init_expr->getSourceRange());

  // Cannot use 'SageBuilder::buildVariableDeclaration' because of anonymous field
    // *node = SageBuilder::buildVariableDeclaration(name, type, init, SageBuilder::topScopeStack());
  // Build it by hand...
    SgVariableDeclaration * var_decl = new SgVariableDeclaration(name, type, init);

    if (isSgClassType(type)) {
        std::map<SgClassType *, bool>::iterator bool_it = p_class_type_decl_first_see_in_type.find(isSgClassType(type));
        ROSE_ASSERT(bool_it != p_class_type_decl_first_see_in_type.end());
        if (bool_it->second) {
            var_decl->set_baseTypeDefiningDeclaration(isSgNamedType(type)->get_declaration()->get_definingDeclaration());
            var_decl->set_variableDeclarationContainsBaseTypeDefiningDeclaration(true);
        }
    }
    else if (isSgEnumType(type)) {
        std::map<SgEnumType *, bool>::iterator bool_it = p_enum_type_decl_first_see_in_type.find(isSgEnumType(type));
        ROSE_ASSERT(bool_it != p_enum_type_decl_first_see_in_type.end());
        if (bool_it->second) {
            var_decl->set_baseTypeDefiningDeclaration(isSgEnumType(type)->get_declaration()->get_definingDeclaration());
            var_decl->set_variableDeclarationContainsBaseTypeDefiningDeclaration(true);
        }
    }

    var_decl->set_firstNondefiningDeclaration(var_decl);
    var_decl->set_parent(SageBuilder::topScopeStack());

    ROSE_ASSERT(var_decl->get_variables().size() == 1);

    SgInitializedName * init_name = var_decl->get_variables()[0];
    ROSE_ASSERT(init_name != NULL);
    init_name->set_scope(SageBuilder::topScopeStack());

    applySourceRange(init_name, field_decl->getSourceRange());

    SgVariableDefinition * var_def = isSgVariableDefinition(init_name->get_declptr());
    ROSE_ASSERT(var_def != NULL);
    applySourceRange(var_def, field_decl->getSourceRange());

    SgVariableSymbol * var_symbol = new SgVariableSymbol(init_name);
    SageBuilder::topScopeStack()->insert_symbol(name, var_symbol);

    *node = var_decl;

    return VisitDeclaratorDecl(field_decl, node) && res; 
}
Пример #3
0
bool ClangToSageTranslator::VisitVarDecl(clang::VarDecl * var_decl, SgNode ** node) {
#if DEBUG_VISIT_DECL
    std::cerr << "ClangToSageTranslator::VisitVarDecl" << std::endl;
#endif
    bool res = true;

  // Create the SAGE node: SgVariableDeclaration

    SgName name(var_decl->getNameAsString());

    SgType * type = buildTypeFromQualifiedType(var_decl->getType());

    clang::Expr * init_expr = var_decl->getInit();
    SgNode * tmp_init = Traverse(init_expr);
    SgExpression * expr = isSgExpression(tmp_init);
    if (tmp_init != NULL && expr == NULL) {
        std::cerr << "Runtime error: not a SgInitializer..." << std::endl; // TODO
        res = false;
    }
    SgExprListExp * expr_list_expr = isSgExprListExp(expr);

    SgInitializer * init = NULL;
    if (expr_list_expr != NULL)
        init = SageBuilder::buildAggregateInitializer(expr_list_expr, type);
    else if (expr != NULL)
        init = SageBuilder::buildAssignInitializer_nfi(expr, expr->get_type());
    if (init != NULL)
        applySourceRange(init, init_expr->getSourceRange());

    SgVariableDeclaration * sg_var_decl = new SgVariableDeclaration(name, type, init); // scope: obtain from the scope stack.

    if (isSgClassType(type)) {
        std::map<SgClassType *, bool>::iterator bool_it = p_class_type_decl_first_see_in_type.find(isSgClassType(type));
        ROSE_ASSERT(bool_it != p_class_type_decl_first_see_in_type.end());
        if (bool_it->second) {
            sg_var_decl->set_baseTypeDefiningDeclaration(isSgNamedType(type)->get_declaration()->get_definingDeclaration());
            sg_var_decl->set_variableDeclarationContainsBaseTypeDefiningDeclaration(true);
        }
    }
    else if (isSgEnumType(type)) {
        std::map<SgEnumType *, bool>::iterator bool_it = p_enum_type_decl_first_see_in_type.find(isSgEnumType(type));
        ROSE_ASSERT(bool_it != p_enum_type_decl_first_see_in_type.end());
        if (bool_it->second) {
            sg_var_decl->set_baseTypeDefiningDeclaration(isSgEnumType(type)->get_declaration()->get_definingDeclaration());
            sg_var_decl->set_variableDeclarationContainsBaseTypeDefiningDeclaration(true);
        }
    }

    sg_var_decl->set_firstNondefiningDeclaration(sg_var_decl);
    sg_var_decl->set_parent(SageBuilder::topScopeStack());

    ROSE_ASSERT(sg_var_decl->get_variables().size() == 1);

    SgInitializedName * init_name = sg_var_decl->get_variables()[0];
    ROSE_ASSERT(init_name != NULL);
    init_name->set_scope(SageBuilder::topScopeStack());

    applySourceRange(init_name, var_decl->getSourceRange());

    SgVariableDefinition * var_def = isSgVariableDefinition(init_name->get_declptr());
    ROSE_ASSERT(var_def != NULL);
    applySourceRange(var_def, var_decl->getSourceRange());

    SgVariableSymbol * var_symbol = new SgVariableSymbol(init_name);
    SageBuilder::topScopeStack()->insert_symbol(name, var_symbol);

    *node = sg_var_decl;

    return VisitDeclaratorDecl(var_decl, node) && res;
}
Пример #4
0
void
VerifyOriginalExpressionTreesSetToNull::visit ( SgNode* node )
   {
  // This traversal is used to verify that all of the original expression trees in the AST have
  // been either deleted (optional) or used to replace the constant folded values (the default
  // for the ROSE AST so that we can preserve the greatest amount of source-to-source detail).

  // Note that it can detect problems that are due to orphaned expressions in the AST.
  // An example is test2011_138.C where the multidimensional array indexing causes and orphaned 
  // expression to be created and it has a original expression tree.  Since the orphaned expression 
  // can't be reached we can eliminate the original expression tree.  The bug in ROSE is that there
  // is an orphaned expression tree not that there is a remaining original expression tree.

  // We need a mechanism to detect nodes that exist in the AST and are not pointed to by any other 
  // IR node (and then we have to decide if parent pointers count).

     ROSE_ASSERT(node != NULL);

  // printf ("In VerifyOriginalExpressionTreesSetToNull::visit(): node = %s \n",node->class_name().c_str());

     SgExpression* exp = isSgExpression(node);
     if (exp != NULL)
        {
          SgExpression* originalExpressionTree = exp->get_originalExpressionTree();

          if (originalExpressionTree != NULL)
             {
#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
               printf ("Error: there is a valid originalExpressionTree = %p = %s on node = %p = %s \n",originalExpressionTree,originalExpressionTree->class_name().c_str(),exp,exp->class_name().c_str());
#endif
             }
#if 0 // Liao debugging 11/13/2012
          ROSE_ASSERT(originalExpressionTree == NULL);
#endif

       // Allow us to ignore the cases of originalExpressionTrees hidden in array types.
       // I want to narrow down the failing tests codes to eliminate this case which is handled separately.

          if (originalExpressionTree != NULL)
             {
#if 0
               SgNode* parent = exp;

            // Note that test2011_121.C fails to be either a SgArrayType or a SgVariableDefinition (failing in some part of "complex" header file).
            // test2005_203.C demonstrates the use of constant folding in bitfield specifications.
            // while (parent != NULL && isSgArrayType(parent) == NULL) 
               while (parent != NULL && isSgArrayType(parent) == NULL && isSgVariableDefinition(parent) == NULL) 
                  {
                    parent = parent->get_parent();
                  }

               if (isSgArrayType(parent) == NULL)
                  {
                    printf ("So what is the parent: parent = %p = %s \n",parent, (parent != NULL) ? parent->class_name().c_str() : "NULL");
                  }
               ROSE_ASSERT(isSgArrayType(parent) != NULL || isSgVariableDefinition(parent) != NULL);
#else
#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
               printf ("In VerifyOriginalExpressionTreesSetToNull(): originalExpressionTree = %p = %s on node = %p = %s Ingoring originalExpressionTree != NULL \n",
                    originalExpressionTree,originalExpressionTree->class_name().c_str(),exp,exp->class_name().c_str());
#endif
#endif
             }
        }
   }
Пример #5
0
void
RemoveConstantFoldedValueViaParent::visit ( SgNode* node )
   {
  // This is an alternative implementation that allows us to handle expression that are not 
  // traversed in the AST (e.g. types like SgArrayType which can contain expressions).

     ROSE_ASSERT(node != NULL);

  // DQ (3/11/2006): Set NULL pointers where we would like to have none.
#if 0
     printf ("In RemoveConstantFoldedValueViaParent::visit(): node = %p = %s \n",node,node->class_name().c_str());
#endif

  // DQ (10/12/2012): Turn this on so that we can detect failing IR nodes (failing later) that have valid originalExpressionTrees.
  // DQ (10/12/2012): Turn this back off because it appears to fail...
#if 0
     SgExpression* exp = isSgExpression(node);
     if (exp != NULL)
        {
          SgExpression* originalExpressionTree = exp->get_originalExpressionTree();
          if (originalExpressionTree != NULL)
             {
               SgNode* parent = exp->get_parent();
               if (parent != NULL)
                  {
                    printf ("Current IR node with SgExpression parent = %p = %s child = %p = %s originalExpressionTree = %p = %s \n",parent,parent->class_name().c_str(),node,node->class_name().c_str(),originalExpressionTree,originalExpressionTree->class_name().c_str());
                    bool traceReplacement = true;
                    ConstantFoldedValueReplacer r(traceReplacement, exp);
                    parent->processDataMemberReferenceToPointers(&r);
                 // node->processDataMemberReferenceToPointers(&r);
                  }

            // Set the originalExpressionTree to NULL.
               exp->set_originalExpressionTree(NULL);

            // Set the parent of originalExpressionTree to be the parent of exp.
               originalExpressionTree->set_parent(parent);

            // And then delete the folded constant.
               SageInterface::deleteAST(exp);
             }
        }
#endif

     SgArrayType* arrayType = isSgArrayType(node);
     if (arrayType != NULL)
        {
#if 0
          printf ("Found an array type arrayType = %p arrayType->get_index() = %p \n",arrayType,arrayType->get_index());
#endif
          SgExpression* index = arrayType->get_index();
          if (index != NULL)
             {
#if 0
               printf ("Fixup array index = %p = %s (traverse index AST subtree) \n",index,index->class_name().c_str());
#endif
               RemoveConstantFoldedValue astFixupTraversal;
               astFixupTraversal.traverse(index);
#if 0
               printf ("DONE: Fixup array index = %p (traverse index AST) \n\n\n\n",index);
#endif
#if 0
               printf ("Found an array index = %p (fixup index directly) \n",index);
#endif
            // Handle the case where the original expression tree is at the root of the subtree.
               SgExpression* originalExpressionTree = index->get_originalExpressionTree();
               if (originalExpressionTree != NULL)
                  {
#if 0
                    printf ("Found an originalExpressionTree in the array index originalExpressionTree = %p \n",originalExpressionTree);
#endif
                 // DQ (6/12/2013): This appears to be a problem in EDG 4.7 (see test2011_117.C).
                    std::vector<SgExpression*> redundantChainOfOriginalExpressionTrees;
                    if (originalExpressionTree->get_originalExpressionTree() != NULL)
                       {
#if 0
                         printf ("Detected originalExpressionTree nested directly within the originalExpressionTree \n",
                              originalExpressionTree,originalExpressionTree->class_name().c_str(),
                              originalExpressionTree->get_originalExpressionTree(),originalExpressionTree->get_originalExpressionTree()->class_name().c_str());
#endif
                      // Loop to the end of the chain of original expressions (which EDG 4.7 should never have constructed).
                         while (originalExpressionTree->get_originalExpressionTree() != NULL)
                            {
#if 0
                              printf ("Looping through a chain of originalExpressionTrees \n");
#endif
                           // Save the list of redundnat nodes so that we can delete them properly.
                              redundantChainOfOriginalExpressionTrees.push_back(originalExpressionTree);

                              originalExpressionTree = originalExpressionTree->get_originalExpressionTree();
                            }
#if 0
                         printf ("Exiting as a test! \n");
                         ROSE_ASSERT(false);
#endif
                       }

                    arrayType->set_index(originalExpressionTree);
                    originalExpressionTree->set_parent(arrayType);

                    index->set_originalExpressionTree(NULL);

                 // printf ("DEBUGING: skip delete of index in array type \n");
                    delete index;

                 // DQ (6/12/2013): Delete the nodes that we had to skip over (caused by chain of redundant entries from EDG 4.7).
                    std::vector<SgExpression*>::iterator i = redundantChainOfOriginalExpressionTrees.begin();
                    while (i != redundantChainOfOriginalExpressionTrees.end())
                       {
#if 0
                         printf ("deleting the redundnat originalExpressionTree chain caused by EDG 4.7 (delete %p = %s) \n",*i,(*i)->class_name().c_str());
#endif
                         delete *i;
                         i++;
                       }

                    index = NULL;
                  }
             }
        }

     SgVariableDefinition* variableDefinition = isSgVariableDefinition(node);
     if (variableDefinition != NULL)
        {
#if 0
          printf ("Found a SgVariableDefinition \n");
#endif
          SgExpression* bitfieldExp = variableDefinition->get_bitfield();
          if (bitfieldExp != NULL)
             {
#if 0
               printf ("Fixup bitfieldExp = %p (traverse bitfieldExp AST subtree) \n",bitfieldExp);
#endif
               RemoveConstantFoldedValue astFixupTraversal;
               astFixupTraversal.traverse(bitfieldExp);

            // Handle the case where the original expression tree is at the root of the subtree.
               SgExpression* originalExpressionTree = bitfieldExp->get_originalExpressionTree();
               if (originalExpressionTree != NULL)
                  {
#if 0
                 // DQ (9/18/2011): This code will not work since the bitfile data member in SgVariableDefinition is a SgUnsignedLongVal instead of a SgExpression.
                    variableDefinition->set_bitfield(originalExpressionTree);
                    originalExpressionTree->set_parent(variableDefinition);

                    bitfieldExp->set_originalExpressionTree(NULL);
                    delete bitfieldExp;
                    bitfieldExp = NULL;
#else
                 // The ROSE AST needs to be fixed to handle more general expressions for bitfield widths (this does not effect the CFG).
                 // TODO: Change the data type of the bitfield data member in SgVariableDefinition.

                 // DQ (1/20/2014): This has been done now.
                 // printf ("Member data bitfield widths need to be changed (in the ROSE IR) to support more general expressions (can't fix this original expression tree) \n");
#endif
#if 0
                 // This case is not handled yet!
                    printf ("Found an original expression tree in a bitfield expression \n");
                    ROSE_ASSERT(false);
#endif
                  }
             }
        }
   }
int main(int argc, char **argv)
{
  SgProject *project = frontend(argc, argv);
  
  // Instantiate a class hierarchy wrapper.
  ClassHierarchyWrapper classHierarchy( project );

  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;

    }

  }
#if 0
#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;
    if ( !isMethodCall(functionCallExp, isDotExp) )
      continue;
    
    numCallSites++;
    // Certainly can be resolved to the static method.
    numPossibleResolutions++;

    if ( isDotExp ) {
      // If this is a dot expression (i.e., a.foo()), we can
      // statically determine its type.
      numMonomorphicCallSites++;
      continue;
    }

    // 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 numOverridesForMethod = 0;

    if ( ( isVirtual(functionDeclaration) ) ||
	 ( isDeclaredVirtualWithinAncestor(functionDeclaration) ) ) {
      
      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;
	  }

	  // Determine whether subclass of the class defining this
	  // method overrides the method.
	  if ( methodOverridesVirtualMethod(method, 
					    memberFunctionDeclaration) ) {
	    numOverridesForMethod++;
	  }

	}

      }

      if ( numOverridesForMethod == 0 )
	numMonomorphicCallSites++;
      numPossibleResolutions += numOverridesForMethod;

      std::cout << "Method invocation has " << numOverridesForMethod + 1 << " possible resolutions " << std::endl;
      std::cout << functionCallExp->unparseToCompleteString() << std::endl;

    }

  }
#endif
#endif
  return 0;
}