-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] Fix bogus error on aliased derived type #69959
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesWhen a derived type definition is visible by two or more names in the same scope due to USE renaming, any generic ASSIGNMENT(=) or OPERATOR() bindings in the type will produce incorrect error messages about indistinguishable specific procedures. This is due to the use of a std::vector<> to hold a sequence of symbols and some derived information for the specific procedures of the generic name. Change to a std::map<> indexed by the ultimate symbol of each specific so that duplicates cannot arise. Full diff: https://github.com/llvm/llvm-project/pull/69959.diff 2 Files Affected:
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 2c2866d590ae5a4..45fd9dc28fe560c 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -198,10 +198,10 @@ class DistinguishabilityHelper {
SemanticsContext &context_;
struct ProcedureInfo {
GenericKind kind;
- const Symbol &symbol;
const Procedure &procedure;
};
- std::map<SourceName, std::vector<ProcedureInfo>> nameToInfo_;
+ std::map<SourceName, std::map<const Symbol *, ProcedureInfo>>
+ nameToSpecifics_;
};
void CheckHelper::Check(const ParamValue &value, bool canBeAssumed) {
@@ -3441,26 +3441,26 @@ evaluate::Shape SubprogramMatchHelper::FoldShape(const evaluate::Shape &shape) {
}
void DistinguishabilityHelper::Add(const Symbol &generic, GenericKind kind,
- const Symbol &specific, const Procedure &procedure) {
- if (!context_.HasError(specific)) {
- nameToInfo_[generic.name()].emplace_back(
- ProcedureInfo{kind, specific, procedure});
+ const Symbol &ultimateSpecific, const Procedure &procedure) {
+ if (!context_.HasError(ultimateSpecific)) {
+ nameToSpecifics_[generic.name()].emplace(
+ &ultimateSpecific, ProcedureInfo{kind, procedure});
}
}
void DistinguishabilityHelper::Check(const Scope &scope) {
- for (const auto &[name, info] : nameToInfo_) {
- auto count{info.size()};
- for (std::size_t i1{0}; i1 < count - 1; ++i1) {
- const auto &[kind, symbol, proc]{info[i1]};
- for (std::size_t i2{i1 + 1}; i2 < count; ++i2) {
+ for (const auto &[name, info] : nameToSpecifics_) {
+ for (auto iter1{info.begin()}; iter1 != info.end(); ++iter1) {
+ const auto &[ultimate, procInfo]{*iter1};
+ const auto &[kind, proc]{procInfo};
+ for (auto iter2{iter1}; ++iter2 != info.end();) {
auto distinguishable{kind.IsName()
? evaluate::characteristics::Distinguishable
: evaluate::characteristics::DistinguishableOpOrAssign};
if (!distinguishable(
- context_.languageFeatures(), proc, info[i2].procedure)) {
+ context_.languageFeatures(), proc, iter2->second.procedure)) {
SayNotDistinguishable(GetTopLevelUnitContaining(scope), name, kind,
- symbol, info[i2].symbol);
+ *ultimate, *iter2->first);
}
}
}
diff --git a/flang/test/Semantics/generic07.f90 b/flang/test/Semantics/generic07.f90
index 885697e4b5a9783..e7486c02a7d2ba1 100644
--- a/flang/test/Semantics/generic07.f90
+++ b/flang/test/Semantics/generic07.f90
@@ -1,5 +1,5 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
-module m
+module m1
type :: t1
sequence
real :: x
@@ -29,8 +29,28 @@ subroutine s4a(x)
end
end
+module m2
+ type t10
+ integer n
+ contains
+ procedure :: f
+ generic:: operator(+) => f
+ end type
+ contains
+ elemental type(t10) function f(x,y)
+ class(t10), intent(in) :: x, y
+ f%n = x%n + y%n
+ end
+end
+
+module m3
+ use m2, only: rt10 => t10
+end
+
program test
- use m, only: s1a, s2a, s3a, s4a
+ use m1, only: s1a, s2a, s3a, s4a
+ use m2, only: t10
+ use m3, only: rt10 ! alias for t10, ensure no distinguishability error
type :: t1
sequence
integer :: x ! distinct type
@@ -54,7 +74,7 @@ program test
interface distinguishable3
procedure :: s1a, s1b
end interface
- !ERROR: Generic 'indistinguishable' may not have specific procedures 's2a' and 's2b' as their interfaces are not distinguishable
+ !ERROR: Generic 'indistinguishable' may not have specific procedures 's2b' and 's2a' as their interfaces are not distinguishable
interface indistinguishable
procedure :: s2a, s2b
end interface
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All builds and tests correctly and looks good.
When a derived type definition is visible by two or more names in the same scope due to USE renaming, any generic ASSIGNMENT(=) or OPERATOR() bindings in the type will produce incorrect error messages about indistinguishable specific procedures. This is due to the use of a std::vector<> to hold a sequence of symbols and some derived information for the specific procedures of the generic name. Change to a std::map<> indexed by the ultimate symbol of each specific so that duplicates cannot arise.
When a derived type definition is visible by two or more names in the same scope due to USE renaming, any generic ASSIGNMENT(=) or OPERATOR() bindings in the type will produce incorrect error messages about indistinguishable specific procedures. This is due to the use of a std::vector<> to hold a sequence of symbols and some derived information for the specific procedures of the generic name. Change to a std::map<> indexed by the ultimate symbol of each specific so that duplicates cannot arise.