https://github.com/spall updated 
https://github.com/llvm/llvm-project/pull/229939

>From 83235680a7d359f216091f848c9a478d2c761906 Mon Sep 17 00:00:00 2001
From: Sarah Spall <[email protected]>
Date: Wed, 7 Oct 2026 15:40:26 -0700
Subject: [PATCH 1/6] implicit struct passing for groupshared struct

---
 clang/lib/Sema/SemaOverload.cpp               | 13 ++++----
 clang/test/AST/HLSL/StructPassing-AST.hlsl    | 18 +++++++++++
 .../BasicFeatures/StructPassing.hlsl          | 30 +++++++++++++++++++
 3 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index e5049d11480ac4..44b397d2a47b93 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6344,12 +6344,15 @@ ExprResult 
Sema::PerformImplicitObjectArgumentInitialization(
   QualType FromRecordType, DestType;
   QualType ImplicitParamRecordType = Method->getFunctionObjectParameterType();
 
+  LangAS FromAS = From->getType().getAddressSpace();
   if (getLangOpts().HLSL &&
-      From->getType().getAddressSpace() == LangAS::hlsl_constant) {
-    QualType CastType = From->getType().getLocalUnqualifiedType().withConst();
-    From = ImplicitCastExpr::Create(Context, CastType, CK_LValueToRValue, From,
-                                    /*BasePath=*/nullptr, VK_PRValue,
-                                    FPOptionsOverride());
+      (FromAS == LangAS::hlsl_constant || FromAS == LangAS::hlsl_groupshared)) 
{
+    QualType CastType = From->getType().getLocalUnqualifiedType();
+    From = ImplicitCastExpr::Create(
+        Context,
+        FromAS == LangAS::hlsl_constant ? CastType.withConst() : CastType,
+        CK_LValueToRValue, From,
+        /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
   }
 
   Expr::Classification FromClassification;
diff --git a/clang/test/AST/HLSL/StructPassing-AST.hlsl 
b/clang/test/AST/HLSL/StructPassing-AST.hlsl
index 8ae83fa89b3905..745187514bd432 100644
--- a/clang/test/AST/HLSL/StructPassing-AST.hlsl
+++ b/clang/test/AST/HLSL/StructPassing-AST.hlsl
@@ -118,5 +118,23 @@ void case6(S s) {
   useP(s);
 }
 
+struct G {
+  void f() {}
+};
+
+groupshared G g;
+  
+// CHECK: FunctionDecl {{.*}} case7 'void ()'
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: ExprWithCleanups {{.*}} 'void'
+// CHECK-NEXT: CXXMemberCallExpr {{.*}} 'void'
+// CHECK-NEXT: MemberExpr {{.*}} '<bound member function type>' .f {{.*}}
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+void case7() {
+  g.f();
+}
+
 // CHECK-NOT: CXXConstructExpr
 // CHECK-NOT: CXXOperatorCallExpr
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
index c80c7c9466afcf..a846f682493fa6 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
@@ -133,3 +133,33 @@ void case6(S s) {
   // derived to base conversion in argument passing
   useP(s);
 }
+
+// CHECK-LABEL: define hidden void @_Z5case7v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
+// CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_G:%.*]], align 1
+// CHECK-NEXT:    call void @_ZN1G1fEv(ptr noundef nonnull align 1 
dereferenceable(1) [[REF_TMP]]) #[[ATTR3]] [ "convergencectrl"(token [[TMP0]]) ]
+// CHECK-NEXT:    ret void
+//
+void case7();
+
+struct G {
+// CHECK-LABEL: define linkonce_odr hidden void @_ZN1G1fEv(
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) 
#[[ATTR0]] align 2 {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
+// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
+// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
+// CHECK-NEXT:    ret void
+//
+  void f() {}
+};
+
+groupshared G g;
+
+void case7() {
+  // implicit argument passing of a groupshared struct
+  g.f();
+}

>From 4437bff2ca71e485c76f4bdb8ebaa58aac64cbfc Mon Sep 17 00:00:00 2001
From: Sarah Spall <[email protected]>
Date: Wed, 7 Oct 2026 16:47:10 -0700
Subject: [PATCH 2/6] add new test. change test file so update script won't
 break new tests

