diff options
Diffstat (limited to 'flang/lib/Semantics/expression.cpp')
| -rw-r--r-- | flang/lib/Semantics/expression.cpp | 54 |
1 files changed, 34 insertions, 20 deletions
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 92dbe0e5da11..d022378ce145 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -828,7 +828,7 @@ MaybeExpr ExpressionAnalyzer::Analyze( template <typename TYPE> Constant<TYPE> ReadRealLiteral( - parser::CharBlock source, FoldingContext &context) { + parser::CharBlock source, FoldingContext &context, bool isDefaultKind) { const char *p{source.begin()}; auto valWithFlags{ Scalar<TYPE>::Read(p, context.targetCharacteristics().roundingMode())}; @@ -838,19 +838,24 @@ Constant<TYPE> ReadRealLiteral( if (context.targetCharacteristics().areSubnormalsFlushedToZero()) { value = value.FlushSubnormalToZero(); } - return {value}; + typename Constant<TYPE>::Result resultInfo; + resultInfo.set_isFromInexactLiteralConversion( + isDefaultKind && valWithFlags.flags.test(RealFlag::Inexact)); + return {value, resultInfo}; } struct RealTypeVisitor { using Result = std::optional<Expr<SomeReal>>; using Types = RealTypes; - RealTypeVisitor(int k, parser::CharBlock lit, FoldingContext &ctx) - : kind{k}, literal{lit}, context{ctx} {} + RealTypeVisitor( + int k, parser::CharBlock lit, FoldingContext &ctx, bool isDeftKind) + : kind{k}, literal{lit}, context{ctx}, isDefaultKind{isDeftKind} {} template <typename T> Result Test() { if (kind == T::kind) { - return {AsCategoryExpr(ReadRealLiteral<T>(literal, context))}; + return { + AsCategoryExpr(ReadRealLiteral<T>(literal, context, isDefaultKind))}; } return std::nullopt; } @@ -858,6 +863,7 @@ struct RealTypeVisitor { int kind; parser::CharBlock literal; FoldingContext &context; + bool isDefaultKind; }; // Reads a real literal constant and encodes it with the right kind. @@ -909,8 +915,9 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) { "Explicit kind parameter together with non-'E' exponent letter is not standard"_port_en_US); } } - auto result{common::SearchTypes( - RealTypeVisitor{kind, x.real.source, GetFoldingContext()})}; + bool isDefaultKind{!x.kind && letterKind.value_or('e') == 'e'}; + auto result{common::SearchTypes(RealTypeVisitor{ + kind, x.real.source, GetFoldingContext(), isDefaultKind})}; if (!result) { // C717 Say("Unsupported REAL(KIND=%d)"_err_en_US, kind); } @@ -1841,8 +1848,7 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) { if (*thisLen != *constantLength_ && !(messageDisplayedSet_ & 1)) { exprAnalyzer_.Warn( common::LanguageFeature::DistinctArrayConstructorLengths, - "Character literal in array constructor without explicit " - "type has different length than earlier elements"_port_en_US); + "Character literal in array constructor without explicit type has different length than earlier elements"_port_en_US); messageDisplayedSet_ |= 1; } if (*thisLen > *constantLength_) { @@ -1862,17 +1868,17 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) { } else { if (!(messageDisplayedSet_ & 2)) { exprAnalyzer_.Say( - "Values in array constructor must have the same declared type " - "when no explicit type appears"_err_en_US); // C7110 + "Values in array constructor must have the same declared type when no explicit type appears"_err_en_US); // C7110 messageDisplayedSet_ |= 2; } } } else { + CheckRealWidening(*x, *type_, exprAnalyzer_.GetFoldingContext()); if (auto cast{ConvertToType(*type_, std::move(*x))}) { values_.Push(std::move(*cast)); } else if (!(messageDisplayedSet_ & 4)) { - exprAnalyzer_.Say("Value in array constructor of type '%s' could not " - "be converted to the type of the array '%s'"_err_en_US, + exprAnalyzer_.Say( + "Value in array constructor of type '%s' could not be converted to the type of the array '%s'"_err_en_US, x->GetType()->AsFortran(), type_->AsFortran()); // C7111, C7112 messageDisplayedSet_ |= 4; } @@ -2065,8 +2071,9 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) { // Check if implicit conversion of expr to the symbol type is legal (if needed), // and make it explicit if requested. -static MaybeExpr ImplicitConvertTo(const semantics::Symbol &sym, - Expr<SomeType> &&expr, bool keepConvertImplicit) { +static MaybeExpr ImplicitConvertTo(const Symbol &sym, Expr<SomeType> &&expr, + bool keepConvertImplicit, FoldingContext &foldingContext) { + CheckRealWidening(expr, DynamicType::From(sym), foldingContext); if (!keepConvertImplicit) { return ConvertToType(sym, std::move(expr)); } else { @@ -2293,10 +2300,12 @@ MaybeExpr ExpressionAnalyzer::CheckStructureConstructor( // convert would cause a segfault. Lowering will deal with // conditionally converting and preserving the lower bounds in this // case. - if (MaybeExpr converted{ImplicitConvertTo( - *symbol, std::move(value), IsAllocatable(*symbol))}) { - if (auto componentShape{GetShape(GetFoldingContext(), *symbol)}) { - if (auto valueShape{GetShape(GetFoldingContext(), *converted)}) { + FoldingContext &foldingContext{GetFoldingContext()}; + if (MaybeExpr converted{ImplicitConvertTo(*symbol, std::move(value), + /*keepConvertImplicit=*/IsAllocatable(*symbol), + foldingContext)}) { + if (auto componentShape{GetShape(foldingContext, *symbol)}) { + if (auto valueShape{GetShape(foldingContext, *converted)}) { if (GetRank(*componentShape) == 0 && GetRank(*valueShape) > 0) { AttachDeclaration( Say(exprSource, @@ -2310,7 +2319,7 @@ MaybeExpr ExpressionAnalyzer::CheckStructureConstructor( if (checked && *checked && GetRank(*componentShape) > 0 && GetRank(*valueShape) == 0 && (IsDeferredShape(*symbol) || - !IsExpandableScalar(*converted, GetFoldingContext(), + !IsExpandableScalar(*converted, foldingContext, *componentShape, true /*admit PURE call*/))) { AttachDeclaration( Say(exprSource, @@ -4827,6 +4836,11 @@ std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() { // conversion in this case. if (lhsType) { if (rhsType) { + FoldingContext &foldingContext{context_.GetFoldingContext()}; + auto restorer{foldingContext.messages().SetLocation( + actuals_.at(1).value().sourceLocation().value_or( + foldingContext.messages().at()))}; + CheckRealWidening(rhs, lhsType, foldingContext); if (!IsAllocatableDesignator(lhs) || context_.inWhereBody()) { AddAssignmentConversion(*lhsType, *rhsType); } |
