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, ")"); } }
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 }
bool isSimpleType(const Type* t) { return isIntType(t) || isCharType(t) || isPointer(t) || isReference(t); }
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); }