/** * No atexit handler should terminate in any way other than by returning * \note This catches calls to exit, _exit, _abort, _Exit, longjmp and * siglongjmp */ bool ENV32_C( const SgNode *node ) { const SgFunctionRefExp *fnRef = isSgFunctionRefExp(node); if (!(fnRef && isCallOfFunctionNamed(fnRef, "atexit"))) return false; const SgFunctionRefExp* ref = isSgFunctionRefExp(getFnArg(fnRef, 0)); assert(ref); const SgFunctionDeclaration *fnDecl = ref->get_symbol()->get_declaration(); assert(fnDecl); bool violation = false; FOREACH_SUBNODE(fnDecl,nodes,i,V_SgFunctionRefExp) { const SgFunctionRefExp *iFn = isSgFunctionRefExp(*i); assert(iFn); if(isCallOfFunctionNamed( iFn, "exit") || isCallOfFunctionNamed( iFn, "_exit") || isCallOfFunctionNamed( iFn, "abort") || isCallOfFunctionNamed( iFn, "_Exit") || isCallOfFunctionNamed( iFn, "longjmp") || isCallOfFunctionNamed( iFn, "siglongjmp")) { print_error( fnDecl, "ENV32-C", "No atexit handler should terminate in any way other than by returning"); violation = true; } } return violation; }
/** * Take care when calling remove() on an open file */ bool FIO08_C( const SgNode *node ) { const SgFunctionRefExp *fnRef = isSgFunctionRefExp(node); if(!(fnRef && isCallOfFunctionNamed(fnRef, "remove"))) return false; const SgExpression *fnExp = removeImplicitPromotions(getFnArg(fnRef,0)); assert(fnExp); const SgVarRefExp *ref = isSgVarRefExp(fnExp); if(!ref) return false; const SgInitializedName *var = getRefDecl(ref); bool opened = false; bool closed = false; /* *open or *close */ const SgFunctionRefExp *iFn = NULL; /* Argument to *open or *close */ const SgVarRefExp *iVar = NULL; /* File descriptor return by *open */ const SgInitializedName *fd = NULL; FOREACH_SUBNODE(findParentOfType(node, SgFunctionDefinition), nodes, i, V_SgFunctionRefExp) { iFn = isSgFunctionRefExp(*i); assert(iFn); if(iFn == fnRef) break; iVar = isSgVarRefExp(removeImplicitPromotions(getFnArg(iFn,0))); if (!iVar) continue; if(isCallOfFunctionNamed(iFn, "open") || isCallOfFunctionNamed(iFn, "fopen") || isCallOfFunctionNamed(iFn, "freopen")) { fd = getVarAssignedTo(iFn, NULL); assert(fd); if (getRefDecl(iVar) == var) { closed = false; opened = true; } } if (opened && (isCallOfFunctionNamed(iFn, "close")) || isCallOfFunctionNamed(iFn, "fclose")) { if (getRefDecl(iVar) == fd) { closed = true; opened = false; } } }
/* * Replace the op_par_loop with respective kernel function */ void OPSource::fixParLoops(SgNode *n) { SgName kernel_name; SgFunctionCallExp *fn = isSgFunctionCallExp(n); if(fn != NULL) { string fn_name = fn->getAssociatedFunctionDeclaration()->get_name().getString(); if(fn_name.compare("op_par_loop_2")==0 || fn_name.compare("op_par_loop_3")==0 || fn_name.compare("op_par_loop_4")==0 || fn_name.compare("op_par_loop_5")==0 || fn_name.compare("op_par_loop_6")==0 || fn_name.compare("op_par_loop_7")==0 || fn_name.compare("op_par_loop_8")==0 || fn_name.compare("op_par_loop_9")==0) { SgExprListExp* exprList = fn->get_args(); SgExpressionPtrList &exprs = exprList->get_expressions(); SgFunctionRefExp* varExp = isSgFunctionRefExp(exprs[0]); if(varExp != NULL) { kernel_name = varExp->get_symbol()->get_name(); } exprs.erase(exprs.begin()); SgExpressionPtrList::iterator it = exprs.begin() + op_par_loop_args::num_params - 1; for(; it != exprs.end(); it += op_argument::num_params) { *it = buildCastExp( *it, buildPointerType(SgClassType::createType( buildStructDeclaration("op_dat<void>"))) ); } // Inject Name exprs.insert(exprs.begin(), buildStringVal(kernel_name)); // Fetch the declaration SgName name = SgName("op_par_loop_") + kernel_name; SgFunctionDeclaration *funcDecl = cudaFunctionDeclarations[kernel_name]; if(funcDecl) { SgFunctionRefExp* ref = isSgFunctionRefExp(fn->get_function()); SgFunctionSymbol *symbol = ref->get_symbol(); symbol->set_declaration(funcDecl); ref->set_symbol(symbol); fn->set_function(ref); } } } }
void CompassAnalyses::StringTokenToIntegerConverter::Traversal:: visit(SgNode* node) { // Implement your traversal here. if(isSgFunctionCallExp(node)) { SgFunctionCallExp* callSite = isSgFunctionCallExp(node); if(callSite->get_function() != NULL) { SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(callSite->get_function()); if(functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); ROSE_ASSERT(functionSymbol != NULL); std::string functionName = functionSymbol->get_name().getString(); if(functionName == "atoi" || functionName == "atol" || functionName == "atoll" || functionName == "sscanf" ) { output->addOutput(new CheckerOutput(node)); } } } } } //End of the visit function.
/** * Prefer fseek() to rewind() */ bool FIO07_C( const SgNode *node ) { const SgFunctionRefExp *fnRef = isSgFunctionRefExp(node); if (!(fnRef && isCallOfFunctionNamed(fnRef, "rewind"))) return false; print_error( node, "FIO07-C", "Prefer fseek() to rewind()", true); return true; }
void CompassAnalyses::NoVariadicFunctions::Traversal:: visit(SgNode* node) { switch( node->variantT() ) { case V_SgFunctionRefExp: { SgFunctionRefExp *fref = isSgFunctionRefExp(node); ROSE_ASSERT(fref != NULL); SgFunctionDeclaration *fdecl = fref->get_symbol()->get_declaration(); this->functionDeclarationHandler( fdecl, fref ); } break; //case V_SgFunctionRefExp case V_SgMemberFunctionRefExp: { SgMemberFunctionRefExp *fref = isSgMemberFunctionRefExp(node); ROSE_ASSERT(fref != NULL); SgFunctionDeclaration *fdecl = fref->get_symbol()->get_declaration(); this->functionDeclarationHandler( fdecl, fref ); } break; //case V_SgMemberFunctionRefExp default: break; } //switch( node->variantT() ) return; } //End of the visit function.
/////////////////////////////////////////////////////////////////////////////////// The CompassAnalyses::NoExitInMpiCode::Traversal::visit(SgNode* node) /// function implements a simple AST traversal seeking out SgFunctionRefExp /// nodes for function reference expressions corresponding to MPI Init and /// Finalize and calls to exit() nested in those blocks; these are reported /// as checker violations. /// /// \param node is a SgNode* //////////////////////////////////////////////////////////////////////////////// void CompassAnalyses::NoExitInMpiCode::Traversal::visit(SgNode* node) { static bool usedMPI = false; SgFunctionRefExp *sgfrexp = isSgFunctionRefExp(node); if( sgfrexp != NULL ) { std::string sgfrexpName = sgfrexp->get_symbol()->get_name().getString(); if( sgfrexpName == "MPI_Init" ) { usedMPI = true; } //if( sgfrexpNam == "MPI_Init" ) if( sgfrexpName == "MPI_Finalize" ) { usedMPI = false; } //if( sgfrexpName == "MPI_Finalize" ) //#ASR:07/07/10 //fixed object creation of CheckerOutput for Cxx standard if( usedMPI == true && sgfrexpName == "exit" ) { output->addOutput( new CompassAnalyses::NoExitInMpiCode::CheckerOutput( node ) ); //output->addOutput( new CompassAnalyses::NoExitInMpiCode::CheckerOutput::CheckerOutput( node ) ); } //if( usedMPI == true && sgfrexpName == "exit" ) } //if( sgfrexp != NULL ) return; } //visit(SgNode *node)
void CompassAnalyses::PreferFseekToRewind::Traversal:: visit(SgNode* node) { // Implement your traversal here. if(isSgFunctionCallExp(node)) { SgFunctionCallExp* callSite = isSgFunctionCallExp(node); if(callSite->get_function() != NULL) { SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(callSite->get_function()); if(functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); ROSE_ASSERT(functionSymbol != NULL); std::string functionName = functionSymbol->get_name().getString(); if(functionName == "rewind") { output->addOutput(new CheckerOutput(node)); } } } } } //End of the visit function.
/** * Do not use system() * * \note As written, these tests catch template declarations only if instantiated. */ bool ENV04_C( const SgNode *node ) { const SgFunctionRefExp *fnRef = isSgFunctionRefExp(node); if (!fnRef) return false; if (!(isCallOfFunctionNamed(fnRef, "system") ||isCallOfFunctionNamed(fnRef, "popen"))) return false; print_error( node, "ENV04-C", "Do not use system() or popen() unless you need a command interpreter", true); return true; }
/** * Do not modify the string returned by getenv() */ bool ENV30_C( const SgNode *node ) { const SgFunctionRefExp *fnRef = isSgFunctionRefExp(node); if (!fnRef) return false; if (!isCallOfFunctionNamed(fnRef, "getenv")) return false; const SgInitializedName *var = getVarAssignedTo(fnRef, NULL); if (!var) return false; if (isConstType(var->get_type()->dereference())) return false; print_error(node, "ENV30-C", "Do not modify the string returned by getenv()"); return true; }
void ASLAnalysis::visit(SgNode* node){ // concrete classes of AST nodes switch(node->variantT()){ // naming scheme for variants: V_<classname> case V_SgFunctionDeclaration:{ SgFunctionDeclaration* fdecl=isSgFunctionDeclaration(node); if(SgFunctionDefinition* fdef=fdecl->get_definition()) { std::string functionName=fdecl->get_name().getString(); Sg_File_Info* ptrFileInfo=node->get_file_info(); std::string aslPrefix=""; if(ptrFileInfo){ aslPrefix=ptrFileInfo->get_filenameString()+"/"; } enterFunction(aslPrefix+functionName); // set function name and reset enumeration counter } } break; // function calls through function pointers case V_SgPointerDerefExp:{ if(isSgFunctionCallExp(node->get_parent()) && !(isSgFunctionCallExp(node->get_parent())->get_function() != node)){ #ifdef DEBUG std::cout<<"Function Pointer at call-site"<<std::endl; #endif storeLocalSite(node); callSiteCounter++; functionPointerCallCounter++; } } break; case V_SgFunctionCallExp:{ SgFunctionCallExp* fcall=isSgFunctionCallExp(node); if(SgFunctionRefExp* func=isSgFunctionRefExp(fcall->get_function())) { // SgFunctionSymbol* functionSymbol=func->get_symbol(); // std::string functionName=functionSymbol->get_name().getString(); callSiteCounter++; } } break; } }
/** * Be careful using functions that use file names for identification */ bool FIO01_C( const SgNode *node ) { const SgFunctionRefExp *fnRef = isSgFunctionRefExp(node); if (!fnRef) return false; if (!(isCallOfFunctionNamed(fnRef, "chown") || isCallOfFunctionNamed(fnRef, "stat") || isCallOfFunctionNamed(fnRef, "chmod"))) { return false; } const SgVarRefExp* file_name = isSgVarRefExp(getFnArg(fnRef,0)); if (!file_name) return false; /** * See if the file was opened inside this function, if so, we have a * problem */ FOREACH_SUBNODE(findParentOfType(fnRef, SgFunctionDefinition), nodes, i, V_SgFunctionRefExp) { const SgFunctionRefExp *iFn = isSgFunctionRefExp(*i); assert(iFn); if (isCallOfFunctionNamed(iFn, "open") || isCallOfFunctionNamed(iFn, "fopen")) { const SgVarRefExp *iVar = isSgVarRefExp(getFnArg(iFn,0)); if (iVar && (getRefDecl(iVar) == getRefDecl(file_name))) { print_error(node, "FIO01-C", "Be careful using functions that use file names for identification", true); return true; } } } /* If the file was not opened, it's probably ok to use these functions */ return false; }
void FortranAnalysis::visit(SgFunctionCallExp * fcall) { SgFunctionRefExp * fref = isSgFunctionRefExp(fcall->get_function()); if (fref != NULL) { SgExpressionPtrList::iterator it = fcall->get_args()->get_expressions().begin(); std::string name = fref->get_symbol()->get_name().getString(); if (name == "interior" && it != fcall->get_args()->get_expressions().end()) { SgVarRefExp * var = isSgVarRefExp(*it); SgSymbol * sym = var->get_symbol(); sym->setAttribute("halo_attr", new AstTextAttribute("HALO_VAR")); debug("SgFunctionCallExp: adding halo attribute to %s\n", sym->get_name().getString().c_str()); } } }
virtual void visit(SgNode * n) { switch (n->variantT()) { case V_SgFunctionDeclaration: { SgFunctionDeclaration * func_decl = isSgFunctionDeclaration(n); ROSE_ASSERT(func_decl != NULL); std::string func_name = func_decl->get_name().getString(); // std::cout << "Found SgFunctionDeclaration: " << func_name << std::endl; if (func_name == "caller") p_caller = func_decl; if (func_name == "kernel") p_kernel = func_decl; break; } case V_SgForStatement: { SgForStatement * for_stmt = isSgForStatement(n); ROSE_ASSERT(for_stmt != NULL); // std::cout << "Found SgForStatement." << std::endl; p_for_stmts.push_back(for_stmt); break; } case V_SgFunctionCallExp: { SgFunctionCallExp * func_call = isSgFunctionCallExp(n); ROSE_ASSERT(func_call != NULL); SgFunctionRefExp * func_ref = isSgFunctionRefExp(func_call->get_function()); ROSE_ASSERT(func_ref != NULL); // std::cout << "Found SgFunctionCallExp: " << func_ref->getAssociatedFunctionDeclaration ()->get_name().getString() << std::endl; if (func_ref->getAssociatedFunctionDeclaration()->get_name().getString() == "kernel") p_kernel_call_site = func_call; break; } case V_SgSourceFile: // fix the file suffix, Liao 12/29/2010 { SgSourceFile * sfile = isSgSourceFile (n); ROSE_ASSERT (sfile != NULL); sfile->set_Cuda_only(true); } default:{} } }
void CompassAnalyses::NoRand::Traversal:: visit(SgNode* node) { const int STRING_LEN_RAND = 4; SgFunctionRefExp *sgFuncRef = isSgFunctionRefExp( node ); if( sgFuncRef != NULL ) { std::string fncName = sgFuncRef->get_symbol()->get_name().getString(); if( fncName.find( "rand", 0, STRING_LEN_RAND ) != std::string::npos ) { output->addOutput( new CheckerOutput( node ) ); } //if( fncName.find("vfork", 0, STRING_LEN_RAND) != std::string::npos ) } //if( sgFuncRef != NULL ) return; } //End of the visit function.
bool FortranAnalysis::matchRegionAssignment(SgExprStatement * expr_stmt) { SgBinaryOp * bin_op = isSgBinaryOp(expr_stmt->get_expression()); if (bin_op == NULL) return false; SgFunctionCallExp * fcall = isSgFunctionCallExp(bin_op->get_rhs_operand()); if (fcall == NULL) return false; SgFunctionRefExp * fref = isSgFunctionRefExp(fcall->get_function()); if (fref == NULL) return false; SgExpressionPtrList::iterator it = fcall->get_args()->get_expressions().begin(); std::string name = fref->get_symbol()->get_name().getString(); if (name == "interior" && it != fcall->get_args()->get_expressions().end()) { SgVarRefExp * var = isSgVarRefExp(*it); if (var == NULL) return false; AstTextAttribute * attr = (AstTextAttribute *) var->get_symbol()->getAttribute("dummy_attr"); if (attr == NULL) return false; if (attr->toString() != "DUMMY_ARRAY_ARG") return false; } return true; }
/** * Beware of multiple environment variables with the same effective name */ bool ENV02_C( const SgNode *node ) { static std::set<std::string> origStrs; static std::set<std::string> normStrs; static std::map<std::string, const SgFunctionRefExp *> strToNode; const SgFunctionRefExp *fnRef = isSgFunctionRefExp(node); if (!fnRef) return false; if (!(isCallOfFunctionNamed(fnRef, "getenv") ||isCallOfFunctionNamed(fnRef, "setenv") ||isCallOfFunctionNamed(fnRef, "putenv"))) { return false; } const SgStringVal *strVal = isSgStringVal(removeImplicitPromotions(getFnArg(fnRef,0))); if (!strVal) return false; std::string str = strVal->get_value(); if (const unsigned int eq = str.find_first_of("=")) str = str.substr(0,eq); if (origStrs.find(str) != origStrs.end()) return false; origStrs.insert(str); std::transform(str.begin(), str.end(), str.begin(), tolower); if (normStrs.find(str) != normStrs.end()) { print_error(node, "ENV02-C", "Beware of multiple environment variables with the same effective name", true); print_error(strToNode[str], "ENV02-C", "Previous reference was here", true); return true; } normStrs.insert(str); strToNode[str] = fnRef; return false; }
/** * Do not rely on an environment pointer following an operation that may * invalidate it */ bool ENV31_C( const SgNode *node ) { const SgVarRefExp *varRef = isSgVarRefExp(node); if (!varRef) return false; if (getRefDecl(varRef)->get_name().getString() != "envp") return false; bool violation = false; FOREACH_SUBNODE(getRefDecl(varRef)->get_scope(), nodes, i, V_SgExpression) { if (varRef == isSgVarRefExp(*i)) break; const SgFunctionRefExp *iFn = isSgFunctionRefExp(*i); if (!iFn) continue; if (isCallOfFunctionNamed(iFn, "putenv") ||isCallOfFunctionNamed(iFn, "setenv")) { violation = true; break; } } if (violation) { print_error(node, "ENV31-C", "Do not rely on an environment pointer following an operation that may invalidate it"); } return violation; }
SgFunctionDeclaration * getFunctionDeclaration(SgFunctionCallExp *functionCall) { SgFunctionDeclaration *funcDec = NULL; SgExpression *expression = functionCall->get_function(); ROSE_ASSERT(expression != NULL); switch(expression->variantT()) { case V_SgMemberFunctionRefExp: { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(expression); ROSE_ASSERT(memberFunctionRefExp != NULL); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); ROSE_ASSERT(funcDec != NULL); break; } case V_SgDotExp: { SgDotExp *dotExp = isSgDotExp(expression); ROSE_ASSERT(dotExp != NULL); if(dotExp->get_traversalSuccessorContainer().size()>=2) { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(dotExp->get_traversalSuccessorContainer()[1]); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); } ROSE_ASSERT(funcDec != NULL); break; } case V_SgArrowExp: { SgArrowExp *arrowExp = isSgArrowExp(expression); ROSE_ASSERT(arrowExp != NULL); if(arrowExp->get_traversalSuccessorContainer().size()>=2) { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(arrowExp->get_traversalSuccessorContainer()[1]); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); } ROSE_ASSERT(funcDec != NULL); break; } case V_SgFunctionRefExp: { SgFunctionRefExp *functionRefExp = isSgFunctionRefExp(expression); ROSE_ASSERT(functionRefExp != NULL); // found a standard function reference funcDec = functionRefExp->get_symbol_i()->get_declaration(); ROSE_ASSERT(funcDec != NULL); break; } case V_SgPointerDerefExp: { ROSE_ABORT(); break; } default: { ROSE_ABORT(); } } return funcDec; }
/** * Do not store the pointer to the string returned by getenv() * * \todo Do we also need to check for putenv/setenv in the loop? */ bool ENV00_C( const SgNode *node ) { // find call of getenv const SgFunctionRefExp *fnRef = isSgFunctionRefExp(node); if (!fnRef) return false; if (!isCallOfFunctionNamed(fnRef, "getenv")) return false; // find var saved into const SgInitializedName *var = getVarAssignedTo(fnRef, NULL); if (!var) return false; bool getenv_found = false; bool write = false; bool after = false; // traverse down, searching for copy functions (break) FOREACH_SUBNODE(findParentOfType(fnRef, SgFunctionDefinition), nodes, i, V_SgExpression) { const SgExpression * expr = isSgExpression(*i); const SgFunctionRefExp *iFnRef = isSgFunctionRefExp(*i); assert(expr); if (!after) { if (iFnRef == fnRef) after = true; continue; } // search for another call to getenv if (iFnRef && isCallOfFunctionNamed(iFnRef, "getenv")) { getenv_found = true; if (var == getVarAssignedTo(isSgFunctionRefExp(expr), NULL)) return false; continue; } if (!getenv_found) continue; // search for write (break) const SgVarRefExp *iVar = isSgVarRefExp(expr); if (!iVar || (getRefDecl(iVar) != var)) continue; const SgFunctionCallExp *iFnCall = findParentOfType(iVar, SgFunctionCallExp); if (!iFnCall) { if (varWrittenTo(iVar)) return false; write = true; break; } const SgFunctionRefExp *iFn = isSgFunctionRefExp(iFnCall->get_function()); assert(iFn); if (isCallOfFunctionNamed(iFn, "strcpy") ||isCallOfFunctionNamed(iFn, "memset") ||isCallOfFunctionNamed(iFn, "strdup")) return false; write = true; break; } // if read & getenv then error if (getenv_found && write) { print_error(node, "ENV00-C", "Do not store the pointer to the string returned by getenv()", true); return true; } return false; }
int main( int argc, char* argv[] ) { // Initialize and check compatibility. See rose::initialize ROSE_INITIALIZE; SgProject* project = frontend(argc,argv); AstTests::runAllTests(project); #if 0 // Output the graph so that we can see the whole AST graph, for debugging. generateAstGraph(project, 4000); #endif #if 1 printf ("Generate the dot output of the SAGE III AST \n"); generateDOT ( *project ); printf ("DONE: Generate the dot output of the SAGE III AST \n"); #endif // There are lots of way to write this, this is one simple approach; get all the function calls. std::vector<SgNode*> functionCalls = NodeQuery::querySubTree (project,V_SgFunctionCallExp); // Find the SgFunctionSymbol for snprintf so that we can reset references to "sprintf" to "snprintf" instead. // SgGlobal* globalScope = (*project)[0]->get_globalScope(); SgSourceFile* sourceFile = isSgSourceFile(project->get_fileList()[0]); ROSE_ASSERT(sourceFile != NULL); SgGlobal* globalScope = sourceFile->get_globalScope(); SgFunctionSymbol* snprintf_functionSymbol = globalScope->lookup_function_symbol("snprintf"); ROSE_ASSERT(snprintf_functionSymbol != NULL); // Iterate over the function calls to find the calls to "sprintf" for (unsigned long i = 0; i < functionCalls.size(); i++) { SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(functionCalls[i]); ROSE_ASSERT(functionCallExp != NULL); SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionCallExp->get_function()); if (functionRefExp != NULL) { SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol(); if (functionSymbol != NULL) { SgName functionName = functionSymbol->get_name(); // printf ("Function being called: %s \n",functionName.str()); if (functionName == "sprintf") { // Now we have something to do! functionRefExp->set_symbol(snprintf_functionSymbol); // Now add the "n" argument SgExprListExp* functionArguments = functionCallExp->get_args(); SgExpressionPtrList & functionArgumentList = functionArguments->get_expressions(); // "sprintf" shuld have exactly 2 arguments (I guess the "..." don't count) printf ("functionArgumentList.size() = %zu \n",functionArgumentList.size()); // ROSE_ASSERT(functionArgumentList.size() == 2); SgExpressionPtrList::iterator i = functionArgumentList.begin(); // printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str()); SgVarRefExp* variableRefExp = isSgVarRefExp(*i); ROSE_ASSERT(variableRefExp != NULL); // printf ("variableRefExp->get_type() = %p = %s = %s \n",variableRefExp->get_type(),variableRefExp->get_type()->class_name().c_str(),SageInterface::get_name(variableRefExp->get_type()).c_str()); SgType* bufferType = variableRefExp->get_type(); SgExpression* bufferLengthExpression = NULL; switch(bufferType->variantT()) { case V_SgArrayType: { SgArrayType* arrayType = isSgArrayType(bufferType); bufferLengthExpression = arrayType->get_index(); break; } case V_SgPointerType: { // SgPointerType* pointerType = isSgPointerType(bufferType); SgInitializedName* variableDeclaration = variableRefExp->get_symbol()->get_declaration(); ROSE_ASSERT(variableDeclaration != NULL); SgExpression* initializer = variableDeclaration->get_initializer(); if (initializer != NULL) { SgAssignInitializer* assignmentInitializer = isSgAssignInitializer(initializer); ROSE_ASSERT(assignmentInitializer != NULL); // This is the rhs of the initialization of the pointer (likely a malloc through a cast). // This assumes: buffer = (char*) malloc(bufferLengthExpression); SgExpression* initializationExpression = assignmentInitializer->get_operand(); ROSE_ASSERT(initializationExpression != NULL); SgCastExp* castExp = isSgCastExp(initializationExpression); ROSE_ASSERT(castExp != NULL); SgFunctionCallExp* functionCall = isSgFunctionCallExp(castExp->get_operand()); ROSE_ASSERT(functionCall != NULL); SgExprListExp* functionArguments = isSgExprListExp(functionCall->get_args()); bufferLengthExpression = functionArguments->get_expressions()[0]; ROSE_ASSERT(bufferLengthExpression != NULL); } else { printf ("Initializer not found, so no value for n in snprintf can be computed currently \n"); } break; } default: { printf ("Error: default reached in evaluation of buffer type = %p = %s \n",bufferType,bufferType->class_name().c_str()); ROSE_ASSERT(false); } } ROSE_ASSERT(bufferLengthExpression != NULL); // printf ("bufferLengthExpression = %p = %s = %s \n",bufferLengthExpression,bufferLengthExpression->class_name().c_str(),SageInterface::get_name(bufferLengthExpression).c_str()); // Jump over the first argument, the "n" is defined to be the 2nd argument (the rest are shifted one position). i++; // Build a deep copy of the expression used to define the static buffer (could be any complex expression). SgTreeCopy copy_help; SgExpression* bufferLengthExpression_copy = isSgExpression(bufferLengthExpression->copy(copy_help)); // Insert the "n" for the parameter list to work with "snprintf" instead of "sprintf" functionArgumentList.insert(i,bufferLengthExpression_copy); } } } } return backend(project); }