/** * Const-qualify immutable objects * * \todo count assignments, if only one, report violation */ bool DCL00_C( const SgNode *node ) { const SgInitializedName *varName = isSgInitializedName(node); if (!varName) return false; /** * Ignore variables generated by macros */ if ((varName->get_name().getString().substr(0,2) == "__") || isCompilerGeneratedNode(node)) return false; /** * Ignore global variables */ if (isGlobalVar(varName)) return false; /** * Ignore variables that are already const, are function pointers, or are * declared inside of a struct, enum, or as an argument to a function */ SgType *varType = varName->get_type(); if (isConstType(varType) || isConstType(varType->dereference()) || isConstType(varType->dereference()->dereference()) || isSgFunctionType(varType) || isSgClassType(varType) || findParentOfType(varName, SgCtorInitializerList) || findParentOfType(varName, SgEnumDeclaration) || findParentOfType(varName, SgClassDeclaration)) return false; /** * DCL13-C is a subset of this rule, figure out which rule we are dealing * with here */ std::string ruleStr; std::string errStr; if (findParentOfType(varName, SgFunctionParameterList)) { /** ignore function prototypes, just worry about the definitions */ const SgFunctionDeclaration *fnDecl = findParentOfType(varName, SgFunctionDeclaration); /** * Disabling assertion due to C++ code */ if (!fnDecl) return false; // assert(fnDecl); if (!fnDecl->get_definition()) return false; if (isSgPointerType(varName->get_type()) || isSgArrayType(varName->get_type())) { ruleStr = "DCL13-C"; errStr = "Declare function parameters that are pointers to values not changed by the function as const: "; } else { return false; } } else { ruleStr = "DCL00-C"; errStr = "Const-qualify immutable objects: "; } /** * Ignore global variables or variables declared as extern */ const SgScopeStatement *varScope = varName->get_scope(); if (isSgGlobal(varScope) || isExternVar(varName)) return false; FOREACH_SUBNODE(varScope, nodes, i, V_SgVarRefExp) { const SgVarRefExp *iVar = isSgVarRefExp(*i); assert(iVar); if (getRefDecl(iVar) != varName) continue; const SgNode *parent = iVar->get_parent(); while(isSgCastExp(parent)) { parent = parent->get_parent(); } assert(parent); /** * If the variable is written to or it's address is taken, we can no * longer be sure it should be const, if it's a struct and gets * dereferenced, who knows what's getting written there :/ */ if (varWrittenTo(iVar) || isSgArrowExp(parent) || findParentOfType(iVar, SgAddressOfOp)) return false; /** * If the variable is a pointer or array, and we pass it to a function * or as an argument to pointer arithmetic, or assign it's value * somewhere, we can longer be sure it should be const */ if ((isSgPointerType(varType) || isSgArrayType(varType)) && (findParentOfType(iVar, SgFunctionCallExp) || isSgAddOp(parent) || isSgSubtractOp(parent) || isSgAssignOp(parent) || isSgPntrArrRefExp(parent) || isSgPointerDerefExp(parent) || isSgAssignInitializer(parent))) return false; } const std::string msg = errStr + varName->get_name().getString(); print_error(node, ruleStr.c_str(), msg.c_str(), true); return true; }
void CompassAnalyses::VariableNameEqualsDatabaseName::Traversal:: visit(SgNode* node) { if( isSgAssignInitializer(node) != NULL ) assignExp = node; if( isSgAssignOp(node) != NULL ) assignExp = node; SgFunctionCallExp* funcCall = isSgFunctionCallExp(node); // See if we have a dot expression or arrow expression which // accesses the desired member function in the class we are looking for. if ( funcCall != NULL ) { SgExpression* funcExp = funcCall->get_function(); if ( ( isSgDotExp(funcExp) != NULL ) | ( isSgArrowExp(funcExp) != NULL ) ) { SgBinaryOp* binOp = isSgBinaryOp(funcExp); SgExpression* rhsOp = binOp->get_rhs_operand(); // SgExpression* lhsOp = binOp->get_lhs_operand(); if ( SgMemberFunctionRefExp* funcRef = isSgMemberFunctionRefExp(rhsOp) ) { // std::cout << "c1\n" ; SgMemberFunctionSymbol* funcSymbol = funcRef->get_symbol(); ROSE_ASSERT(funcSymbol->get_declaration() != NULL); // DQ (1/16/2008): Note that the defining declaration need not exist (see test2001_11.C) // ROSE_ASSERT(funcSymbol->get_declaration()->get_definingDeclaration() != NULL); if (funcSymbol->get_declaration()->get_definingDeclaration() != NULL) { SgMemberFunctionDeclaration* funcDecl = isSgMemberFunctionDeclaration(funcSymbol->get_declaration()->get_definingDeclaration()); ROSE_ASSERT( funcDecl != NULL ); SgClassDefinition* clDef = isSgClassDefinition(funcDecl->get_scope()); SgClassDeclaration* clDecl = isSgClassDeclaration(clDef->get_declaration()); // SgClassDeclaration* clDecl = funcDecl->get_associatedClassDeclaration(); ROSE_ASSERT( clDecl != NULL ); std::string className = clDecl->get_name().getString(); ROSE_ASSERT(funcDecl != NULL); std::string functionName = funcDecl->get_name().getString(); // If the class is the class we are looking for see if the member function // access is to the member function we are interested in. // std::cout << "className = " << className << std::endl; // std::cout << "functionName = " << functionName << std::endl; if ( (className == classToLookFor) && ( functionName == memberFunctionToLookFor ) ) { SgExprListExp* actualArgs = funcCall->get_args(); SgExpressionPtrList& actualExpArgs = actualArgs->get_expressions (); ROSE_ASSERT(actualExpArgs.size() == 1); Rose_STL_Container<SgNode*> nodeLst = NodeQuery::querySubTree(*actualExpArgs.begin(), V_SgStringVal); ROSE_ASSERT( nodeLst.size() > 0); SgStringVal* actualArg = isSgStringVal(*nodeLst.begin()); ROSE_ASSERT(actualArg != NULL); std::string stringArg = actualArg->get_value(); std::cout << "arg:" << stringArg << std::endl; std::string varName; // SgInitializedName* initName = NULL; if ( SgAssignInitializer* assignInit = isSgAssignInitializer(assignExp) ) { SgInitializedName* initName = isSgInitializedName(assignInit->get_parent()); ROSE_ASSERT(initName != NULL); varName = initName->get_name().getString(); } else { if ( SgAssignOp* assignOp = isSgAssignOp(assignExp) ) { SgExpression* lhsOp = assignOp->get_lhs_operand(); SgVarRefExp* varRef = isSgVarRefExp(lhsOp); ROSE_ASSERT(varRef!=NULL); SgVariableSymbol* varSymbol = varRef->get_symbol(); ROSE_ASSERT(varSymbol != NULL); SgInitializedName* initName = varSymbol->get_declaration(); varName = initName->get_name().getString(); } } if (varName != "") { // we are only interested in the part of the argument after the last ":" // Database scopes in ALE3D are separated by ":" size_t posCol = stringArg.find_last_of(':'); if (posCol != std::string::npos) stringArg = stringArg.substr(posCol+1); //Find violations to the rule if ( stringArg != varName) { output->addOutput(new CheckerOutput(assignExp)); std::cout << "violation" << varName << std::endl; } else { std::cout << "non=violation" << varName << std::endl; } } } } } } } } // End of the visit function.
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; }