@@ -176,8 +176,8 @@ class ArgumentAnalyzer {
176176
177177 // Find and return a user-defined operator or report an error.
178178 // The provided message is used if there is no such operator.
179- MaybeExpr TryDefinedOp (
180- const char *, parser::MessageFixedText , bool isUserOp = false );
179+ MaybeExpr TryDefinedOp (const char *, parser::MessageFixedText,
180+ bool isUserOp = false , bool checkForNullPointer = true );
181181 template <typename E>
182182 MaybeExpr TryDefinedOp (E opr, parser::MessageFixedText msg) {
183183 return TryDefinedOp (
@@ -211,7 +211,8 @@ class ArgumentAnalyzer {
211211 void SayNoMatch (
212212 const std::string &, bool isAssignment = false , bool isAmbiguous = false );
213213 std::string TypeAsFortran (std::size_t );
214- bool AnyUntypedOrMissingOperand () const ;
214+ bool AnyUntypedOperand () const ;
215+ bool AnyMissingOperand () const ;
215216
216217 ExpressionAnalyzer &context_;
217218 ActualArguments actuals_;
@@ -3788,7 +3789,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedUnary &x) {
37883789 ArgumentAnalyzer analyzer{*this , name.source };
37893790 analyzer.Analyze (std::get<1 >(x.t ));
37903791 return analyzer.TryDefinedOp (name.source .ToString ().c_str (),
3791- " No operator %s defined for %s" _err_en_US, true );
3792+ " No operator %s defined for %s" _err_en_US, /* isUserOp= */ true );
37923793}
37933794
37943795// Binary (dyadic) operations
@@ -4176,15 +4177,23 @@ MaybeExpr ExpressionAnalyzer::IterativelyAnalyzeSubexpressions(
41764177 } while (!queue.empty ());
41774178 // Analyze the collected subexpressions in bottom-up order.
41784179 // On an error, bail out and leave partial results in place.
4179- MaybeExpr result;
4180- for (auto riter{finish.rbegin ()}; riter != finish.rend (); ++riter) {
4181- const parser::Expr &expr{**riter};
4182- result = ExprOrVariable (expr, expr.source );
4183- if (!result) {
4184- return result;
4180+ if (finish.size () == 1 ) {
4181+ const parser::Expr &expr{DEREF (finish.front ())};
4182+ return ExprOrVariable (expr, expr.source );
4183+ } else {
4184+ // NULL() operand catching is deferred to operation analysis so
4185+ // that they can be accepted by defined operators.
4186+ auto restorer{AllowNullPointer ()};
4187+ MaybeExpr result;
4188+ for (auto riter{finish.rbegin ()}; riter != finish.rend (); ++riter) {
4189+ const parser::Expr &expr{**riter};
4190+ result = ExprOrVariable (expr, expr.source );
4191+ if (!result) {
4192+ return result;
4193+ }
41854194 }
4195+ return result; // last value was from analysis of "top"
41864196 }
4187- return result; // last value was from analysis of "top"
41884197}
41894198
41904199MaybeExpr ExpressionAnalyzer::Analyze (const parser::Expr &expr) {
@@ -4681,7 +4690,7 @@ bool ArgumentAnalyzer::AnyCUDADeviceData() const {
46814690// attribute.
46824691bool ArgumentAnalyzer::HasDeviceDefinedIntrinsicOpOverride (
46834692 const char *opr) const {
4684- if (AnyCUDADeviceData () && !AnyUntypedOrMissingOperand ()) {
4693+ if (AnyCUDADeviceData () && !AnyUntypedOperand () && ! AnyMissingOperand ()) {
46854694 std::string oprNameString{" operator(" s + opr + ' )' };
46864695 parser::CharBlock oprName{oprNameString};
46874696 parser::Messages buffer;
@@ -4709,9 +4718,9 @@ bool ArgumentAnalyzer::HasDeviceDefinedIntrinsicOpOverride(
47094718 return false ;
47104719}
47114720
4712- MaybeExpr ArgumentAnalyzer::TryDefinedOp (
4713- const char *opr, parser::MessageFixedText error, bool isUserOp) {
4714- if (AnyUntypedOrMissingOperand ()) {
4721+ MaybeExpr ArgumentAnalyzer::TryDefinedOp (const char *opr,
4722+ parser::MessageFixedText error, bool isUserOp, bool checkForNullPointer ) {
4723+ if (AnyMissingOperand ()) {
47154724 context_.Say (error, ToUpperCase (opr), TypeAsFortran (0 ), TypeAsFortran (1 ));
47164725 return std::nullopt ;
47174726 }
@@ -4790,7 +4799,9 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp(
47904799 context_.Say (
47914800 " Operands of %s are not conformable; have rank %d and rank %d" _err_en_US,
47924801 ToUpperCase (opr), actuals_[0 ]->Rank (), actuals_[1 ]->Rank ());
4793- } else if (CheckForNullPointer () && CheckForAssumedRank ()) {
4802+ } else if (!CheckForAssumedRank ()) {
4803+ } else if (checkForNullPointer && !CheckForNullPointer ()) {
4804+ } else { // use the supplied error
47944805 context_.Say (error, ToUpperCase (opr), TypeAsFortran (0 ), TypeAsFortran (1 ));
47954806 }
47964807 return result;
@@ -4808,15 +4819,16 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp(
48084819 for (std::size_t i{0 }; i < oprs.size (); ++i) {
48094820 parser::Messages buffer;
48104821 auto restorer{context_.GetContextualMessages ().SetMessages (buffer)};
4811- if (MaybeExpr thisResult{TryDefinedOp (oprs[i], error)}) {
4822+ if (MaybeExpr thisResult{TryDefinedOp (oprs[i], error, /* isUserOp=*/ false ,
4823+ /* checkForNullPointer=*/ false )}) {
48124824 result = std::move (thisResult);
48134825 hit.push_back (oprs[i]);
48144826 hitBuffer = std::move (buffer);
48154827 }
48164828 }
48174829 }
4818- if (hit.empty ()) { // for the error
4819- result = TryDefinedOp (oprs[0 ], error);
4830+ if (hit.empty ()) { // run TryDefinedOp() again just to emit errors
4831+ CHECK (! TryDefinedOp (oprs[0 ], error). has_value () );
48204832 } else if (hit.size () > 1 ) {
48214833 context_.Say (
48224834 " Matching accessible definitions were found with %zd variant spellings of the generic operator ('%s', '%s')" _err_en_US,
@@ -5232,10 +5244,19 @@ std::string ArgumentAnalyzer::TypeAsFortran(std::size_t i) {
52325244 }
52335245}
52345246
5235- bool ArgumentAnalyzer::AnyUntypedOrMissingOperand () const {
5247+ bool ArgumentAnalyzer::AnyUntypedOperand () const {
5248+ for (const auto &actual : actuals_) {
5249+ if (actual && !actual->GetType () &&
5250+ !IsBareNullPointer (actual->UnwrapExpr ())) {
5251+ return true ;
5252+ }
5253+ }
5254+ return false ;
5255+ }
5256+
5257+ bool ArgumentAnalyzer::AnyMissingOperand () const {
52365258 for (const auto &actual : actuals_) {
5237- if (!actual ||
5238- (!actual->GetType () && !IsBareNullPointer (actual->UnwrapExpr ()))) {
5259+ if (!actual) {
52395260 return true ;
52405261 }
52415262 }
0 commit comments