void StringIntegerAssignmentCheck::check(
    const MatchFinder::MatchResult &Result) {
  const auto *Argument = Result.Nodes.getNodeAs<Expr>("expr");
  SourceLocation Loc = Argument->getLocStart();

  auto Diag =
      diag(Loc, "an integer is interpreted as a character code when assigning "
                "it to a string; if this is intended, cast the integer to the "
                "appropriate character type; if you want a string "
                "representation, use the appropriate conversion facility");

  if (Loc.isMacroID())
    return;

  auto CharType = *Result.Nodes.getNodeAs<QualType>("type");
  bool IsWideCharType = CharType->isWideCharType();
  if (!CharType->isCharType() && !IsWideCharType)
    return;
  bool IsOneDigit = false;
  bool IsLiteral = false;
  if (const auto *Literal = dyn_cast<IntegerLiteral>(Argument)) {
    IsOneDigit = Literal->getValue().getLimitedValue() < 10;
    IsLiteral = true;
  }

  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
      Argument->getLocEnd(), 0, *Result.SourceManager,
      Result.Context->getLangOpts());
  if (IsOneDigit) {
    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L'" : "'")
         << FixItHint::CreateInsertion(EndLoc, "'");
    return;
  }
  if (IsLiteral) {
    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L\"" : "\"")
         << FixItHint::CreateInsertion(EndLoc, "\"");
    return;
  }

  if (getLangOpts().CPlusPlus11) {
    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "std::to_wstring("
                                                           : "std::to_string(")
         << FixItHint::CreateInsertion(EndLoc, ")");
  }
}
Esempio n. 2
0
void
UnparseFortran_type::unparseArrayType(SgType* type, SgUnparse_Info& info, bool printDim)
{
    // Examples:
    //   real, dimension(10, 10) :: A1, A2
    //   real, dimension(:) :: B1
    //   character(len=*) :: s1
#if 0
    curprint ("\n! Inside of UnparserFort::unparseArrayType \n");
#endif

    SgArrayType* array_type = isSgArrayType(type);
    ROSE_ASSERT(array_type != NULL);

    // I think that supressStrippedTypeName() and SkipBaseType() are redundant...
    if (info.supressStrippedTypeName() == false)
    {
        // DQ (1/16/2011): We only want to output the name of the stripped type once!
        SgType* stripType = array_type->stripType();
        unparseType(stripType, info);
        info.set_supressStrippedTypeName();
    }

    // DQ (8/5/2010): It is an error to treat an array of char as a string (see test2010_16.f90).
#if 0
    // dimension information
    SgExprListExp* dim = array_type->get_dim_info();

    // if (isCharType(array_type->get_base_type()))
    // if (false && isCharType(array_type->get_base_type()))
    if (isCharType(array_type->get_base_type()))
    {
        // a character type: must be treated specially
        ROSE_ASSERT(array_type->get_rank() == 1);
        curprint("(len=");

        SgExpressionPtrList::iterator it = dim->get_expressions().begin();
        if (it != dim->get_expressions().end())
        {
            SgExpression* expr = *it;
            if (expr->variantT() == V_SgSubscriptExpression)
            {
                // this is a subscript expression but all we want to unparse is the length
                // of the string, which should be the upper bound of the subscript expression
                SgSubscriptExpression* sub_expr = isSgSubscriptExpression(expr);
                ROSE_ASSERT(sub_expr != NULL);

                ROSE_ASSERT(unp != NULL);
                ROSE_ASSERT(unp->u_fortran_locatedNode != NULL);
                unp->u_fortran_locatedNode->unparseExpression(sub_expr->get_upperBound(), info);
            }
            else
            {
                // unparse the entire expression
                ROSE_ASSERT(unp != NULL);
                ROSE_ASSERT(unp->u_fortran_locatedNode != NULL);
                unp->u_fortran_locatedNode->unparseExpression(*it, info);
            }
        }
        else
        {
            curprint("*");
        }
        curprint(")");
    }
    else
    {
        // a non-character type

        // explicit-shape (explicit rank and bounds/extents)
        // assumed-shape (explicit rank; unspecified bounds/extents)
        // deferred-shape (explicit rank; unspecified bounds/extents)
        // assumed-size (explicit ranks, explicit bounds/extents except last dim)
        ROSE_ASSERT(array_type->get_rank() >= 1);
        curprint(", DIMENSION");

        ROSE_ASSERT(unp != NULL);
        ROSE_ASSERT(unp->u_fortran_locatedNode != NULL);
        // unp->u_fortran_locatedNode->unparseExprList(dim, info); // adds parens
        // unp->u_fortran_locatedNode->UnparseLanguageIndependentConstructs::unparseExprList(dim, info); // adds parens

        // curprint("(");
        // curprint( StringUtility::numberToString(array_type->get_rank()) );
        // curprint(")");

        // unp->u_fortran_locatedNode->unparseExpression(array_type->get_dim_info(),info);
        unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* output parens */ true);
    }
