Exemplo n.º 1
0
/*!
 *  \brief Creates an assignment to "pack" a local variable back into
 *  an outlined-function parameter that has been passed as a pointer
 *  value.
 *
 *  This routine takes the original "unpack" definition, of the form
 *
 *    TYPE local_unpack_var = *outlined_func_arg;
 *    int i = *(int *)(__out_argv[1]); // parameter wrapping case
 *
 *  and creates the "re-pack" assignment expression,
 *
 *    *outlined_func_arg = local_unpack_var
 *    *(int *)(__out_argv[1]) =i; // parameter wrapping case
 *
 *  C++ variables of reference types do not need this step.
 */
static
SgAssignOp *
createPackExpr (SgInitializedName* local_unpack_def)
{
  if (!Outliner::temp_variable)
  {
    if (is_C_language()) //skip for pointer dereferencing used in C language
      return NULL;
  }
  // reference types do not need copy the value back in any cases
  if (isSgReferenceType (local_unpack_def->get_type ()))  
    return NULL;

  if (local_unpack_def
      && !isReadOnlyType (local_unpack_def->get_type ()))
//      && !isSgReferenceType (local_unpack_def->get_type ()))
    {
      SgName local_var_name (local_unpack_def->get_name ());

      SgAssignInitializer* local_var_init =
        isSgAssignInitializer (local_unpack_def->get_initializer ());
      ROSE_ASSERT (local_var_init);

      // Create the LHS, which derefs the function argument, by
      // copying the original dereference expression.
      // 
      SgPointerDerefExp* param_deref_unpack =
        isSgPointerDerefExp (local_var_init->get_operand_i ());
      if (param_deref_unpack == NULL)  
      {
        cout<<"packing statement is:"<<local_unpack_def->get_declaration()->unparseToString()<<endl;
        cout<<"local unpacking stmt's initializer's operand has non-pointer deferencing type:"<<local_var_init->get_operand_i ()->class_name()<<endl;
        ROSE_ASSERT (param_deref_unpack);
      }

      SgPointerDerefExp* param_deref_pack = isSgPointerDerefExp (ASTtools::deepCopy (param_deref_unpack));
      ROSE_ASSERT (param_deref_pack);
              
      // Create the RHS, which references the local variable.
      SgScopeStatement* scope = local_unpack_def->get_scope ();
      ROSE_ASSERT (scope);
      SgVariableSymbol* local_var_sym =
        scope->lookup_var_symbol (local_var_name);
      ROSE_ASSERT (local_var_sym);
      SgVarRefExp* local_var_ref = SageBuilder::buildVarRefExp (local_var_sym);
      ROSE_ASSERT (local_var_ref);

      // Assemble the final assignment expression.
      return SageBuilder::buildAssignOp (param_deref_pack, local_var_ref);
    }
  return 0;
}
bool isMethodCall(SgFunctionCallExp *functionCall, bool &isDotExp)
{
  ROSE_ASSERT(functionCall != NULL);

  SgExpression *expression = functionCall->get_function();
  ROSE_ASSERT(expression != NULL);

  bool isMethod = false;
  isDotExp = false;

  switch(expression->variantT()) {
  case V_SgDotExp:
    {
      isMethod = true;

      SgDotExp *dotExp = isSgDotExp(expression);
      ROSE_ASSERT(dotExp != NULL);
	  
      SgExpression *lhs = dotExp->get_lhs_operand();
      ROSE_ASSERT(lhs != NULL);
	  
      SgPointerDerefExp *pointerDerefExp =
	isSgPointerDerefExp(lhs);
	  
      if ( pointerDerefExp != NULL ) {
	;
      } else {
	isDotExp = true;
      }

      break;
    }
  case V_SgMemberFunctionRefExp:
  case V_SgArrowExp:
    {
      isMethod = true;
      break;
    }
  case V_SgFunctionRefExp:
  case V_SgPointerDerefExp:
    {
      isMethod = false;
      break;
    }
  default:
    {
      std::cerr << "Was not expecting an " << expression->sage_class_name() << std::endl;
      std::cerr << "in a function call." << std::endl;
      ROSE_ABORT();
    }
  }

  return isMethod;
}
Exemplo n.º 3
0
 // on other nodes
 lrRecord (lrRecord &parent, SgNode* n)
 {
         SgBinaryOp* binOp;
         SgUnaryOp* unOp;
         SgFunctionCallExp* funcCall;
         //SgPntrArrRefExp* arrRef;
         char typeStr[100];
         
         // if this node is on the read, write or read-write side of an assignment operation, set its access appropriately
         if(parent.readSubtree == n)
                 access = readAccess;
         else if(n == parent.writeSubtree)
                 access = writeAccess;
         else if(n == parent.rwSubtree)
                 access = rwAccess;
         else
                 access = parent.access;
         
         if((binOp = isSgBinaryOp(n)))
         {                       
                 // writeSubtree = readSubtree
                 if(isSgAssignOp(binOp))
                 {
                         writeSubtree = binOp->get_lhs_operand();
                         readSubtree = binOp->get_rhs_operand();
                         rwSubtree = (void*)NULL;
                         strcpy(typeStr, "SgAssignOp");
                 }
                 // rwSubtree op= readSubtree
                 else if(isSgCompoundAssignOp(binOp))
                 {
                         rwSubtree = binOp->get_lhs_operand();
                         readSubtree = binOp->get_rhs_operand();
                         writeSubtree = (void*)NULL;
                         strcpy(typeStr, "Sg*AssignOp");
                 }
                 else if(isSgPntrArrRefExp(binOp))
                 {
                         // all the references involved in an array reference, whether they are used to compute the array name
                         // or used in the argument, are read-only
                         writeSubtree = (void*)NULL;
                         readSubtree = (void*)NULL;
                         readSubtree.wildMatch();
                         rwSubtree = (void*)NULL;
                         strcpy(typeStr, "SgPntrArrRefExp");
                 }
                 else 
                 {
                         readSubtree = (void*)NULL;
                         writeSubtree = (void*)NULL;
                         rwSubtree = (void*)NULL;
                         strcpy(typeStr, "???");
                 }
                 
                 //printf("SgBinaryNode 0x%x type %s access=%d: %s\n", binOp, typeStr, access, binOp->unparseToString().c_str());        
         }
         else if((unOp = isSgUnaryOp(n)))
         {
                 // unary update operations have only one operand, which is read-write
                 // writeSubtree
                 if(isSgMinusMinusOp(unOp) ||
                         isSgPlusPlusOp(unOp))
                 {
                         writeSubtree = (void*)NULL;
                         readSubtree = (void*)NULL;
                         rwSubtree = unOp->get_operand();
                         strcpy(typeStr, "Sg**Op");
                 }
                 // dereference operations have a read-only operand
                 else if(isSgPointerDerefExp(unOp))
                 {
                         writeSubtree = (void*)NULL;
                         readSubtree = unOp->get_operand();
                         rwSubtree = (void*)NULL;
                         strcpy(typeStr, "isSgPointerDerefExp");
                 }
                 else 
                 {
                         readSubtree = (void*)NULL;
                         writeSubtree = (void*)NULL;
                         rwSubtree = (void*)NULL;
                         strcpy(typeStr, "???");
                 }
                 //printf("SgUnaryNode 0x%x %s access=%d: %s\n", unOp, typeStr, access, unOp->unparseToString().c_str());
         }
         else if((funcCall = isSgFunctionCallExp(n)))
         {
                 // all the references involved in a function call, whether they are used to compute the function pointer
                 // or used in the argument, are read-only
                 writeSubtree = (void*)NULL;
                 readSubtree = (void*)NULL;
                 readSubtree.wildMatch();
                 rwSubtree = (void*)NULL;
                 //printf("SgFunctionCall 0x%x access=%d: %s\n", funcCall, access, funcCall->unparseToString().c_str());
         }
         // else, if this is neither a binary, nor unary operation node
         else
         {
                 // leave subtree fields of this record as NULL
                 readSubtree = (void*)NULL;
                 writeSubtree = (void*)NULL;
                 rwSubtree = (void*)NULL;
                 
                 //printf("SgNode 0x%x access=%d: %s\n", n, access, n->unparseToString().c_str());
         }
 }
Exemplo n.º 4
0
Arquivo: DCL.C Projeto: 8l/rose
/**
 * 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;
}