---
 .../BasicFeatures/StructPassing.hlsl          | 59 +++++++++++++++----
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
index a846f682493fa6..07455027a1ac71 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
@@ -134,19 +134,33 @@ void case6(S s) {
   useP(s);
 }
 
+// disabled otherwise the IR will be generated in the wrong order.
+// UTC_ARGS: --disable
+
+struct G {
+  int X;
+  void f() {}
+  void setX(int val) { this.X = val; }
+};
+
+groupshared G g;
+
 // CHECK-LABEL: define hidden void @_Z5case7v(
 // CHECK-SAME: ) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
 // CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_G:%.*]], align 1
-// CHECK-NEXT:    call void @_ZN1G1fEv(ptr noundef nonnull align 1 
dereferenceable(1) [[REF_TMP]]) #[[ATTR3]] [ "convergencectrl"(token [[TMP0]]) ]
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[REF_TMP]], 
ptr addrspace(3) align 1 @g, i32 4, i1 false)
+// CHECK-NEXT:    call void @_ZN1G1fEv(ptr noundef nonnull align 1 
dereferenceable(4) [[REF_TMP]]) #[[ATTR3]] [ "convergencectrl"(token [[TMP0]]) ]
 // CHECK-NEXT:    ret void
 //
-void case7();
+void case7() {
+  // implicit argument passing of a groupshared struct
+  g.f();
+}
 
-struct G {
 // CHECK-LABEL: define linkonce_odr hidden void @_ZN1G1fEv(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) 
#[[ATTR0]] align 2 {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(4) [[THIS:%.*]]) 
#[[ATTR0]] align 2 {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 4
@@ -154,12 +168,35 @@ struct G {
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
 // CHECK-NEXT:    ret void
 //
-  void f() {}
-};
-
-groupshared G g;
 
-void case7() {
-  // implicit argument passing of a groupshared struct
-  g.f();
+// CHECK-LABEL: define hidden void @_Z5case8i(
+// CHECK-SAME: i32 noundef [[VAL:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
+// CHECK-NEXT:    [[VAL_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_G:%.*]], align 1
+// CHECK-NEXT:    store i32 [[VAL]], ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[REF_TMP]], 
ptr addrspace(3) align 1 @g, i32 4, i1 false)
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    call void @_ZN1G4setXEi(ptr noundef nonnull align 1 
dereferenceable(4) [[REF_TMP]], i32 noundef [[TMP1]]) #[[ATTR3]] [ 
"convergencectrl"(token [[TMP0]]) ]
+// CHECK-NEXT:    ret void
+//
+void case8(int val) {
+  // implicit argument passing of a groupshared struct where the implicit 
object is modified
+  g.setX(val);
 }
+
+// CHECK-LABEL: define linkonce_odr hidden void @_ZN1G4setXEi(
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(4) [[THIS:%.*]], 
i32 noundef [[VAL:%.*]]) #[[ATTR0]] align 2 {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
+// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[VAL_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[VAL]], ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_G:%.*]], ptr 
[[THIS1]], i32 0, i32 0
+// CHECK-NEXT:    store i32 [[TMP1]], ptr [[X]], align 1
+// CHECK-NEXT:    ret void
+//

>From 641eb2fbb5864421d21c99b5dc813131e6ff2fbe Mon Sep 17 00:00:00 2001
From: Sarah Spall <[email protected]>
Date: Thu, 8 Oct 2026 08:31:52 -0700
Subject: [PATCH 3/6] respond to pr comment

---
 clang/lib/Sema/SemaOverload.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 44b397d2a47b93..d90ef3a2a49bb3 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6348,10 +6348,10 @@ ExprResult 
