Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,10 +765,18 @@ static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) {

static void instantiateDependentHLSLParamModifierAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const HLSLParamModifierAttr *Attr, Decl *New) {
ParmVarDecl *P = cast<ParmVarDecl>(New);
P->addAttr(Attr->clone(S.getASTContext()));
P->setType(S.HLSL().getInoutParameterType(P->getType()));
const HLSLParamModifierAttr *Attr, const Decl *Old, Decl *New) {
ParmVarDecl *NewParm = cast<ParmVarDecl>(New);
NewParm->addAttr(Attr->clone(S.getASTContext()));

const Type *OldParmTy = cast<ParmVarDecl>(Old)->getType().getTypePtr();
if (OldParmTy->isDependentType())
NewParm->setType(S.HLSL().getInoutParameterType(NewParm->getType()));

assert(!Attr->isAnyOut() || (NewParm->getType().isRestrictQualified() &&
NewParm->getType()->isReferenceType()) &&
"out or inout parameter type must be a "
"reference and restrict qualified");
}

void Sema::InstantiateAttrsForDecl(
Expand Down Expand Up @@ -923,7 +931,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,

if (const auto *ParamAttr = dyn_cast<HLSLParamModifierAttr>(TmplAttr)) {
instantiateDependentHLSLParamModifierAttr(*this, TemplateArgs, ParamAttr,
New);
Tmpl, New);
continue;
}

Expand Down
42 changes: 42 additions & 0 deletions clang/test/SemaHLSL/Language/TemplateOutArg.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,44 @@ T buzz(int X, T Y) {
return X + Y;
}

// Case 4: Verify that the parameter modifier attributes are instantiated
// for both templated and non-templated arguments, and that the non-templated
// out argument type is not modified by the template instantiation.

// CHECK-LABEL: FunctionTemplateDecl {{.*}} fizz_two

// Check the pattern decl.
// CHECK: FunctionDecl {{.*}} fizz_two 'void (inout T, out int)'
// CHECK-NEXT: ParmVarDecl {{.*}} referenced V 'T'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
// CHECK-NEXT: ParmVarDecl {{.*}} referenced I 'int &__restrict'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out

// Check the 3 instantiations (int, float, & double).

// CHECK-LABEL: FunctionDecl {{.*}} used fizz_two 'void (inout int, out int)' implicit_instantiation
// CHECK: ParmVarDecl {{.*}} used V 'int &__restrict'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
// CHECK: ParmVarDecl {{.*}} used I 'int &__restrict'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out

// CHECK-LABEL: FunctionDecl {{.*}} used fizz_two 'void (inout float, out int)' implicit_instantiation
// CHECK: ParmVarDecl {{.*}} used V 'float &__restrict'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
// CHECK: ParmVarDecl {{.*}} used I 'int &__restrict'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out

// CHECK-LABEL: FunctionDecl {{.*}} used fizz_two 'void (inout double, out int)' implicit_instantiation
// CHECK: ParmVarDecl {{.*}} used V 'double &__restrict'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
// CHECK: ParmVarDecl {{.*}} used I 'int &__restrict'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
template <typename T>
void fizz_two(inout T V, out int I) {
V += 2;
I = V;
}

export void caller() {
int X = 2;
float Y = 3.3;
Expand All @@ -211,4 +249,8 @@ export void caller() {
X = buzz(X, X);
Y = buzz(X, Y);
Z = buzz(X, Z);

fizz_two(X, X);
fizz_two(Y, X);
fizz_two(Z, X);
}