diff options
author | Chris B <chris.bieneman@me.com> | 2024-08-31 10:59:08 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-31 10:59:08 -0500 |
commit | 89fb8490a99e612f7a574e8678b21a90f689f5b4 (patch) | |
tree | 213165d8d6b5bc6c0bd0cca5ce2ff30b144a4df8 /clang/lib/Sema/SemaDecl.cpp | |
parent | e41579a31f77008eb76c418df5d192d0974421d2 (diff) | |
download | llvm-89fb8490a99e612f7a574e8678b21a90f689f5b4.zip llvm-89fb8490a99e612f7a574e8678b21a90f689f5b4.tar.gz llvm-89fb8490a99e612f7a574e8678b21a90f689f5b4.tar.bz2 |
[HLSL] Implement output parameter (#101083)
HLSL output parameters are denoted with the `inout` and `out` keywords
in the function declaration. When an argument to an output parameter is
constructed a temporary value is constructed for the argument.
For `inout` pamameters the argument is initialized via copy-initialization
from the argument lvalue expression to the parameter type. For `out`
parameters the argument is not initialized before the call.
In both cases on return of the function the temporary value is written
back to the argument lvalue expression through an implicit assignment
binary operator with casting as required.
This change introduces a new HLSLOutArgExpr ast node which represents
the output argument behavior. The OutArgExpr has three defined children:
- An OpaqueValueExpr of the argument lvalue expression.
- An OpaqueValueExpr of the copy-initialized parameter.
- A BinaryOpExpr assigning the first with the value of the second.
Fixes #87526
---------
Co-authored-by: Damyan Pepper <damyanp@microsoft.com>
Co-authored-by: John McCall <rjmccall@gmail.com>
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 69b793b..8ae1baa 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3249,26 +3249,6 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl, diag::note_carries_dependency_missing_first_decl) << 1/*Param*/; } - // 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. - if (S.getLangOpts().HLSL) { - const auto *NDAttr = newDecl->getAttr<HLSLParamModifierAttr>(); - const auto *ODAttr = oldDecl->getAttr<HLSLParamModifierAttr>(); - // We don't need to cover the case where one declaration doesn't have an - // attribute. The only possible case there is if one declaration has an `in` - // attribute and the other declaration has no attribute. This case is - // allowed since parameters are `in` by default. - if (NDAttr && ODAttr && - NDAttr->getSpellingListIndex() != ODAttr->getSpellingListIndex()) { - S.Diag(newDecl->getLocation(), diag::err_hlsl_param_qualifier_mismatch) - << NDAttr << newDecl; - S.Diag(oldDecl->getLocation(), diag::note_previous_declaration_as) - << ODAttr; - } - } - if (!oldDecl->hasAttrs()) return; @@ -4054,6 +4034,22 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, } } + // HLSL check parameters for matching ABI specifications. + if (getLangOpts().HLSL) { + if (HLSL().CheckCompatibleParameterABI(New, Old)) + return true; + + // If no errors are generated when checking parameter ABIs we can check if + // the two declarations have the same type ignoring the ABIs and if so, + // the declarations can be merged. This case for merging is only valid in + // HLSL because there are no valid cases of merging mismatched parameter + // ABIs except the HLSL implicit in and explicit in. + if (Context.hasSameFunctionTypeIgnoringParamABI(OldQTypeForComparison, + NewQType)) + return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); + // Fall through for conflicting redeclarations and redefinitions. + } + // If the function types are compatible, merge the declarations. Ignore the // exception specifier because it was already checked above in // CheckEquivalentExceptionSpec, and we don't want follow-on diagnostics |