Sema::PerformImplicitObjectArgumentInitialization(
   if (getLangOpts().HLSL &&
       (FromAS == LangAS::hlsl_constant || FromAS == LangAS::hlsl_groupshared)) 
{
     QualType CastType = From->getType().getLocalUnqualifiedType();
-    From = ImplicitCastExpr::Create(
-        Context,
-        FromAS == LangAS::hlsl_constant ? CastType.withConst() : CastType,
-        CK_LValueToRValue, From,
+    if (FromAS == LangAS::hlsl_constant)
+      CastType = CastType.withConst();
+    
+    From = ImplicitCastExpr::Create(Context, CastType, CK_LValueToRValue, From,
         /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
   }
 

>From 961e9d6e4e0acb162f081eaf8064715d14f50a2c Mon Sep 17 00:00:00 2001
From: Sarah Spall <[email protected]>
Date: Thu, 8 Oct 2026 10:20:59 -0700
Subject: [PATCH 4/6] format

---
 clang/lib/Sema/SemaOverload.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d90ef3a2a49bb3..1876f547db836e 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6350,9 +6350,10 @@ ExprResult 
Sema::PerformImplicitObjectArgumentInitialization(
     QualType CastType = From->getType().getLocalUnqualifiedType();
     if (FromAS == LangAS::hlsl_constant)
       CastType = CastType.withConst();
-    
+
     From = ImplicitCastExpr::Create(Context, CastType, CK_LValueToRValue, From,
-        /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
+                                    /*BasePath=*/nullptr, VK_PRValue,
+                                    FPOptionsOverride());
   }
 
   Expr::Classification FromClassification;

>From cec374d943d58ba0df937381f1e06eab6c870834 Mon Sep 17 00:00:00 2001
From: Sarah Spall <[email protected]>
Date: Wed, 14 Oct 2026 09:13:35 -0700
Subject: [PATCH 5/6] update so we use hlsl in out expr for implicit object
 param

---
 clang/lib/CodeGen/CGExpr.cpp                  |  6 +-
 clang/lib/CodeGen/CGExprCXX.cpp               | 16 ++++-
 clang/lib/CodeGen/CodeGenFunction.h           |  2 +-
 clang/lib/Sema/SemaOverload.cpp               | 31 ++++++++--
 clang/test/AST/HLSL/StructPassing-AST.hlsl    | 60 +++++++++++++++++--
 .../BasicFeatures/StructPassing.hlsl          | 49 ++++++++++++---
 6 files changed, 142 insertions(+), 22 deletions(-)

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 8323a170a1dbbc..4fc208550f2710 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -6585,7 +6585,8 @@ CodeGenFunction::EmitHLSLOutArgLValues(const 
HLSLOutArgExpr *E, QualType Ty) {
 }
 
 LValue CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
-                                           CallArgList &Args, QualType Ty) {
+                                           CallArgList &Args, QualType Ty,
+                                           bool IsImplicitObject) {
 
   auto [BaseLV, TempLV] = EmitHLSLOutArgLValues(E, Ty);
 
@@ -6594,7 +6595,8 @@ LValue CodeGenFunction::EmitHLSLOutArgExpr(const 
HLSLOutArgExpr *E,
 
   Address TmpAddr(Addr, ElTy, TempLV.getAlignment());
   Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast());
-  Args.add(RValue::get(TmpAddr, *this), Ty);
+  if (!IsImplicitObject)
+    Args.add(RValue::get(TmpAddr, *this), Ty);
   return TempLV;
 }
 
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 8279611accba33..46d50e26533ac6 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -278,8 +278,18 @@ RValue 
CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
     }
   }
 