#else

    if (printDim)
    {
        ROSE_ASSERT(array_type->get_rank() >= 1);
        curprint(array_type->get_isCoArray()? ", CODIMENSION": ", DIMENSION");

        ROSE_ASSERT(unp != NULL);
        ROSE_ASSERT(unp->u_fortran_locatedNode != NULL);

        if (array_type->get_isCoArray())
        {   // print codimension info
            curprint("[");
            unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* do not output parens */ false);
            curprint("]");
        }
        else  // print dimension info
            unp->u_fortran_locatedNode->unparseExprList(array_type->get_dim_info(),info,/* output parens */ true);
    }

    // DQ (1/16/2011): Plus unparse the base type...(unless it will just output the stripped types name).
    if (array_type->get_base_type()->containsInternalTypes() == true)
    {
        unparseType(array_type->get_base_type(), info, printDim);
    }
#endif

#if 0
    curprint ("\n! Leaving UnparserFort::unparseArrayType \n");
#endif
}
Esempio n. 3
0
bool isSimpleType(const Type* t) { return isIntType(t) || isCharType(t) || isPointer(t) || isReference(t); }
Esempio n. 4
0
CGResult sst::AssignOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)
{
	cs->pushLoc(this);
	defer(cs->popLoc());

	auto lr = this->left->codegen(cs).value;
	auto lt = lr->getType();

	if(!lr->islorclvalue())
	{
		SpanError::make(SimpleError::make(this->loc, "Cannot assign to non-lvalue (most likely a temporary) expression"))
			->add(util::ESpan(this->left->loc, "here"))
			->postAndQuit();
	}
	else if(lr->isclvalue())
	{
		SpanError::make(SimpleError::make(this->loc, "Cannot assign to immutable expression"))
			->add(util::ESpan(this->left->loc, "here"))
			->postAndQuit();
	}


	// okay, i guess
	auto rr = this->right->codegen(cs, lt).value;
	auto rt = rr->getType();

	if(this->op != Operator::Assign)
	{
		// ok it's a compound assignment
		// auto [ newl, newr ] = cs->autoCastValueTypes(lr, rr);
		auto nonass = Operator::getNonAssignmentVersion(this->op);

		// some things -- if we're doing +=, and the types are supported, then just call the actual
		// append function, instead of doing the + first then assigning it.

		if(nonass == Operator::Plus)
		{
			if(lt->isDynamicArrayType() && lt == rt)
			{
				// right then.
				if(!lr->islvalue())
					error(this, "Cannot append to an r-value array");

				auto appendf = cgn::glue::array::getAppendFunction(cs, lt->toDynamicArrayType());

				//? are there any ramifications for these actions for ref-counted things?
				auto res = cs->irb.Call(appendf, lr, cs->irb.CreateSliceFromSAA(rr, false));

				cs->irb.Store(res, lr);
				return CGResult(0);
			}
			else if(lt->isDynamicArrayType() && lt->getArrayElementType() == rt)
			{
				// right then.
				if(!lr->islvalue())
					error(this, "Cannot append to an r-value array");

				auto appendf = cgn::glue::array::getElementAppendFunction(cs, lt->toDynamicArrayType());

				//? are there any ramifications for these actions for ref-counted things?
				auto res = cs->irb.Call(appendf, lr, rr);

				cs->irb.Store(res, lr);
				return CGResult(0);
			}
			else if(lt->isStringType() && lt == rt)
			{
				// right then.
				if(!lr->islvalue())
					error(this, "Cannot append to an r-value array");

				auto appendf = cgn::glue::string::getAppendFunction(cs);

				//? are there any ramifications for these actions for ref-counted things?
				auto res = cs->irb.Call(appendf, lr, cs->irb.CreateSliceFromSAA(rr, true));

				cs->irb.Store(res, lr);
				return CGResult(0);
			}
			else if(lt->isStringType() && rt->isCharType())
			{
				// right then.
				if(!lr->islvalue())
					error(this, "Cannot append to an r-value string");

				auto appendf = cgn::glue::string::getCharAppendFunction(cs);

				//? are there any ramifications for these actions for ref-counted things?
				auto res = cs->irb.Call(appendf, lr, rr);

				cs->irb.Store(res, lr);
				return CGResult(0);
			}
		}


		// do the op first
		auto res = cs->performBinaryOperation(this->loc, { this->left->loc, lr }, { this->right->loc, rr }, nonass);

		// assign the res to the thing
		rr = res.value;
	}

	rr = cs->oneWayAutocast(rr, lt);

	if(rr == 0)
	{
		error(this, "Invalid assignment from value of type '%s' to expected type '%s'", rr->getType(), lt);
	}

	// ok then
	if(lt != rr->getType())
		error(this, "What? left = %s, right = %s", lt, rr->getType());

	cs->autoAssignRefCountedValue(lr, rr, /* isInitial: */ false, /* performStore: */ true);
	return CGResult(0);
}