summaryrefslogtreecommitdiff
path: root/flang/lib/Semantics/expression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Semantics/expression.cpp')
-rw-r--r--flang/lib/Semantics/expression.cpp54
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);
}