-  auto getLValueForThis = [this, IsArrow,
-                           Base](bool EmitCheckedForStore = false) {
+  LValue HLSLThisLValue;
+  if (auto *HLSLOutArg = dyn_cast<HLSLOutArgExpr>(Base)) {
+    if (!RtlArgs)
+      RtlArgs = &RtlArgStorage;
+    HLSLThisLValue = EmitHLSLOutArgExpr(
+        HLSLOutArg, *RtlArgs, HLSLOutArg->getType(), 
/*IsImplicitObject=*/true);
+    EmitCallArgs(*RtlArgs, MD->getType()->castAs<FunctionProtoType>(),
+                 drop_begin(CE->arguments(), 0), CE->getDirectCallee());
+  }
+
+  auto getLValueForThis = [this, IsArrow, Base,
+                           HLSLThisLValue](bool EmitCheckedForStore = false) {
     // FIXME: Respect EmitCheckedForStore for the IsArrow case.
     if (IsArrow) {
       LValueBaseInfo BaseInfo;
@@ -288,6 +298,8 @@ RValue 
CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
       return MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(),
                             BaseInfo, TBAAInfo);
     }
+    if (isa<HLSLOutArgExpr>(Base))
+      return HLSLThisLValue;
     if (EmitCheckedForStore)
       return EmitCheckedLValue(Base, TCK_Store);
     return EmitLValue(Base);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index 00294ad547d5ec..28fef2193b5164 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4586,7 +4586,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   std::pair<LValue, LValue> EmitHLSLOutArgLValues(const HLSLOutArgExpr *E,
                                                   QualType Ty);
   LValue EmitHLSLOutArgExpr(const HLSLOutArgExpr *E, CallArgList &Args,
-                            QualType Ty);
+                            QualType Ty, bool IsImplicitObject = false);
 
   Address EmitExtVectorElementLValue(LValue V);
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 1876f547db836e..0746d28378ece3 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6346,14 +6346,35 @@ ExprResult 
Sema::PerformImplicitObjectArgumentInitialization(
 
   LangAS FromAS = From->getType().getAddressSpace();
   if (getLangOpts().HLSL &&
-      (FromAS == LangAS::hlsl_constant || FromAS == LangAS::hlsl_groupshared)) 
{
-    QualType CastType = From->getType().getLocalUnqualifiedType();
-    if (FromAS == LangAS::hlsl_constant)
-      CastType = CastType.withConst();
-
+      (FromAS == LangAS::hlsl_constant ||
+       (FromAS == LangAS::hlsl_groupshared && Method->isConst()))) {
+    QualType CastType = From->getType().getLocalUnqualifiedType().withConst();
     From = ImplicitCastExpr::Create(Context, CastType, CK_LValueToRValue, From,
                                     /*BasePath=*/nullptr, VK_PRValue,
                                     FPOptionsOverride());
+  } else if (getLangOpts().HLSL && FromAS == LangAS::hlsl_groupshared) {
+    ASTContext &Ctx = SemaRef.getASTContext();
+    QualType Ty =
+        From->getType().getLocalUnqualifiedType().getNonLValueExprType(Ctx);
+    InitializedEntity Entity = InitializedEntity::InitializeTemporary(Ty);
+    auto *FromOpV = new (Ctx) OpaqueValueExpr(
+        From->getBeginLoc(), From->getType().getLocalUnqualifiedType(),
+        VK_LValue, OK_Ordinary, From);
+    ExprResult Res =
+        SemaRef.PerformCopyInitialization(Entity, From->getBeginLoc(), From);
+    if (Res.isInvalid())
+      return ExprError();
+    Expr *Base = Res.get();
+    auto *OpV = new (Ctx)
+        OpaqueValueExpr(From->getBeginLoc(), Ty, VK_LValue, OK_Ordinary, Base);
+
+    Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), From->getBeginLoc(),
+                             tok::equal, FromOpV, OpV);
+    if (Res.isInvalid())
+      return ExprError();
+    Expr *Writeback = Res.get();
+    From = HLSLOutArgExpr::Create(Ctx, Ty, FromOpV, OpV, Writeback,
+                                  /*IsInOut=*/true);
   }
 
   Expr::Classification FromClassification;
diff --git a/clang/test/AST/HLSL/StructPassing-AST.hlsl 
b/clang/test/AST/HLSL/StructPassing-AST.hlsl
index 745187514bd432..c8c87b46b9e0a7 100644
--- a/clang/test/AST/HLSL/StructPassing-AST.hlsl
+++ b/clang/test/AST/HLSL/StructPassing-AST.hlsl
@@ -119,22 +119,72 @@ void case6(S s) {
 }
 
 struct G {
+  int X;
   void f() {}
+  void setX(int val) { X = val; }
+  int getX() const { return X; }
 };
 
 groupshared G g;
   
-// CHECK: FunctionDecl {{.*}} case7 'void ()'
-// CHECK-NEXT: CompoundStmt {{.*}}
-// CHECK-NEXT: ExprWithCleanups {{.*}} 'void'
+// CHECK: FunctionDecl {{.*}} case7 'void ()' external-linkage
+// CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: CXXMemberCallExpr {{.*}} 'void'
-// CHECK-NEXT: MemberExpr {{.*}} '<bound member function type>' .f {{.*}}
-// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: MemberExpr {{.*}} '<bound member function type>' .f
+// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'G' lvalue inout
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+// CHECK-NEXT: BinaryOperator {{.*}} 'G' lvalue '='
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
 // CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
 void case7() {
   g.f();
 }
 
