void CompassAnalyses::DiscardAssignment::Traversal:: visit(SgNode* node) { if (isSgAssignOp(node)) { // simple case: the parent of a "real" assignment op must be an // expression statement if (!isSgExprStatement(node->get_parent())) { output->addOutput(new CheckerOutput(node)); } else { // not so simple case: the parent is an expression statement, but if // that statement is an if/loop condition, we still want to complain SgNode *assignment = node->get_parent(); SgNode *p = assignment->get_parent(); SgDoWhileStmt *dws; SgForStatement *fs; SgIfStmt *is; SgSwitchStatement *ss; SgWhileStmt *ws; if ((dws = isSgDoWhileStmt(p)) && dws->get_condition() == assignment) { output->addOutput(new CheckerOutput(node)); } else if ((fs = isSgForStatement(p)) && fs->get_test() == assignment) { output->addOutput(new CheckerOutput(node)); } else if ((is = isSgIfStmt(p)) && is->get_conditional() == assignment) { output->addOutput(new CheckerOutput(node)); } else if ((ss = isSgSwitchStatement(p)) && ss->get_item_selector() == assignment) { output->addOutput(new CheckerOutput(node)); } else if ((ws = isSgWhileStmt(p)) && ws->get_condition() == assignment) { output->addOutput(new CheckerOutput(node)); } } } else if (SgMemberFunctionRefExp *mf = isSgMemberFunctionRefExp(node)) { // not so simple case: call to operator= member function that is not an // expression statement by itself SgFunctionCallExp *call = isSgFunctionCallExp(mf->get_parent()->get_parent()); if (call && !isSgExprStatement(call->get_parent()) && mf->get_parent() == call->get_function() && std::strcmp(mf->get_symbol()->get_name().str(), "operator=") == 0) { output->addOutput(new CheckerOutput(call)); } } } //End of the visit function.
/* Given a node in the AST, it replaces all function calls with the corresponding expression from the fct2Var mapping. Since we traverse in order of function evaluation, all nodes that are lower in the subtree are supposed to have been mapped, since they have already appeared in the list. Also, we only replace the shallowest level of function calls in the surrent subtree, since we assume that replaceFunctionCallsInExpression has already been called for each of the subtrees rooted at the shallowest function calls lower than the current node: E.g.: f(g(h(i))) + 5 has the AST: + / \ fc1 5 / \ f fc2 / \ g fc3 / \ h i where fc? represents an SgFunctionCallExpression. Order of function evaluation is h(i), g(_), f(_). Calling 'replaceFunctionCallsInExpression' on '+' will generate temp_var + 5 but calling the same function on 'fc2' will generate f(temp_var) + 5 */ void FunctionCallNormalization::replaceFunctionCallsInExpression( SgNode *root, map<SgFunctionCallExp *, SgExpression *> fct2Var ) { if ( !root ) return; if ( NodeQuery::querySubTree( root, V_SgFunctionCallExp ).size() > 0 ) { list<SgNode *> toVisit; toVisit.push_back( root ); while ( !toVisit.empty() ) { SgNode *crt = toVisit.front(); // will visit every node above an function call exp, but not below // also, we will replace function call expressions found if ( !isSgFunctionCallExp( crt ) ) { vector<SgNode *> succ = ( crt )->get_traversalSuccessorContainer(); for ( vector<SgNode *>::iterator succIt = succ.begin(); succIt != succ.end(); succIt++ ) if ( isSgNode ( *succIt ) ) toVisit.push_back( *succIt ); } else { SgFunctionCallExp *call = isSgFunctionCallExp( crt ); ROSE_ASSERT ( call ); map<SgFunctionCallExp *, SgExpression *>::iterator mapIter; mapIter = fct2Var.find( call ); if ( mapIter == fct2Var.end() ) cout << "NOT FOUND " << call->unparseToString() << "\t" << call << "\n"; // a mapping for function call exps in the subtree must already exist ( postorder traversal ) ROSE_ASSERT ( mapIter != fct2Var.end() && mapIter->second ); // duplicate the variable SgTreeCopy treeCopy; SgExpression *scnd = mapIter->second; ROSE_ASSERT ( isSgExpression( scnd ) ); SgExpression *newVar = isSgExpression( scnd->copy( treeCopy ) ); ROSE_ASSERT ( newVar ); SgExpression *parent = isSgExpression( call->get_parent() ); ROSE_ASSERT ( parent ); // replace the node in the AST newVar->set_parent( parent ); int k = parent->replace_expression( call, newVar ); ROSE_ASSERT ( k == 1 ); delete call; } toVisit.pop_front(); } } }