[flang] Don't crash on some bogus expressions

Recover more gracefully from user errors in expressions.

Differential Revision: https://reviews.llvm.org/D104326
This commit is contained in:
peter klausler 2021-06-15 15:14:16 -07:00
parent 560636e549
commit 3061334e0d
3 changed files with 18 additions and 3 deletions

View file

@ -174,7 +174,8 @@ private:
// Wraps a data reference in a typed Designator<>, and a procedure
// or procedure pointer reference in a ProcedureDesignator.
MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) {
const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
const Symbol &last{ref.GetLastSymbol()};
const Symbol &symbol{last.GetUltimate()};
if (semantics::IsProcedure(symbol)) {
if (auto *component{std::get_if<Component>(&ref.u)}) {
return Expr<SomeType>{ProcedureDesignator{std::move(*component)}};
@ -193,8 +194,17 @@ MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) {
symbol.name());
}
return std::nullopt;
} else if (MaybeExpr result{AsGenericExpr(std::move(ref))}) {
return result;
} else {
return AsGenericExpr(std::move(ref));
if (!context_.HasError(last) && !context_.HasError(symbol)) {
AttachDeclaration(
Say("'%s' is not an object that can appear in an expression"_err_en_US,
last.name()),
symbol);
context_.SetError(last);
}
return std::nullopt;
}
}

View file

@ -3361,7 +3361,8 @@ void DeclarationVisitor::EndDecl() {
}
bool DeclarationVisitor::CheckUseError(const parser::Name &name) {
const auto *details{name.symbol->detailsIf<UseErrorDetails>()};
const auto *details{
name.symbol ? name.symbol->detailsIf<UseErrorDetails>() : nullptr};
if (!details) {
return false;
}
@ -3370,6 +3371,7 @@ bool DeclarationVisitor::CheckUseError(const parser::Name &name) {
msg.Attach(location, "'%s' was use-associated from module '%s'"_en_US,
name.source, module->GetName().value());
}
context().SetError(*name.symbol);
return true;
}
@ -5247,6 +5249,7 @@ void ConstructVisitor::ResolveIndexName(
!prevRoot.has<EntityDetails>()) {
Say2(name, "Index name '%s' conflicts with existing identifier"_err_en_US,
*prev, "Previous declaration of '%s'"_en_US);
context().SetError(symbol);
return;
} else {
if (const auto *type{prevRoot.GetType()}) {

View file

@ -220,9 +220,11 @@ contains
SELECT RANK(ptr=>x)
RANK (3)
PRINT *, "PRINT RANK 3"
!ERROR: 'ptr' is not an object that can appear in an expression
j = INT(0, KIND=MERGE(KIND(0), -1, RANK(ptr) == 0))
RANK (1)
PRINT *, "PRINT RANK 1"
!ERROR: 'ptr' is not an object that can appear in an expression
j = INT(0, KIND=MERGE(KIND(0), -1, RANK(ptr) == 1))
END SELECT
end subroutine