+// CHECK: FunctionDecl {{.*}} case8 'void (int)' external-linkage
+// CHECK-NEXT: ParmVarDecl {{.*}} used V 'int'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CXXMemberCallExpr {{.*}} 'void'
+// CHECK-NEXT: MemberExpr {{.*}} '<bound member function type>' .setX
+// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'G' lvalue inout
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+// CHECK-NEXT: BinaryOperator {{.*}} 'G' lvalue '='
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'V' 'int'
+void case8(int V) {
+  g.setX(V);
+}
+
+// CHECK: FunctionDecl {{.*}} case9 'void ()'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} Y 'int' cinit
+// CHECK-NEXT: ExprWithCleanups {{.*}} 'int'
+// CHECK-NEXT: CXXMemberCallExpr {{.*}} 'int'
+// CHECK-NEXT: MemberExpr {{.*}} '<bound member function type>' .getX
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'const G' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const G' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
+void case9() {
+  int Y = g.getX();
+}
+
 // CHECK-NOT: CXXConstructExpr
 // CHECK-NOT: CXXOperatorCallExpr
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
index 07455027a1ac71..382bf0cf860442 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/StructPassing.hlsl
@@ -141,6 +141,7 @@ struct G {
   int X;
   void f() {}
   void setX(int val) { this.X = val; }
+  int getX() const { return X; }
 };
 
 groupshared G g;
@@ -149,9 +150,12 @@ groupshared G g;
 // CHECK-SAME: ) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
-// CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_G:%.*]], align 1
-// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[REF_TMP]], 
ptr addrspace(3) align 1 @g, i32 4, i1 false)
-// CHECK-NEXT:    call void @_ZN1G1fEv(ptr noundef nonnull align 1 
dereferenceable(4) [[REF_TMP]]) #[[ATTR3]] [ "convergencectrl"(token [[TMP0]]) ]
+// CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_G:%.*]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = alloca [[STRUCT_G]], align 1
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[TMP]], ptr 
addrspace(3) align 1 @g, i32 4, i1 false)
+// CHECK-NEXT:    call void @_ZN1G1fEv(ptr noundef nonnull align 1 
dereferenceable(4) [[TMP]]) #[[ATTR3]] [ "convergencectrl"(token [[TMP0]]) ]
+// CHECK-NEXT:    call void @llvm.memcpy.p3.p0.i32(ptr addrspace(3) align 1 
@g, ptr align 1 [[TMP]], i32 4, i1 false)
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[TMP1]], ptr 
addrspace(3) align 1 @g, i32 4, i1 false)
 // CHECK-NEXT:    ret void
 //
 void case7() {
@@ -174,11 +178,14 @@ void case7() {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
 // CHECK-NEXT:    [[VAL_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_G:%.*]], align 1
+// CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_G:%.*]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = alloca [[STRUCT_G]], align 1
 // CHECK-NEXT:    store i32 [[VAL]], ptr [[VAL_ADDR]], align 4
-// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[REF_TMP]], 
ptr addrspace(3) align 1 @g, i32 4, i1 false)
-// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
-// CHECK-NEXT:    call void @_ZN1G4setXEi(ptr noundef nonnull align 1 
dereferenceable(4) [[REF_TMP]], i32 noundef [[TMP1]]) #[[ATTR3]] [ 
"convergencectrl"(token [[TMP0]]) ]
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[TMP]], ptr 
addrspace(3) align 1 @g, i32 4, i1 false)
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    call void @_ZN1G4setXEi(ptr noundef nonnull align 1 
dereferenceable(4) [[TMP]], i32 noundef [[TMP2]]) #[[ATTR3]] [ 
"convergencectrl"(token [[TMP0]]) ]
+// CHECK-NEXT:    call void @llvm.memcpy.p3.p0.i32(ptr addrspace(3) align 1 
@g, ptr align 1 [[TMP]], i32 4, i1 false)
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[TMP1]], ptr 
addrspace(3) align 1 @g, i32 4, i1 false)
 // CHECK-NEXT:    ret void
 //
 void case8(int val) {
@@ -200,3 +207,31 @@ void case8(int val) {
 // CHECK-NEXT:    store i32 [[TMP1]], ptr [[X]], align 1
 // CHECK-NEXT:    ret void
 //
+
+// CHECK-LABEL: define hidden void @_Z5case9v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
+// CHECK-NEXT:    [[Y:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_G:%.*]], align 1
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p3.i32(ptr align 1 [[REF_TMP]], 
ptr addrspace(3) align 1 @g, i32 4, i1 false)
+// CHECK-NEXT:    [[CALL1:%.*]] = call noundef i32 @_ZNK1G4getXEv(ptr noundef 
nonnull align 1 dereferenceable(4) [[REF_TMP]]) #[[ATTR3]] [ 
"convergencectrl"(token [[TMP0]]) ]
+// CHECK-NEXT:    store i32 [[CALL1]], ptr [[Y]], align 4
+// CHECK-NEXT:    ret void
+//
+void case9() {
+  // implicit argument passing of a groupshared struct where the function is 
const
+  int Y = g.getX();
+}
+
+// CHECK-LABEL: define linkonce_odr hidden noundef i32 @_ZNK1G4getXEv(
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(4) [[THIS:%.*]]) 
#[[ATTR0]] align 2 {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = call token 
@llvm.experimental.convergence.entry()
+// CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
+// CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
+// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_G:%.*]], ptr 
[[THIS1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[X]], align 1
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//

>From 5be839dc3e562e907192d5face7e1374976847df Mon Sep 17 00:00:00 2001
From: Sarah Spall <[email protected]>
Date: Fri, 16 Oct 2026 12:55:39 -0700
Subject: [PATCH 6/6] respond to pr comments

---
 clang/include/clang/Sema/SemaHLSL.h        |  3 +
 clang/lib/CodeGen/CGExpr.cpp               |  4 +-
 clang/lib/CodeGen/CGExprCXX.cpp            |  6 +-
 clang/lib/Sema/SemaHLSL.cpp                | 65 ++++++++++++----------
 clang/lib/Sema/SemaOverload.cpp            | 27 +++------
 clang/test/AST/HLSL/StructPassing-AST.hlsl |  4 ++
 6 files changed, 58 insertions(+), 51 deletions(-)

diff --git a/clang/include/clang/Sema/SemaHLSL.h 
b/clang/include/clang/Sema/SemaHLSL.h
index c25640fbf26bb9..024ace2872a28d 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -239,6 +239,9 @@ class SemaHLSL : public SemaBase {
   bool CanPerformElementwiseCast(Expr *Src, QualType DestType);
   bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType);
   bool CanPerformPackedTypeCast(Expr *Src, QualType DestTy);
+  ExprResult CreateOutArgExprHelper(Expr *Arg, QualType ArgTy, QualType 
ParamTy,
+                                    InitializedEntity Entity,
+                                    SourceLocation Loc, bool IsInOut);
   ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg);
 
   QualType getInoutParameterType(QualType Ty);
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 4fc208550f2710..5d75ed69740113 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -6586,7 +6586,7 @@ CodeGenFunction::EmitHLSLOutArgLValues(const 
HLSLOutArgExpr *E, QualType Ty) {
 
 LValue CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
                                            CallArgList &Args, QualType Ty,
-                                           bool IsImplicitObject) {
+                                           bool IsImplicit) {
 
   auto [BaseLV, TempLV] = EmitHLSLOutArgLValues(E, Ty);
 
@@ -6595,7 +6595,7 @@ LValue CodeGenFunction::EmitHLSLOutArgExpr(const 
HLSLOutArgExpr *E,
 
   Address TmpAddr(Addr, ElTy, TempLV.getAlignment());
   Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast());
-  if (!IsImplicitObject)
+  if (!IsImplicit)
     Args.add(RValue::get(TmpAddr, *this), Ty);
   return TempLV;
 }
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 46d50e26533ac6..66c93fbeb82fac 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -278,7 +278,7 @@ RValue 
CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
     }
   }
 
-  LValue HLSLThisLValue;
+  std::optional<LValue> HLSLThisLValue;
   if (auto *HLSLOutArg = dyn_cast<HLSLOutArgExpr>(Base)) {
     if (!RtlArgs)
       RtlArgs = &RtlArgStorage;
@@ -298,8 +298,8 @@ RValue 
CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
       return MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(),
                             BaseInfo, TBAAInfo);
     }
-    if (isa<HLSLOutArgExpr>(Base))
-      return HLSLThisLValue;
+    if (HLSLThisLValue)
+      return *HLSLThisLValue;
     if (EmitCheckedForStore)
       return EmitCheckedLValue(Base, TCK_Store);
     return EmitLValue(Base);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 73a6c8ae9672ab..d95862a38c3eb1 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -5335,7 +5335,42 @@ bool SemaHLSL::CanPerformPackedTypeCast(Expr *Src, 
QualType DestTy) {
           Ctx.hasSameUnqualifiedType(SrcTy, UIntTy));
 }
 
+ExprResult SemaHLSL::CreateOutArgExprHelper(Expr *Arg, QualType ArgTy,
+                                            QualType ParamTy,
+                                            InitializedEntity Entity,
+                                            SourceLocation Loc, bool IsInOut) {
+  ASTContext &Ctx = SemaRef.getASTContext();
+
+  QualType Ty = ParamTy.getNonLValueExprType(Ctx);
+
+  auto *ArgOpV =
+      new (Ctx) OpaqueValueExpr(Loc, ArgTy, VK_LValue, OK_Ordinary, Arg);
+
+  // Parameters are initialized via copy initialization. This allows for
+  // overload resolution of argument constructors.
+  ExprResult Res = SemaRef.PerformCopyInitialization(Entity, Loc, ArgOpV);
+  if (Res.isInvalid())
+    return ExprError();
+  Expr *Base = Res.get();
+  // After the cast, drop the reference type when creating the exprs.
+  Ty = Ty.getNonLValueExprType(Ctx);
+  auto *OpV = new (Ctx) OpaqueValueExpr(Loc, Ty, VK_LValue, OK_Ordinary, Base);
+
+  // Writebacks are performed with `=` binary operator, which allows for
+  // overload resolution on writeback result expressions.
+  Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), Arg->getBeginLoc(),
+                           tok::equal, ArgOpV, OpV);
+
+  if (Res.isInvalid())
+    return ExprError();
+  Expr *Writeback = Res.get();
+  auto *OutExpr =
+      HLSLOutArgExpr::Create(Ctx, Ty, ArgOpV, OpV, Writeback, IsInOut);
+  return ExprResult(OutExpr);
+}
+
 ExprResult SemaHLSL::ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg) {
+  ASTContext &Ctx = SemaRef.getASTContext();
   assert(Param->hasAttr<HLSLParamModifierAttr>() &&
          "We should not get here without a parameter modifier expression");
   const auto *Attr = Param->getAttr<HLSLParamModifierAttr>();
@@ -5349,8 +5384,6 @@ ExprResult SemaHLSL::ActOnOutParamExpr(ParmVarDecl 
*Param, Expr *Arg) {
     return ExprError();
   }
 
-  ASTContext &Ctx = SemaRef.getASTContext();
-
   QualType Ty = Param->getType().getNonLValueExprType(Ctx);
 
   // HLSL allows implicit conversions from scalars to vectors, but not the
@@ -5362,35 +5395,11 @@ ExprResult SemaHLSL::ActOnOutParamExpr(ParmVarDecl 
*Param, Expr *Arg) {
     return ExprError();
   }
 
-  auto *ArgOpV = new (Ctx) OpaqueValueExpr(Param->getBeginLoc(), 
Arg->getType(),
-                                           VK_LValue, OK_Ordinary, Arg);
-
-  // Parameters are initialized via copy initialization. This allows for
-  // overload resolution of argument constructors.
   InitializedEntity Entity =
       InitializedEntity::InitializeParameter(Ctx, Ty, false);
-  ExprResult Res =
-      SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);
-  if (Res.isInvalid())
-    return ExprError();
-  Expr *Base = Res.get();
-  // After the cast, drop the reference type when creating the exprs.
-  Ty = Ty.getNonLValueExprType(Ctx);
-  auto *OpV = new (Ctx)
-      OpaqueValueExpr(Param->getBeginLoc(), Ty, VK_LValue, OK_Ordinary, Base);
 
