================ @@ -1121,3 +1121,99 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { } return false; } + +bool SemaHLSL::CheckCompatibleParameterABI(FunctionDecl *New, + FunctionDecl *Old) { + if (New->getNumParams() != Old->getNumParams()) + return true; + + bool HadError = false; + + for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) { + ParmVarDecl *NewParam = New->getParamDecl(i); + ParmVarDecl *OldParam = Old->getParamDecl(i); + + // HLSL parameter declarations for inout and out must match between + // declarations. In HLSL inout and out are ambiguous at the call site, + // but have different calling behavior, so you cannot overload a + // method based on a difference between inout and out annotations. + const auto *NDAttr = NewParam->getAttr<HLSLParamModifierAttr>(); + unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0); + const auto *ODAttr = OldParam->getAttr<HLSLParamModifierAttr>(); + unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0); + + if (NSpellingIdx != OSpellingIdx) { + SemaRef.Diag(NewParam->getLocation(), + diag::err_hlsl_param_qualifier_mismatch) + << NDAttr << NewParam; + SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as) + << ODAttr; + HadError = true; + } + } + return HadError; +} + +ExprResult SemaHLSL::ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg) { + assert(Param->hasAttr<HLSLParamModifierAttr>() && + "We should not get here without a parameter modifier expression"); + const auto *Attr = Param->getAttr<HLSLParamModifierAttr>(); + if (Attr->getABI() == ParameterABI::Ordinary) + return ExprResult(Arg); + + bool IsInOut = Attr->getABI() == ParameterABI::HLSLInOut; + if (!Arg->isLValue()) { + SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_lvalue) + << Arg << (IsInOut ? 1 : 0); + return ExprError(); + } + + ASTContext &Ctx = SemaRef.getASTContext(); + + QualType Ty = Param->getType().getNonLValueExprType(Ctx); + + // HLSL allows implicit conversions from scalars to vectors, but not the + // inverse, so we need to disallow `inout` with scalar->vector or + // scalar->matrix conversions. + if (Arg->getType()->isScalarType() != Ty->isScalarType()) { + SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension) + << Arg << (IsInOut ? 1 : 0); + return ExprError(); + } + + bool RequiresConversion = + Ty.getUnqualifiedType() != Arg->getType().getUnqualifiedType(); + + // If the unqualified types mismatch we may have some casting. Since this + // results in a copy we can ignore qualifiers. + if (RequiresConversion) { + ExprResult Res = + SemaRef.PerformImplicitConversion(Arg, Ty, Sema::AA_Passing); ---------------- llvm-beanz wrote:
My latest update is mostly in line with the feedback here. I did the OVE's a little different, but it _radically_ simplified the CodeGen changes (thank you for all the suggestions!). I've changed the initialization to use `PerformCopyInitialization` so that it will resolve constructors correctly and the write back is just a binary op built with `ActOnBinOp`. That also radically simplified the codegen. At a simplified level the C++-equivalent code for how `inout` and `out` arguments work is something like this: ```c++ namespace detail { template<typename TmpT, typename SrcT> struct InOutAdapter { SrcT &SrcLV; TmpT TmpLV; InOutAdapter(SrcT &S) : SrcLV(S), TmpLV(S) {} ~InOutAdapter() { SrcLV = TmpLV; } operator TmpT&(){ return TmpLV; } }; } template <typename ArgT, typename SrcT> detail::InOutAdapter<ArgT, SrcT> make_inout(SrcT &V) { return detail::InOutAdapter<ArgT, SrcT>(V); } namespace detail { template<typename TmpT, typename SrcT> struct OutAdapter { SrcT &SrcLV; TmpT TmpLV; OutAdapter(SrcT &S) : SrcLV(S) {} ~OutAdapter() { SrcLV = TmpLV; } operator TmpT&(){ return TmpLV; } }; } template <typename ArgT, typename SrcT> detail::OutAdapter<ArgT, SrcT> make_out(SrcT &V) { return detail::OutAdapter<ArgT, SrcT>(V); } ``` [Compiler Explorer C++ Example](https://godbolt.org/z/G1jhn78qG) I believe with my latest changes the AST generation and codegen both correctly match this. https://github.com/llvm/llvm-project/pull/101083 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits