Skip to content

Commit 1b2c1ae

Browse files
committed
Make this more consistently a reference type (#4112)
* Make `this` more consistently a reference type Prior to this change explicit `this` access inside a struct was treated as a reference, but implicit `this` was still a pointer type. With this change `this` is always a reference type. This has no impact on code generation since references and pointers all digress to addresses, but it does make the AST more accurately reflect the types and it resolves #3732. * Updating test case to handle incorrect operator
1 parent 374044c commit 1b2c1ae

6 files changed

Lines changed: 128 additions & 9 deletions

File tree

tools/clang/include/clang/Sema/Sema.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ namespace clang {
195195
struct DeductionFailureInfo;
196196
class TemplateSpecCandidateSet;
197197

198+
class CXXThisExpr; // HLSL Change
199+
198200
namespace sema {
199201
class AccessedEntity;
200202
class BlockScopeInfo;
@@ -9077,6 +9079,11 @@ class Sema {
90779079
return NumArgs + 1 > NumParams; // If so, we view as an extra argument.
90789080
return NumArgs > NumParams;
90799081
}
9082+
9083+
// HLSL Change Begin - adjust this from T* to T&-like
9084+
CXXThisExpr *genereateHLSLThis(SourceLocation Loc, QualType ThisType,
9085+
bool isImplicit);
9086+
// HLSL Change End - adjust this from T* to T&-like
90809087
};
90819088

90829089
/// \brief RAII object that enters a new expression evaluation context.

tools/clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -971,17 +971,24 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
971971
CheckCXXThisCapture(Loc);
972972
// HLSL Change Starts - adjust this from T* to T&-like
973973
if (getLangOpts().HLSL && ThisTy.getTypePtr()->isPointerType()) {
974-
// Expressions cannot be of reference type - instead, they yield
975-
// an lvalue on the underlying type.
976-
CXXThisExpr* ResultExpr = new (Context)CXXThisExpr(
977-
Loc, ThisTy.getTypePtr()->getPointeeType(), /*isImplicit=*/false);
978-
ResultExpr->setValueKind(ExprValueKind::VK_LValue);
979-
return ResultExpr;
974+
return genereateHLSLThis(Loc, ThisTy, /*isImplicit=*/false);
980975
}
981976
// HLSL Change Ends
982977
return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false);
983978
}
984979

980+
// HLSL Change Begin - adjust this from T* to T&-like
981+
CXXThisExpr *Sema::genereateHLSLThis(SourceLocation Loc, QualType ThisType,
982+
bool isImplicit) {
983+
// Expressions cannot be of reference type - instead, they yield
984+
// an lvalue on the underlying type.
985+
CXXThisExpr *ResultExpr = new (Context)
986+
CXXThisExpr(Loc, ThisType.getTypePtr()->getPointeeType(), isImplicit);
987+
ResultExpr->setValueKind(ExprValueKind::VK_LValue);
988+
return ResultExpr;
989+
}
990+
// HLSL Change End - adjust this from T* to T&-like
991+
985992
bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
986993
// If we're outside the body of a member function, then we'll have a specified
987994
// type for 'this'.

tools/clang/lib/Sema/SemaExprMember.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,13 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
10491049
if (SS.getRange().isValid())
10501050
Loc = SS.getRange().getBegin();
10511051
CheckCXXThisCapture(Loc);
1052-
BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
1052+
1053+
// HLSL Change Starts - adjust this from T* to T&-like
1054+
if (getLangOpts().HLSL && BaseExprType->isPointerType())
1055+
BaseExpr = genereateHLSLThis(Loc, BaseExprType, /*isImplicit=*/true);
1056+
else
1057+
BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
1058+
// HLSL Change Ends
10531059
}
10541060

10551061
bool ShouldCheckUse = true;
@@ -1762,12 +1768,17 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
17621768
if (SS.getRange().isValid())
17631769
Loc = SS.getRange().getBegin();
17641770
CheckCXXThisCapture(Loc);
1765-
baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
1771+
if (getLangOpts().HLSL && ThisTy->isPointerType()) {
1772+
baseExpr = genereateHLSLThis(Loc, ThisTy, /*isImplicit=*/true);
1773+
ThisTy = ThisTy->getAs<PointerType>()->getPointeeType();
1774+
} else
1775+
baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
17661776
}
17671777

17681778
return BuildMemberReferenceExpr(baseExpr, ThisTy,
17691779
/*OpLoc*/ SourceLocation(),
1770-
/*IsArrow*/ true,
1780+
// HLSL Change - this is a reference
1781+
/*IsArrow*/ !getLangOpts().HLSL,
17711782
SS, TemplateKWLoc,
17721783
/*FirstQualifierInScope*/ nullptr,
17731784
R, TemplateArgs);

tools/clang/lib/Sema/TreeTransform.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2343,6 +2343,10 @@ class TreeTransform {
23432343
QualType ThisType,
23442344
bool isImplicit) {
23452345
getSema().CheckCXXThisCapture(ThisLoc);
2346+
// HLSL Change Begin - adjust this from T* to T&-like
2347+
if (getSema().getLangOpts().HLSL && ThisType.getTypePtr()->isPointerType())
2348+
return getSema().genereateHLSLThis(ThisLoc, ThisType, isImplicit);
2349+
// HLSL Change End - adjust this from T* to T&-like
23462350
return new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, isImplicit);
23472351
}
23482352

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %dxc -T cs_6_6 -E main -ast-dump %s | FileCheck %s
2+
// RUN: %dxc -T cs_6_6 -E main -DERROR_CASE 2>&1 %s | FileCheck -check-prefix=FAIL %s
3+
4+
struct pair {
5+
int First;
6+
float Second;
7+
8+
int first() {
9+
return this.First;
10+
}
11+
12+
float second() {
13+
return Second;
14+
}
15+
16+
#if ERROR_CASE
17+
float third() {
18+
// FAIL: error: operator is not supported
19+
return this->First;
20+
}
21+
#endif
22+
};
23+
24+
[numthreads(1,1,1)]
25+
void main() {
26+
pair Vals = {1, 2.0};
27+
Vals.First = Vals.first();
28+
Vals.Second = Vals.second();
29+
}
30+
31+
// CHECK: CXXMethodDecl 0x{{[0-9a-zA-Z]+}} <line:8:3, line:10:3> line:8:7 used first 'int ()'
32+
// CHECK-NEXT: `-CompoundStmt 0x{{[0-9a-zA-Z]+}} <col:15, line:10:3>
33+
// CHECK-NEXT: `-ReturnStmt 0x{{[0-9a-zA-Z]+}} <line:9:5, col:17>
34+
// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9a-zA-Z]+}} <col:12, col:17> 'int' <LValueToRValue>
35+
// CHECK-NEXT: `-MemberExpr 0x{{[0-9a-zA-Z]+}} <col:12, col:17> 'int' lvalue .First 0x{{[0-9a-zA-Z]+}}
36+
// CHECK-NEXT: `-CXXThisExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'pair' lvalue this
37+
// CHECK-NEXT: `-CXXMethodDecl 0x{{[0-9a-zA-Z]+}} <line:12:3, line:14:3> line:12:9 used second 'float ()'
38+
// CHECK-NEXT: `-CompoundStmt 0x{{[0-9a-zA-Z]+}} <col:18, line:14:3>
39+
// CHECK-NEXT: `-ReturnStmt 0x{{[0-9a-zA-Z]+}} <line:13:5, col:12>
40+
// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'float' <LValueToRValue>
41+
// CHECK-NEXT: `-MemberExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'float' lvalue .Second 0x{{[0-9a-zA-Z]+}}
42+
// CHECK-NEXT: `-CXXThisExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'pair' lvalue this
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// RUN: %dxc -T cs_6_6 -E main -enable-templates -ast-dump %s | FileCheck %s
2+
// RUN: %dxc -T cs_6_6 -E main -HV 2021 -ast-dump %s | FileCheck %s
3+
4+
template<typename K, typename V>
5+
struct pair {
6+
K First;
7+
V Second;
8+
9+
K first() {
10+
return this.First;
11+
}
12+
13+
V second() {
14+
return Second;
15+
}
16+
};
17+
18+
[numthreads(1,1,1)]
19+
void main() {
20+
pair<int, float> Vals = {1, 2.0};
21+
Vals.First = Vals.first();
22+
Vals.Second = Vals.second();
23+
}
24+
25+
// CHECK: CXXMethodDecl 0x{{[0-9a-zA-Z]+}} <line:9:3, line:11:3> line:9:5 first 'K ()'
26+
// CHECK-NEXT: `-CompoundStmt 0x{{[0-9a-zA-Z]+}} <col:13, line:11:3>
27+
// CHECK-NEXT: `-ReturnStmt 0x{{[0-9a-zA-Z]+}} <line:10:5, col:17>
28+
// CHECK-NEXT: `-CXXDependentScopeMemberExpr 0x{{[0-9a-zA-Z]+}} <col:12, col:17> '<dependent type>' lvalue
29+
// CHECK-NEXT: `-CXXThisExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'pair<K, V>' lvalue this
30+
// CHECK-NEXT: CXXMethodDecl 0x{{[0-9a-zA-Z]+}} <line:13:3, line:15:3> line:13:5 second 'V ()'
31+
// CHECK-NEXT: `-CompoundStmt 0x{{[0-9a-zA-Z]+}} <col:14, line:15:3>
32+
// CHECK-NEXT: `-ReturnStmt 0x{{[0-9a-zA-Z]+}} <line:14:5, col:12>
33+
// CHECK-NEXT: `-MemberExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'V' lvalue .Second 0x{{[0-9a-zA-Z]+}}
34+
// CHECK-NEXT: `-CXXThisExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'pair<K, V>' lvalue this
35+
36+
37+
// CHECK: CXXMethodDecl 0x{{[0-9a-zA-Z]+}} <line:9:3, line:11:3> line:9:5 used first 'int ()'
38+
// CHECK-NEXT: `-CompoundStmt 0x{{[0-9a-zA-Z]+}} <col:13, line:11:3>
39+
// CHECK-NEXT: `-ReturnStmt 0x{{[0-9a-zA-Z]+}} <line:10:5, col:17>
40+
// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9a-zA-Z]+}} <col:12, col:17> 'int':'int' <LValueToRValue>
41+
// CHECK-NEXT: `-MemberExpr 0x{{[0-9a-zA-Z]+}} <col:12, col:17> 'int':'int' lvalue .First 0x{{[0-9a-zA-Z]+}}
42+
// CHECK-NEXT: `-CXXThisExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'pair<int, float>' lvalue this
43+
// CHECK-NEXT: `-CXXMethodDecl 0x{{[0-9a-zA-Z]+}} <line:13:3, line:15:3> line:13:5 used second 'float ()'
44+
// CHECK-NEXT: `-CompoundStmt 0x{{[0-9a-zA-Z]+}} <col:14, line:15:3>
45+
// CHECK-NEXT: `-ReturnStmt 0x{{[0-9a-zA-Z]+}} <line:14:5, col:12>
46+
// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'float':'float' <LValueToRValue>
47+
// CHECK-NEXT: `-MemberExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'float':'float' lvalue .Second 0x{{[0-9a-zA-Z]+}}
48+
// CHECK-NEXT: `-CXXThisExpr 0x{{[0-9a-zA-Z]+}} <col:12> 'pair<int, float>' lvalue this

0 commit comments

Comments
 (0)