diff options
Diffstat (limited to 'lib/CodeGen/CallGen.cc')
| -rw-r--r-- | lib/CodeGen/CallGen.cc | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/CodeGen/CallGen.cc b/lib/CodeGen/CallGen.cc index 4631332..43c0dd4 100644 --- a/lib/CodeGen/CallGen.cc +++ b/lib/CodeGen/CallGen.cc @@ -225,6 +225,30 @@ const FuncSig *CodeGen::resolveCall(const std::string &Name, } } if (Ordinary) return Ordinary; + // Failing an exact match, CHAR and STRING arguments convert into one + // another; the overload must be unique. + if (!HasTemplates && !HasExplicit) { + auto Scalar = [](const TypeInfo *T) { return T && (T->Kind == TypeKind::Char || T->isString()); }; + const FuncSig *Converted = nullptr; + for (const FuncSig *Sig : Overloads) { + if (Sig->Params.size() != Actual.size()) continue; + bool Match = true; + for (size_t I = 0; I < Actual.size() && Match; ++I) { + const ParamSig &P = Sig->Params[I]; + const TypeInfo *Formal = Types->resolve(P.TypeName); + Match = Actual[I].Rank == (P.IsArray ? P.Rank : 0) && Actual[I].Type && + (Actual[I].Type->sameType(Formal) || + (!P.IsByRef && !P.IsArray && Scalar(Actual[I].Type) && Scalar(Formal))); + } + if (!Match) continue; + if (Converted) { + reportError("Ambiguous call to %s(%s)", Name.c_str(), Key.c_str()); + return nullptr; + } + Converted = Sig; + } + if (Converted) return Converted; + } if (HasTemplates) { // A matching non-variadic template wins before any variadic candidate. for (bool Variadic : {false, true}) { |