-  // Writebacks are performed with `=` binary operator, which allows for
-  // overload resolution on writeback result expressions.
-  Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), Arg->getBeginLoc(),
-                           tok::equal, ArgOpV, OpV);
-
-  if (Res.isInvalid())
-    return ExprError();
-  Expr *Writeback = Res.get();
-  auto *OutExpr =
-      HLSLOutArgExpr::Create(Ctx, Ty, ArgOpV, OpV, Writeback, IsInOut);
-
-  return ExprResult(OutExpr);
+  return CreateOutArgExprHelper(Arg, Arg->getType(), Param->getType(), Entity,
+                                Param->getBeginLoc(), IsInOut);
 }
 
 QualType SemaHLSL::getInoutParameterType(QualType Ty) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 0746d28378ece3..64bbc4428770ba 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -34,6 +34,7 @@
 #include "clang/Sema/SemaAMDGPU.h"
 #include "clang/Sema/SemaARM.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/Template.h"
@@ -6354,27 +6355,17 @@ ExprResult 
Sema::PerformImplicitObjectArgumentInitialization(
                                     FPOptionsOverride());
   } else if (getLangOpts().HLSL && FromAS == LangAS::hlsl_groupshared) {
     ASTContext &Ctx = SemaRef.getASTContext();
-    QualType Ty =
-        From->getType().getLocalUnqualifiedType().getNonLValueExprType(Ctx);
-    InitializedEntity Entity = InitializedEntity::InitializeTemporary(Ty);
-    auto *FromOpV = new (Ctx) OpaqueValueExpr(
-        From->getBeginLoc(), From->getType().getLocalUnqualifiedType(),
-        VK_LValue, OK_Ordinary, From);
+    QualType Ty = From->getType().getLocalUnqualifiedType();
     ExprResult Res =
-        SemaRef.PerformCopyInitialization(Entity, From->getBeginLoc(), From);
+        SemaRef.HLSL()
+            .CreateOutArgExprHelper(From, Ty, Ty,
+                                    InitializedEntity::InitializeTemporary(
+                                        Ty.getNonLValueExprType(Ctx)),
+                                    From->getBeginLoc(), /*IsInOut=*/true)
+            .get();
     if (Res.isInvalid())
       return ExprError();
-    Expr *Base = Res.get();
-    auto *OpV = new (Ctx)
-        OpaqueValueExpr(From->getBeginLoc(), Ty, VK_LValue, OK_Ordinary, Base);
-
-    Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), From->getBeginLoc(),
-                             tok::equal, FromOpV, OpV);
-    if (Res.isInvalid())
-      return ExprError();
-    Expr *Writeback = Res.get();
-    From = HLSLOutArgExpr::Create(Ctx, Ty, FromOpV, OpV, Writeback,
-                                  /*IsInOut=*/true);
+    From = Res.get();
   }
 
   Expr::Classification FromClassification;
diff --git a/clang/test/AST/HLSL/StructPassing-AST.hlsl 
b/clang/test/AST/HLSL/StructPassing-AST.hlsl
index c8c87b46b9e0a7..08fdd6d7ed6125 100644
--- a/clang/test/AST/HLSL/StructPassing-AST.hlsl
+++ b/clang/test/AST/HLSL/StructPassing-AST.hlsl
@@ -136,6 +136,7 @@ groupshared G g;
 // CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
 // CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
 // CHECK-NEXT: BinaryOperator {{.*}} 'G' lvalue '='
 // CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
@@ -143,6 +144,7 @@ groupshared G g;
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
 // CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
 void case7() {
   g.f();
@@ -158,6 +160,7 @@ void case7() {
 // CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
 // CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
 // CHECK-NEXT: BinaryOperator {{.*}} 'G' lvalue '='
 // CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
@@ -165,6 +168,7 @@ void case7() {
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
 // CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'G' <LValueToRValue>
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'G' lvalue
 // CHECK-NEXT: DeclRefExpr {{.*}} 'groupshared G' lvalue Var {{.*}} 'g' 
'groupshared G'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'V' 'int'

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to