diff options
| author | Yong He <yonghe@outlook.com> | 2025-07-22 08:47:50 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-22 15:47:50 +0000 |
| commit | 52a45890b5ab71d7dbfdd01955afce129728d67e (patch) | |
| tree | 141491e9c36cfa6a1a890765682d69ac4bfd2270 /source/slang/slang-check-overload.cpp | |
| parent | 0d26dbaad90f5eac604e148971d14e552bf9d5b8 (diff) | |
Fix crash when private ctor is used for coercion. (#7858)
* Fix crash when private ctor is used for coercion.
* Fix tests.
* Fix.
* Fix test error.
Diffstat (limited to 'source/slang/slang-check-overload.cpp')
| -rw-r--r-- | source/slang/slang-check-overload.cpp | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp index 18fb9798b..8a8da3eb2 100644 --- a/source/slang/slang-check-overload.cpp +++ b/source/slang/slang-check-overload.cpp @@ -245,13 +245,6 @@ bool SemanticsVisitor::TryCheckOverloadCandidateVisibility( OverloadResolveContext& context, OverloadCandidate const& candidate) { - // Always succeeds when we are trying out constructors. - if (context.mode == OverloadResolveContext::Mode::JustTrying) - { - if (as<ConstructorDecl>(candidate.item.declRef)) - return true; - } - if (!context.sourceScope) return true; @@ -1280,6 +1273,21 @@ error: if (context.originalExpr) { + // Even when there is an error, we still want to update + // the expr we return to refer to the candidate we found so far + // so language server can still provide info on the potential callee. + if (candidate.flavor == OverloadCandidate::Flavor::Func) + { + if (auto invokeExpr = as<InvokeExpr>(context.originalExpr)) + { + invokeExpr->functionExpr = ConstructLookupResultExpr( + candidate.item, + context.baseExpr, + candidate.item.declRef.getName(), + context.funcLoc, + context.originalExpr); + } + } return CreateErrorExpr(context.originalExpr); } else @@ -2711,9 +2719,15 @@ Expr* SemanticsVisitor::ResolveInvoke(InvokeExpr* expr) // equivalent in (almost) all cases. // If callee is a type, and we are calling with one argument, then treat it as a // type coercion. + // + // Exception: if the argument is an initializer list, such as + // Foo({1,2,3}), we should not coerce {1,2,3} to Foo, but rather + // treat it as a ctor call with {1,2,3} as the first argument. + // bool typeOverloadChecked = false; - if (expr->arguments.getCount() == 1 && !as<ExplicitCtorInvokeExpr>(expr)) + if (expr->arguments.getCount() == 1 && !as<ExplicitCtorInvokeExpr>(expr) && + !as<InitializerListExpr>(expr->arguments[0])) { if (const auto typeType = as<TypeType>(funcExpr->type)) { @@ -2943,7 +2957,20 @@ Expr* SemanticsVisitor::ResolveInvoke(InvokeExpr* expr) initListExpr->type = m_astBuilder->getInitializerListType(); Expr* outExpr = nullptr; if (_coerceInitializerList(typetype->getType(), &outExpr, initListExpr)) + { + // If there is a coercion error, make sure we return a valid original expr + // for language server to use. + if (IsErrorExpr(outExpr)) + { + if (auto invokeExpr = as<InvokeExpr>(outExpr)) + { + invokeExpr->originalFunctionExpr = typeExpr; + return CreateErrorExpr(invokeExpr); + } + return CreateErrorExpr(typeExpr); + } return outExpr; + } } // Nothing at all was found that we could even consider invoking. |
