[flang-commits] [flang] 2d528fd - [flang] Warn about defined operator with too few/many dummy arguments
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Sat Jan 28 10:15:47 PST 2023
Author: Peter Klausler
Date: 2023-01-28T10:15:35-08:00
New Revision: 2d528fd7d7f6a84e50edb1a9ea3822b4edeb3e01
URL: https://github.com/llvm/llvm-project/commit/2d528fd7d7f6a84e50edb1a9ea3822b4edeb3e01
DIFF: https://github.com/llvm/llvm-project/commit/2d528fd7d7f6a84e50edb1a9ea3822b4edeb3e01.diff
LOG: [flang] Warn about defined operator with too few/many dummy arguments
A function in a defined operator generic interface will syntactically
have one or two arguments. If a defined operator includes a specific
function with 0 or more than 2 dummy arguments, there's no way that it
could be invoked by way of the interface. Emit a warning.
Differential Revision: https://reviews.llvm.org/D142762
Added:
flang/test/Semantics/generic04.f90
Modified:
flang/include/flang/Parser/message.h
flang/lib/Semantics/check-declarations.cpp
flang/lib/Semantics/resolve-names.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index 0659e04d51df0..64d52b2447656 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -59,7 +59,7 @@ class MessageFixedText {
severity_ = severity;
return *this;
}
- bool isFatal() const {
+ bool IsFatal() const {
return severity_ == Severity::Error || severity_ == Severity::Todo;
}
@@ -111,7 +111,7 @@ class MessageFormattedText {
MessageFormattedText &operator=(const MessageFormattedText &) = default;
MessageFormattedText &operator=(MessageFormattedText &&) = default;
const std::string &string() const { return string_; }
- bool isFatal() const {
+ bool IsFatal() const {
return severity_ == Severity::Error || severity_ == Severity::Todo;
}
Severity severity() const { return severity_; }
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 8b072999f82db..f849bcd5ed6d2 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -1451,9 +1451,12 @@ bool CheckHelper::CheckDefinedOperator(SourceName opName, GenericKind kind,
} else {
return true; // OK
}
+ bool isFatal{msg->IsFatal()};
SayWithDeclaration(
specific, std::move(*msg), MakeOpName(opName), specific.name());
- context_.SetError(specific);
+ if (isFatal) {
+ context_.SetError(specific);
+ }
return false;
}
@@ -1462,6 +1465,9 @@ bool CheckHelper::CheckDefinedOperator(SourceName opName, GenericKind kind,
std::optional<parser::MessageFixedText> CheckHelper::CheckNumberOfArgs(
const GenericKind &kind, std::size_t nargs) {
if (!kind.IsIntrinsicOperator()) {
+ if (nargs < 1 || nargs > 2) {
+ return "%s function '%s' should have 1 or 2 dummy arguments"_warn_en_US;
+ }
return std::nullopt;
}
std::size_t min{2}, max{2}; // allowed number of args; default is binary
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index b4e65fad8e905..eebca113fb325 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -2155,19 +2155,21 @@ void ScopeHandler::SayAlreadyDeclared(
void ScopeHandler::SayWithReason(const parser::Name &name, Symbol &symbol,
MessageFixedText &&msg1, Message &&msg2) {
+ bool isFatal{msg1.IsFatal()};
Say(name, std::move(msg1), symbol.name()).Attach(std::move(msg2));
- context().SetError(symbol, msg1.isFatal());
+ context().SetError(symbol, isFatal);
}
void ScopeHandler::SayWithDecl(
const parser::Name &name, Symbol &symbol, MessageFixedText &&msg) {
+ bool isFatal{msg.IsFatal()};
Say(name, std::move(msg), symbol.name())
.Attach(Message{name.source,
symbol.test(Symbol::Flag::Implicit)
? "Implicit declaration of '%s'"_en_US
: "Declaration of '%s'"_en_US,
name.source});
- context().SetError(symbol, msg.isFatal());
+ context().SetError(symbol, isFatal);
}
void ScopeHandler::SayLocalMustBeVariable(
@@ -2190,13 +2192,15 @@ void ScopeHandler::Say2(const SourceName &name1, MessageFixedText &&msg1,
}
void ScopeHandler::Say2(const SourceName &name, MessageFixedText &&msg1,
Symbol &symbol, MessageFixedText &&msg2) {
+ bool isFatal{msg1.IsFatal()};
Say2(name, std::move(msg1), symbol.name(), std::move(msg2));
- context().SetError(symbol, msg1.isFatal());
+ context().SetError(symbol, isFatal);
}
void ScopeHandler::Say2(const parser::Name &name, MessageFixedText &&msg1,
Symbol &symbol, MessageFixedText &&msg2) {
+ bool isFatal{msg1.IsFatal()};
Say2(name.source, std::move(msg1), symbol.name(), std::move(msg2));
- context().SetError(symbol, msg1.isFatal());
+ context().SetError(symbol, isFatal);
}
// This is essentially GetProgramUnitContaining(), but it can return
diff --git a/flang/test/Semantics/generic04.f90 b/flang/test/Semantics/generic04.f90
new file mode 100644
index 0000000000000..1c0b54d9e049b
--- /dev/null
+++ b/flang/test/Semantics/generic04.f90
@@ -0,0 +1,28 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Warn about inaccessible specific procedures in a generic defined operator
+module m
+ interface operator (.foo.)
+ !WARN: OPERATOR(.foo.) function 'noargs' must have 1 or 2 dummy arguments
+ module procedure noargs
+ !WARN: OPERATOR(.foo.) function 'noargs' must have 1 or 2 dummy arguments
+ module procedure threeargs
+ end interface
+ type t
+ contains
+ procedure :: bad
+ !WARN: OPERATOR(.bar.) function 'bad' should have 1 or 2 dummy arguments
+ generic :: operator (.bar.) => bad
+ end type
+ contains
+ real function noargs()
+ noargs = 0.
+ end
+ real function threeargs(fee,fie,foe)
+ real, intent(in) :: fee, fie, foe
+ end
+ function bad(this,x,y)
+ type(t) :: bad
+ class(t), intent(in) :: this, x, y
+ bad = x
+ end
+end
More information about the flang-commits
mailing list