// DQ (10/6/2007): Added fixup function to set scopes not set properly by the ROSETTA generated copy! void SgFunctionParameterList::fixupCopy_symbols(SgNode* copy, SgCopyHelp & help) const { #if DEBUG_FIXUP_COPY printf ("Inside of SgFunctionParameterList::fixupCopy_symbols() for %p = %s copy = %p \n",this,this->class_name().c_str(),copy); #endif // Also call the base class version of the fixupCopycopy() member function SgDeclarationStatement::fixupCopy_symbols(copy,help); SgFunctionParameterList* copyFunctionParameterList = isSgFunctionParameterList(copy); ROSE_ASSERT(copyFunctionParameterList != NULL); const SgInitializedNamePtrList & parameterList_original = this->get_args(); SgInitializedNamePtrList & parameterList_copy = copyFunctionParameterList->get_args(); SgInitializedNamePtrList::const_iterator i_original = parameterList_original.begin(); SgInitializedNamePtrList::iterator i_copy = parameterList_copy.begin(); // Iterate over both lists to match up the correct pairs of SgInitializedName objects while ( (i_original != parameterList_original.end()) && (i_copy != parameterList_copy.end()) ) { (*i_original)->fixupCopy_symbols(*i_copy,help); i_original++; i_copy++; } }
SgFunctionParameterList * SageUtils::buildEmptyParameterList() { SgFunctionParameterList *parameterList = new SgFunctionParameterList(); ROSE_ASSERT (parameterList); parameterList->set_definingDeclaration (NULL); parameterList->set_firstNondefiningDeclaration(parameterList); SageInterface::setOneSourcePositionForTransformation(parameterList); return parameterList; }
void PreAndPostOrderTraversal::preOrderVisit(SgNode* n) { SgFunctionDeclaration * dec = isSgFunctionDeclaration(n); if (dec != NULL) { cout << "Found function declaration " << dec->get_name().getString(); Sg_File_Info * start = dec->get_startOfConstruct(); Sg_File_Info * end = dec->get_endOfConstruct(); if(start->isCompilerGenerated()) { cout << ", which is compiler-generated" << endl; } else { cout << " in file " << start->get_raw_filename() << ", " << start->get_file_id() << " from line " << start->get_line() << ", col " << start->get_col() << " to line " << end->get_line() << ", col " << end->get_col() << endl; } SgFunctionType * type = dec->get_type(); SgType * retType = type->get_return_type(); cout << "Return type: " << retType->unparseToString() << endl; SgFunctionParameterList * params = dec->get_parameterList(); SgInitializedNamePtrList & ptrList = params->get_args(); if(!ptrList.empty()) { cout << "Parameter types: "; for(SgInitializedNamePtrList::iterator j = ptrList.begin(); j != ptrList.end(); j++) { SgType * pType = (*j)->get_type(); cout << pType->unparseToString() << " "; } cout << endl; } cout << "Linkage: " << dec->get_linkage() << endl; cout << endl; } SgFunctionDefinition * def = isSgFunctionDefinition(n); if (def != NULL) { cout << "Found function definition " << def->get_declaration()->get_name().getString(); Sg_File_Info * start = def->get_startOfConstruct(); Sg_File_Info * end = def->get_endOfConstruct(); if(start->isCompilerGenerated()) { cout << ", which is compiler-generated" << endl; } else { cout << " in file " << start->get_raw_filename() << " from line " << start->get_line() << ", col " << start->get_col() << " to line " << end->get_line() << ", col " << end->get_col() << endl; SgBasicBlock * body = def->get_body(); Sg_File_Info * bodyStart = body->get_startOfConstruct(); Sg_File_Info * bodyEnd = body->get_endOfConstruct(); cout << "Function body from line " << bodyStart->get_line() << ", col " << bodyStart->get_col() << " to line " << bodyEnd->get_line() << ", col " << bodyEnd->get_col() << endl; } cout << endl; } }
SgFunctionParameterList * Kernel<Annotation, Runtime>::createParameterList() const { const std::list<SgVariableSymbol *> & params = getArguments().parameters; const std::list<SgVariableSymbol *> & scalars = getArguments().scalars; const std::list<Data<DLX::KLT::Annotation<DLX::TileK::language_t> > *> & datas = getArguments().datas; std::list<SgVariableSymbol *>::const_iterator it_var_sym; std::list<Data<DLX::KLT::Annotation<DLX::TileK::language_t> > *>::const_iterator it_data; SgFunctionParameterList * result = SageBuilder::buildFunctionParameterList(); result->append_arg(SageBuilder::buildInitializedName("param", SageBuilder::buildPointerType(SageBuilder::buildIntType()), NULL)); result->append_arg(SageBuilder::buildInitializedName("data", SageBuilder::buildPointerType(SageBuilder::buildPointerType(SageBuilder::buildVoidType())), NULL)); result->append_arg(SageBuilder::buildInitializedName("scalar", SageBuilder::buildPointerType(SageBuilder::buildPointerType(SageBuilder::buildVoidType())), NULL)); result->append_arg(Runtime::kernel_api.createContext()); return result; }
/** * Processes parameters passed to a function * @param functionDeclaration */ void AOSModule::processParameters(SgFunctionDeclaration *functionDeclaration) { PrintUtil::printFunctionStart("AOSModule::processParameters"); SgBasicBlock *functionBody = functionDeclaration->get_definition()->get_body(); ROSE_ASSERT(functionBody); SgFunctionParameterList *parameters = functionDeclaration->get_parameterList(); ROSE_ASSERT (parameters); SgInitializedNamePtrList & parameterList = parameters->get_args(); foreach(SgInitializedName * initializedName, parameterList) { SgType *paramType = initializedName->get_type(); string type = TransformationSupport::getTypeName(paramType); trace << " Function Parameter :" << initializedName->get_name() << " Type: " << type << endl; Field *metaField = meta->getField(initializedName->get_name().str()); if (metaField == NULL) continue; trace << " Meta Field found " << endl; if(!checkExtendedVariable(initializedName)) continue; // Set the appropriate type as there may be // parameters with const keyword which causes exception // in creating structs at runtime initializedName->set_type(buildParameterType(metaField)); // if struct exist continue if (!isBuildStruct(metaField)) continue; // Build a structure at the start for function buildStructAtStart(metaField, functionBody); }
void FortranCUDAUserSubroutine::createStatements () { using namespace SageInterface; using boost::iequals; using std::string; using std::vector; class TreeVisitor: public AstSimpleProcessing { private: /* * ====================================================== * The recursive visit of a user subroutine populates * this vector with successive function calls which are * then appended after the visit * ====================================================== */ vector < SgProcedureHeaderStatement * > calledRoutines; public: vector < SgProcedureHeaderStatement * > getCalledRoutinesInStatement() { return calledRoutines; } TreeVisitor () { } virtual void visit (SgNode * node) { SgExprStatement * isExprStatement = isSgExprStatement ( node ); if ( isExprStatement != NULL ) { SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() ); if ( functionCallExp != NULL ) { string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call in user subroutine " + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * As we are in fortran, all user subroutines must be * SgProcedureHeaderStatements = subroutines and not * functions. This might be extended to cover also * functions in the future (?). Probably not in OP2 * ====================================================== */ SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( functionCallExp->getAssociatedFunctionDeclaration() ); calledRoutines.push_back ( isProcedureHeaderStatement ); } } } }; Debug::getInstance ()->debugMessage ("User subroutine: outputting and modifying statements", Debug::FUNCTION_LEVEL, __FILE__, __LINE__); SgFunctionParameterList * originalParameters = originalSubroutine->get_parameterList (); vector <SgStatement *> originalStatements = originalSubroutine->get_definition ()->get_body ()->get_statements (); for (vector <SgStatement *>::iterator it = originalStatements.begin (); it != originalStatements.end (); ++it) { SgExprStatement * isExprStatement = isSgExprStatement ( *it ); if ( isExprStatement != NULL ) { SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() ); if ( functionCallExp != NULL ) { string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call in user subroutine " + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * As we are in fortran, all user subroutines must be * SgProcedureHeaderStatements = subroutines and not * functions. This might be extended to cover also * functions in the future (probably not in OP2) * ====================================================== */ SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( functionCallExp->getAssociatedFunctionDeclaration() ); calledRoutines.push_back ( isProcedureHeaderStatement ); } } SgVariableDeclaration * isVariableDeclaration = isSgVariableDeclaration ( *it); if (isVariableDeclaration == NULL) { /* * ====================================================== * Do not append use statement, because other subroutines * are directly appended to the CUDA module * ====================================================== */ SgUseStatement * isUseStmt = isSgUseStatement ( *it ); if (isUseStmt != NULL) { Debug::getInstance ()->debugMessage ( "Not appending use statement", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); } else { Debug::getInstance ()->debugMessage ( "Appending (non-variable-declaration) statement", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); appendStatement (*it, subroutineScope); /* * ====================================================== * Recursively look for subroutine calls inside shallow * nodes in the routines (e.g. when a call is inside an * if). After the visit get the generated vector of names * and append it to the userSubroutine vector * ====================================================== */ TreeVisitor * visitor = new TreeVisitor (); visitor->traverse (*it, preorder); Debug::getInstance ()->debugMessage ("Appending deep subroutine calls", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); vector < SgProcedureHeaderStatement * > deepStatementCalls = visitor->getCalledRoutinesInStatement (); vector < SgProcedureHeaderStatement * >::iterator itDeepCalls; for (itDeepCalls = deepStatementCalls.begin(); itDeepCalls != deepStatementCalls.end(); ++itDeepCalls) calledRoutines.push_back (*itDeepCalls); Debug::getInstance ()->debugMessage ("Appending deep subroutine calls", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); } } else { Debug::getInstance ()->debugMessage ("Appending variable declaration", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); unsigned int OP_DAT_ArgumentGroup = 1; for (SgInitializedNamePtrList::iterator variableIt = isVariableDeclaration->get_variables ().begin (); variableIt != isVariableDeclaration->get_variables ().end (); ++variableIt) { string const variableName = (*variableIt)->get_name ().getString (); SgType * type = (*variableIt)->get_typeptr (); /* * ====================================================== * Specification of "value" attribute is only * for user kernels. Our call convention is that * in all deeper level calls we always pass parameters * by reference (see else branch below) * ====================================================== */ bool isFormalParamater = false; for (SgInitializedNamePtrList::iterator paramIt = originalParameters->get_args ().begin (); paramIt != originalParameters->get_args ().end (); ++paramIt, ++OP_DAT_ArgumentGroup) { string const formalParamterName = (*paramIt)->get_name ().getString (); if (iequals (variableName, formalParamterName)) { isFormalParamater = true; if (parallelLoop->isIndirect (OP_DAT_ArgumentGroup) && parallelLoop->isRead (OP_DAT_ArgumentGroup)) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is an INDIRECT formal parameter which is READ", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration; if ( isUserKernel == true ) variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); else variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); ROSE_ASSERT ( variableDeclaration != NULL ); } else if (parallelLoop->isGlobal (OP_DAT_ArgumentGroup) && parallelLoop->isRead (OP_DAT_ArgumentGroup)) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is a GLOBAL formal parameter which is READ", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); } else { Debug::getInstance ()->debugMessage ("'" + variableName + "' is a formal parameter " + parallelLoop->getOpDatInformation (OP_DAT_ArgumentGroup), Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); if ( isUserKernel == true ) SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); else SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); } } } if (isFormalParamater == false) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is NOT a formal parameter", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclaration ( variableName, type, subroutineScope); } } } } }
string PrefixSuffixGenerationTraversal::DeclarationOrCommentListElement:: generateDeclarationString ( SgDeclarationStatement* declaration ) const { // This function generates a string for a declaration. The string is required for // the intermediate file to make sure that all transformation code will compile // (since it could depend on declarations defined within the code). // Details: // 1) Only record declarations found within the source file (exclude all header files // since they will be seen when the same header files are included). // 2) Resort the variable declarations to remove redundent entries. // WRONG: variable declarations could have dependences upon class declarations! // 3) Don't sort all declarations since some could have dependences. // a) class declarations // b) typedefs // c) function declarations // d) template declarations // e) variable definition??? ROSE_ASSERT (this != NULL); ROSE_ASSERT ( declaration != NULL ); string declarationString; // Build a SgUnparse_Info object to represent formatting options for // this statement (use the default values). SgUnparse_Info info; // exclude comments info.set_SkipComments(); // exclude all CPP directives (since they have already been evaluated by the front-end) info.set_SkipCPPDirectives(); switch ( declaration->variantT() ) { // Enum declarations should not skip their definition since // this is where the constants are declared. case V_SgEnumDeclaration: case V_SgVariableDeclaration: case V_SgTemplateDeclaration: case V_SgTypedefDeclaration: // Need to figure out if a forward declaration would work or be // more conservative and always output the complete class definition. // turn off output of initializer values info.set_SkipInitializer(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; case V_SgClassDeclaration: // Need to figure out if a forward declaration would work or be // more conservative and always output the complete class definition. // turn off the generation of the function definitions only // (we still want the restof the class definition since these // define all member data and member functions). // info.set_SkipClassDefinition(); info.set_SkipFunctionDefinition(); info.set_AddSemiColonAfterDeclaration(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; // For functions just output the declaration and skip the definition // (This also avoids the generation of redundent definitions since the // function we are in when we generate all declarations would be included). case V_SgMemberFunctionDeclaration: case V_SgFunctionDeclaration: { // turn off the generation of the definition info.set_SkipFunctionDefinition(); info.set_AddSemiColonAfterDeclaration(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; } case V_SgFunctionParameterList: { // Handle generation of declaration strings this case differnetly from unparser // since want to generate declaration strings and not function parameter lists // (function parameter lists would be delimited by "," while declarations would // be delimited by ";"). SgFunctionParameterList* parameterListDeclaration = dynamic_cast<SgFunctionParameterList*>(declaration); ROSE_ASSERT (parameterListDeclaration != NULL); SgInitializedNamePtrList & argList = parameterListDeclaration->get_args(); SgInitializedNamePtrList::iterator i; for (i = argList.begin(); i != argList.end(); i++) { printf ("START: Calling unparseToString on type! \n"); ROSE_ASSERT((*i) != NULL); ROSE_ASSERT((*i)->get_type() != NULL); string typeNameString = (*i)->get_type()->unparseToString(); printf ("DONE: Calling unparseToString on type! \n"); string variableName; if ( (*i)->get_name().getString() != "") { variableName = (*i)->get_name().getString(); declarationString += typeNameString + " " + variableName + "; "; } else { // Don't need the tailing ";" if there is no variable name (I think) declarationString += typeNameString + " "; } } break; } // ignore this case ... not really a declaration case V_SgCtorInitializerList: // printf ("Ignore the SgCtorInitializerList (constructor initializer list) \n"); break; case V_SgVariableDefinition: printf ("ERROR: SgVariableDefinition nodes not used in AST \n"); ROSE_ABORT(); break; // default case should always be an error default: printf ("Default reached in AST_Rewrite::AccumulatedDeclarationsAttribute::generateDeclarationString() \n"); printf (" declaration->sage_class_name() = %s \n",declaration->sage_class_name()); ROSE_ABORT(); break; } // Add a space to make it easier to read (not required) declarationString += " "; // printf ("For this scope: declarationString = %s \n",declarationString.c_str()); return declarationString; }
/** * \brief Return true if methodDecl overrides virtualMethodDecl. * \param methodDecl a method declaration. * \param virtualMethodDecl a method declaration. * \return Returns true if virtualMethodDecl is declared as a virtual * method and methodDecl has the same type signature and name * as virtualMethodDecl. * * NB: It is assumed that the class defining virtualMethodDecl is a base * class of the class defining methodDecl. */ bool methodOverridesVirtualMethod(SgMemberFunctionDeclaration *methodDecl, SgMemberFunctionDeclaration *virtualMethodDecl) { if ( !isVirtual(virtualMethodDecl) ) return false; // std::cout << "looks virtual" << std::endl; #if 0 // Hmmm ... couldn't we just compare mangled names? // No, we can't because this includes the scope info, which will // differ between classes. std::cout << "methodDecl: " << methodDecl->get_mangled_name().str() << std::endl; std::cout << "virtualMethodDecl: " << virtualMethodDecl->get_mangled_name().str() << std::endl; return ( methodDecl->get_mangled_name() == virtualMethodDecl->get_mangled_name() ); #else if ( methodDecl->get_name() != virtualMethodDecl->get_name() ) return false; SgType *methodReturnType = methodDecl->get_orig_return_type(); SgType *virtualMethodReturnType = virtualMethodDecl->get_orig_return_type(); if ( methodReturnType != virtualMethodReturnType ) return false; int numMethodParams = 0; int numVirtualMethodParams = 0; SgFunctionParameterList *methodParameterList = methodDecl->get_parameterList(); if (methodParameterList != NULL) { numMethodParams = methodParameterList->get_args().size(); } SgFunctionParameterList *virtualMethodParameterList = virtualMethodDecl->get_parameterList(); if (virtualMethodParameterList != NULL) { numVirtualMethodParams = virtualMethodParameterList->get_args().size(); } if ( numMethodParams != numVirtualMethodParams ) return false; if ( numMethodParams == 0 ) return true; const SgInitializedNamePtrList &methodFormalParams = methodParameterList->get_args(); const SgInitializedNamePtrList &virtualMethodFormalParams = virtualMethodParameterList->get_args(); SgInitializedNamePtrList::const_iterator methodIt; SgInitializedNamePtrList::const_iterator virtualMethodIt; for(methodIt = methodFormalParams.begin(), virtualMethodIt = virtualMethodFormalParams.begin(); methodIt != methodFormalParams.end(); ++methodIt, ++virtualMethodIt) { SgInitializedName* methodFormalParam = *methodIt; ROSE_ASSERT(methodFormalParam != NULL); SgInitializedName* virtualMethodFormalParam = *virtualMethodIt; ROSE_ASSERT(virtualMethodFormalParam != NULL); if ( methodFormalParam->get_type() != virtualMethodFormalParam->get_type() ) return false; } return true; #endif }
void ControlDependenceGraph::_buildInterprocedural() { // Go through the SGNODE dependence nodes and create the appropriate // call site nodes, entry nodes etc. SgFunctionDefinition *func = isSgFunctionDefinition(_head); ROSE_ASSERT(func != NULL); // First create the entry node for the procedure _interprocedural->procedureEntry.entry = new DependenceNode(DependenceNode::ENTRY, func->get_declaration()); DependenceNode *entry = createNode(_interprocedural->procedureEntry.entry); // Link the entry node up with all the nodes in the CDG which do not have // predecessors for (set < SimpleDirectedGraphNode * >::iterator i = _nodes.begin(); i != _nodes.end(); i++) { DependenceNode *node = dynamic_cast < DependenceNode * >(*i); if ((node->numPredecessors() == 0) && (node != entry)) { establishEdge(entry, node); } } // create a formal out return argument, control dependent on the entry // node string return_name = func->get_declaration()->get_name().str(); return_name = return_name + " return"; _interprocedural->procedureEntry.formal_return = new DependenceNode(DependenceNode::FORMALOUT, return_name); DependenceNode *formal_return = createNode(_interprocedural->procedureEntry.formal_return); establishEdge(entry, formal_return); // for each of the arguments in the function parameter list, add a // formal-in and formal-out node SgFunctionParameterList *paramlist = func->get_declaration()->get_parameterList(); SgInitializedNamePtrList params = paramlist->get_args(); for (SgInitializedNamePtrList::iterator i = params.begin(); i != params.end(); i++) { SgInitializedName *name = *i; DependenceNode *formal_in = new DependenceNode(DependenceNode::FORMALIN, name->get_name().str()); DependenceNode *formal_out = new DependenceNode(DependenceNode::FORMALOUT, name->get_name().str()); establishEdge(entry, createNode(formal_in)); establishEdge(entry, createNode(formal_out)); _interprocedural->procedureEntry.formal_in[name] = formal_in; _interprocedural->procedureEntry.formal_out[name] = formal_out; // To preserve the order of arguments, we insert them into arg_order _interprocedural->procedureEntry.arg_order.push_back(name); } // Now we go through each of the SgNodes in our CDG. If any of them // contain a function call, we want to build a call site node for them. map < SgNode *, DependenceNode * >::iterator sgnode_iterator; for (sgnode_iterator = _sgnode_map.begin(); sgnode_iterator != _sgnode_map.end(); sgnode_iterator++) { SgNode *currnode = sgnode_iterator->first; list < SgFunctionCallExp * >calls = InterproceduralInfo::extractFunctionCalls(currnode); if (calls.empty()) continue; for (list < SgFunctionCallExp * >::iterator i = calls.begin(); i != calls.end(); i++) { SgFunctionCallExp *call = *i; // This needs to be replaced with some call graph analysis SgFunctionRefExp *func = isSgFunctionRefExp(call->get_function()); ROSE_ASSERT(func != NULL); SgName func_name = func->get_symbol()->get_name(); InterproceduralInfo::CallSiteStructure callstructure; callstructure.callsite = new DependenceNode(DependenceNode::CALLSITE, call); // the call site is control dependent on the statement (i.e. for // the call site to happen, the statement must be executed) DependenceNode *callsite = createNode(callstructure.callsite); // addLink(callsite, getNode(currnode)); establishEdge(getNode(currnode), callsite); // create an actual out node for the return value, control // dependent on callsite string return_name = func_name.str(); return_name = return_name + " return"; callstructure.actual_return = new DependenceNode(DependenceNode::ACTUALOUT, return_name); DependenceNode *actual_return = createNode(callstructure.actual_return); establishEdge(callsite, actual_return); // For each argument in the function call, build an actual_in and // actual_out, control dependent on callsite SgExpressionPtrList args = call->get_args()->get_expressions(); for (SgExpressionPtrList::iterator j = args.begin(); j != args.end(); j++) { SgExpression *arg = *j; DependenceNode *actual_in = new DependenceNode(DependenceNode::ACTUALIN, arg); DependenceNode *actual_out = new DependenceNode(DependenceNode::ACTUALOUT, arg); establishEdge(callsite, createNode(actual_in)); establishEdge(callsite, createNode(actual_out)); callstructure.actual_in[arg] = actual_in; callstructure.actual_out[arg] = actual_out; // To preserve the order of expressions in the parameter list, // // we insert them into expr_order callstructure.expr_order.push_back(arg); } // add the callstructure to interprocedural info _interprocedural->callsite_map[call] = callstructure; } } }
/** * \brief Return true if methodDecl overrides virtualMethodDecl. * \param methodDecl a method declaration. * \param virtualMethodDecl a method declaration. * \return Returns true if virtualMethodDecl is declared as a virtual * method and methodDecl has the same type signature and name * as virtualMethodDecl. * * NB: It is assumed that the class defining virtualMethodDecl is a base * class of the class defining methodDecl. */ bool methodOverridesVirtualMethod(SgMemberFunctionDeclaration *methodDecl, SgMemberFunctionDeclaration *virtualMethodDecl) { if ( !isVirtual(virtualMethodDecl) ) return false; #if 1 // Hmmm ... couldn't we just compare mangled names? return ( methodDecl->get_mangled_name() == virtualMethodDecl->get_mangled_name() ); #else if ( methodDecl->get_name() != virtualMethodDecl->get_name() ) return false; SgType *methodReturnType = methodDecl->get_orig_return_type(); SgType *virtualMethodReturnType = virtualMethodDecl->get_orig_return_type(); if ( methodReturnType != virtualMethodReturnType ) return false; int numMethodParams = 0; int numVirtualMethodParams = 0; SgFunctionParameterList *methodParameterList = methodDecl->get_parameterList(); if (methodParameterList != NULL) { numMethodParams = methodParameterList->get_args().size(); } SgFunctionParameterList *virtualMethodParameterList = virtualMethodDecl->get_parameterList(); if (virtualMethodParameterList != NULL) { numVirtualMethodParams = virtualMethodParameterList->get_args().size(); } if ( numMethodParams != numVirtualMethodParams ) return false; if ( numMethodParams == 0 ) return true; const SgInitializedNamePtrList &methodFormalParams = methodParameterList->get_args(); const SgInitializedNamePtrList &virtualMethodFormalParams = virtualMethodParameterList->get_args(); SgInitializedNamePtrList::const_iterator methodIt; SgInitializedNamePtrList::const_iterator virtualMethodIt; for(methodIt = methodFormalParams.begin(), virtualMethodIt = virtualMethodFormalParams.begin(); methodIt != methodFormalParams.end(); ++methodIt, ++virtualMethodIt) { SgInitializedName* methodFormalParam = *methodIt; ROSE_ASSERT(methodFormalParam != NULL); SgInitializedName* virtualMethodFormalParam = *virtualMethodIt; ROSE_ASSERT(virtualMethodFormalParam != NULL); if ( methodFormalParam->get_type() != virtualMethodFormalParam->get_type() ) return false; } return true; #endif }