@@ -862,10 +862,13 @@ llvm::raw_ostream &Procedure::Dump(llvm::raw_ostream &o) const {
862
862
// Utility class to determine if Procedures, etc. are distinguishable
863
863
class DistinguishUtils {
864
864
public:
865
+ explicit DistinguishUtils (const common::LanguageFeatureControl &features)
866
+ : features_{features} {}
867
+
865
868
// Are these procedures distinguishable for a generic name?
866
- static bool Distinguishable (const Procedure &, const Procedure &);
869
+ bool Distinguishable (const Procedure &, const Procedure &) const ;
867
870
// Are these procedures distinguishable for a generic operator or assignment?
868
- static bool DistinguishableOpOrAssign (const Procedure &, const Procedure &);
871
+ bool DistinguishableOpOrAssign (const Procedure &, const Procedure &) const ;
869
872
870
873
private:
871
874
struct CountDummyProcedures {
@@ -881,31 +884,33 @@ class DistinguishUtils {
881
884
int notOptional{0 };
882
885
};
883
886
884
- static bool Rule3Distinguishable (const Procedure &, const Procedure &);
885
- static const DummyArgument *Rule1DistinguishingArg (
886
- const DummyArguments &, const DummyArguments &);
887
- static int FindFirstToDistinguishByPosition (
888
- const DummyArguments &, const DummyArguments &);
889
- static int FindLastToDistinguishByName (
890
- const DummyArguments &, const DummyArguments &);
891
- static int CountCompatibleWith (const DummyArgument &, const DummyArguments &);
892
- static int CountNotDistinguishableFrom (
893
- const DummyArgument &, const DummyArguments &);
894
- static bool Distinguishable (const DummyArgument &, const DummyArgument &);
895
- static bool Distinguishable (const DummyDataObject &, const DummyDataObject &);
896
- static bool Distinguishable (const DummyProcedure &, const DummyProcedure &);
897
- static bool Distinguishable (const FunctionResult &, const FunctionResult &);
898
- static bool Distinguishable (const TypeAndShape &, const TypeAndShape &);
899
- static bool IsTkrCompatible (const DummyArgument &, const DummyArgument &);
900
- static bool IsTkrCompatible (const TypeAndShape &, const TypeAndShape &);
901
- static const DummyArgument *GetAtEffectivePosition (
902
- const DummyArguments &, int );
903
- static const DummyArgument *GetPassArg (const Procedure &);
887
+ bool Rule3Distinguishable (const Procedure &, const Procedure &) const ;
888
+ const DummyArgument *Rule1DistinguishingArg (
889
+ const DummyArguments &, const DummyArguments &) const ;
890
+ int FindFirstToDistinguishByPosition (
891
+ const DummyArguments &, const DummyArguments &) const ;
892
+ int FindLastToDistinguishByName (
893
+ const DummyArguments &, const DummyArguments &) const ;
894
+ int CountCompatibleWith (const DummyArgument &, const DummyArguments &) const ;
895
+ int CountNotDistinguishableFrom (
896
+ const DummyArgument &, const DummyArguments &) const ;
897
+ bool Distinguishable (const DummyArgument &, const DummyArgument &) const ;
898
+ bool Distinguishable (const DummyDataObject &, const DummyDataObject &) const ;
899
+ bool Distinguishable (const DummyProcedure &, const DummyProcedure &) const ;
900
+ bool Distinguishable (const FunctionResult &, const FunctionResult &) const ;
901
+ bool Distinguishable (const TypeAndShape &, const TypeAndShape &) const ;
902
+ bool IsTkrCompatible (const DummyArgument &, const DummyArgument &) const ;
903
+ bool IsTkrCompatible (const TypeAndShape &, const TypeAndShape &) const ;
904
+ const DummyArgument *GetAtEffectivePosition (
905
+ const DummyArguments &, int ) const ;
906
+ const DummyArgument *GetPassArg (const Procedure &) const ;
907
+
908
+ const common::LanguageFeatureControl &features_;
904
909
};
905
910
906
911
// Simpler distinguishability rules for operators and assignment
907
912
bool DistinguishUtils::DistinguishableOpOrAssign (
908
- const Procedure &proc1, const Procedure &proc2) {
913
+ const Procedure &proc1, const Procedure &proc2) const {
909
914
auto &args1{proc1.dummyArguments };
910
915
auto &args2{proc2.dummyArguments };
911
916
if (args1.size () != args2.size ()) {
@@ -920,7 +925,7 @@ bool DistinguishUtils::DistinguishableOpOrAssign(
920
925
}
921
926
922
927
bool DistinguishUtils::Distinguishable (
923
- const Procedure &proc1, const Procedure &proc2) {
928
+ const Procedure &proc1, const Procedure &proc2) const {
924
929
auto &args1{proc1.dummyArguments };
925
930
auto &args2{proc2.dummyArguments };
926
931
auto count1{CountDummyProcedures (args1)};
@@ -950,7 +955,7 @@ bool DistinguishUtils::Distinguishable(
950
955
// C1514 rule 3: Procedures are distinguishable if both have a passed-object
951
956
// dummy argument and those are distinguishable.
952
957
bool DistinguishUtils::Rule3Distinguishable (
953
- const Procedure &proc1, const Procedure &proc2) {
958
+ const Procedure &proc1, const Procedure &proc2) const {
954
959
const DummyArgument *pass1{GetPassArg (proc1)};
955
960
const DummyArgument *pass2{GetPassArg (proc2)};
956
961
return pass1 && pass2 && Distinguishable (*pass1, *pass2);
@@ -964,7 +969,7 @@ bool DistinguishUtils::Rule3Distinguishable(
964
969
// that are not distinguishable from x
965
970
// - m is greater than n
966
971
const DummyArgument *DistinguishUtils::Rule1DistinguishingArg (
967
- const DummyArguments &args1, const DummyArguments &args2) {
972
+ const DummyArguments &args1, const DummyArguments &args2) const {
968
973
auto size1{args1.size ()};
969
974
auto size2{args2.size ()};
970
975
for (std::size_t i{0 }; i < size1 + size2; ++i) {
@@ -986,7 +991,7 @@ const DummyArgument *DistinguishUtils::Rule1DistinguishingArg(
986
991
// - args2 has no dummy argument at that effective position
987
992
// - the dummy argument at that position is distinguishable from it
988
993
int DistinguishUtils::FindFirstToDistinguishByPosition (
989
- const DummyArguments &args1, const DummyArguments &args2) {
994
+ const DummyArguments &args1, const DummyArguments &args2) const {
990
995
int effective{0 }; // position of arg1 in list, ignoring passed arg
991
996
for (std::size_t i{0 }; i < args1.size (); ++i) {
992
997
const DummyArgument &arg1{args1.at (i)};
@@ -1006,7 +1011,7 @@ int DistinguishUtils::FindFirstToDistinguishByPosition(
1006
1011
// - args2 has no dummy argument with that name
1007
1012
// - the dummy argument with that name is distinguishable from it
1008
1013
int DistinguishUtils::FindLastToDistinguishByName (
1009
- const DummyArguments &args1, const DummyArguments &args2) {
1014
+ const DummyArguments &args1, const DummyArguments &args2) const {
1010
1015
std::map<std::string, const DummyArgument *> nameToArg;
1011
1016
for (const auto &arg2 : args2) {
1012
1017
nameToArg.emplace (arg2.name , &arg2);
@@ -1026,7 +1031,7 @@ int DistinguishUtils::FindLastToDistinguishByName(
1026
1031
// Count the dummy data objects in args that are nonoptional, are not
1027
1032
// passed-object, and that x is TKR compatible with
1028
1033
int DistinguishUtils::CountCompatibleWith (
1029
- const DummyArgument &x, const DummyArguments &args) {
1034
+ const DummyArgument &x, const DummyArguments &args) const {
1030
1035
return std::count_if (args.begin (), args.end (), [&](const DummyArgument &y) {
1031
1036
return !y.pass && !y.IsOptional () && IsTkrCompatible (x, y);
1032
1037
});
@@ -1035,15 +1040,15 @@ int DistinguishUtils::CountCompatibleWith(
1035
1040
// Return the number of dummy data objects in args that are not
1036
1041
// distinguishable from x and not passed-object.
1037
1042
int DistinguishUtils::CountNotDistinguishableFrom (
1038
- const DummyArgument &x, const DummyArguments &args) {
1043
+ const DummyArgument &x, const DummyArguments &args) const {
1039
1044
return std::count_if (args.begin (), args.end (), [&](const DummyArgument &y) {
1040
1045
return !y.pass && std::holds_alternative<DummyDataObject>(y.u ) &&
1041
1046
!Distinguishable (y, x);
1042
1047
});
1043
1048
}
1044
1049
1045
1050
bool DistinguishUtils::Distinguishable (
1046
- const DummyArgument &x, const DummyArgument &y) {
1051
+ const DummyArgument &x, const DummyArgument &y) const {
1047
1052
if (x.u .index () != y.u .index ()) {
1048
1053
return true ; // different kind: data/proc/alt-return
1049
1054
}
@@ -1061,7 +1066,7 @@ bool DistinguishUtils::Distinguishable(
1061
1066
}
1062
1067
1063
1068
bool DistinguishUtils::Distinguishable (
1064
- const DummyDataObject &x, const DummyDataObject &y) {
1069
+ const DummyDataObject &x, const DummyDataObject &y) const {
1065
1070
using Attr = DummyDataObject::Attr;
1066
1071
if (Distinguishable (x.type , y.type )) {
1067
1072
return true ;
@@ -1071,13 +1076,27 @@ bool DistinguishUtils::Distinguishable(
1071
1076
} else if (y.attrs .test (Attr::Allocatable) && x.attrs .test (Attr::Pointer) &&
1072
1077
x.intent != common::Intent::In) {
1073
1078
return true ;
1079
+ } else if (features_.IsEnabled (
1080
+ common::LanguageFeature::DistinguishableSpecifics) &&
1081
+ (x.attrs .test (Attr::Allocatable) || x.attrs .test (Attr::Pointer)) &&
1082
+ (y.attrs .test (Attr::Allocatable) || y.attrs .test (Attr::Pointer)) &&
1083
+ (x.type .type ().IsUnlimitedPolymorphic () !=
1084
+ y.type .type ().IsUnlimitedPolymorphic () ||
1085
+ x.type .type ().IsPolymorphic () != y.type .type ().IsPolymorphic ())) {
1086
+ // Extension: Per 15.5.2.5(2), an allocatable/pointer dummy and its
1087
+ // corresponding actual argument must both or neither be polymorphic,
1088
+ // and must both or neither be unlimited polymorphic. So when exactly
1089
+ // one of two dummy arguments is polymorphic or unlimited polymorphic,
1090
+ // any actual argument that is admissible to one of them cannot also match
1091
+ // the other one.
1092
+ return true ;
1074
1093
} else {
1075
1094
return false ;
1076
1095
}
1077
1096
}
1078
1097
1079
1098
bool DistinguishUtils::Distinguishable (
1080
- const DummyProcedure &x, const DummyProcedure &y) {
1099
+ const DummyProcedure &x, const DummyProcedure &y) const {
1081
1100
const Procedure &xProc{x.procedure .value ()};
1082
1101
const Procedure &yProc{y.procedure .value ()};
1083
1102
if (Distinguishable (xProc, yProc)) {
@@ -1091,7 +1110,7 @@ bool DistinguishUtils::Distinguishable(
1091
1110
}
1092
1111
1093
1112
bool DistinguishUtils::Distinguishable (
1094
- const FunctionResult &x, const FunctionResult &y) {
1113
+ const FunctionResult &x, const FunctionResult &y) const {
1095
1114
if (x.u .index () != y.u .index ()) {
1096
1115
return true ; // one is data object, one is procedure
1097
1116
}
@@ -1109,19 +1128,19 @@ bool DistinguishUtils::Distinguishable(
1109
1128
}
1110
1129
1111
1130
bool DistinguishUtils::Distinguishable (
1112
- const TypeAndShape &x, const TypeAndShape &y) {
1131
+ const TypeAndShape &x, const TypeAndShape &y) const {
1113
1132
return !IsTkrCompatible (x, y) && !IsTkrCompatible (y, x);
1114
1133
}
1115
1134
1116
1135
// Compatibility based on type, kind, and rank
1117
1136
bool DistinguishUtils::IsTkrCompatible (
1118
- const DummyArgument &x, const DummyArgument &y) {
1137
+ const DummyArgument &x, const DummyArgument &y) const {
1119
1138
const auto *obj1{std::get_if<DummyDataObject>(&x.u )};
1120
1139
const auto *obj2{std::get_if<DummyDataObject>(&y.u )};
1121
1140
return obj1 && obj2 && IsTkrCompatible (obj1->type , obj2->type );
1122
1141
}
1123
1142
bool DistinguishUtils::IsTkrCompatible (
1124
- const TypeAndShape &x, const TypeAndShape &y) {
1143
+ const TypeAndShape &x, const TypeAndShape &y) const {
1125
1144
return x.type ().IsTkCompatibleWith (y.type ()) &&
1126
1145
(x.attrs ().test (TypeAndShape::Attr::AssumedRank) ||
1127
1146
y.attrs ().test (TypeAndShape::Attr::AssumedRank) ||
@@ -1130,7 +1149,7 @@ bool DistinguishUtils::IsTkrCompatible(
1130
1149
1131
1150
// Return the argument at the given index, ignoring the passed arg
1132
1151
const DummyArgument *DistinguishUtils::GetAtEffectivePosition (
1133
- const DummyArguments &args, int index) {
1152
+ const DummyArguments &args, int index) const {
1134
1153
for (const DummyArgument &arg : args) {
1135
1154
if (!arg.pass ) {
1136
1155
if (index == 0 ) {
@@ -1143,7 +1162,7 @@ const DummyArgument *DistinguishUtils::GetAtEffectivePosition(
1143
1162
}
1144
1163
1145
1164
// Return the passed-object dummy argument of this procedure, if any
1146
- const DummyArgument *DistinguishUtils::GetPassArg (const Procedure &proc) {
1165
+ const DummyArgument *DistinguishUtils::GetPassArg (const Procedure &proc) const {
1147
1166
for (const auto &arg : proc.dummyArguments ) {
1148
1167
if (arg.pass ) {
1149
1168
return &arg;
@@ -1152,12 +1171,14 @@ const DummyArgument *DistinguishUtils::GetPassArg(const Procedure &proc) {
1152
1171
return nullptr ;
1153
1172
}
1154
1173
1155
- bool Distinguishable (const Procedure &x, const Procedure &y) {
1156
- return DistinguishUtils::Distinguishable (x, y);
1174
+ bool Distinguishable (const common::LanguageFeatureControl &features,
1175
+ const Procedure &x, const Procedure &y) {
1176
+ return DistinguishUtils{features}.Distinguishable (x, y);
1157
1177
}
1158
1178
1159
- bool DistinguishableOpOrAssign (const Procedure &x, const Procedure &y) {
1160
- return DistinguishUtils::DistinguishableOpOrAssign (x, y);
1179
+ bool DistinguishableOpOrAssign (const common::LanguageFeatureControl &features,
1180
+ const Procedure &x, const Procedure &y) {
1181
+ return DistinguishUtils{features}.DistinguishableOpOrAssign (x, y);
1161
1182
}
1162
1183
1163
1184
DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS (DummyArgument)
0 commit comments