Skip to content

Commit 400d326

Browse files
committed
[HLSL] Cleanup support for this as an l-value
The goal of this change is to clean up some of the code surrounding HLSL using CXXThisExpr as a non-pointer l-value. This change cleans up a bunch of assumptions and inconsistencies around how the type of `this` is handled through the AST and code generation. This change is be mostly NFC for HLSL, and completely NFC for other language modes. This change introduces a new member to query for the this object's type and seeks to clarify the normal usages of the this type. With the introudction of HLSL to clang, CXXThisExpr may now be an l-value and behave like a reference type rather than C++'s normal method of it being an r-value of pointer type. With this change there are now three ways in which a caller might need to query the type of `this`: * The type of the `CXXThisExpr` * The type of the object `this` referrs to * The type of the implicit (or explicit) `this` argument This change codifies those three ways you may need to query respectively as: * CXXMethodDecl::getThisType() * CXXMethodDecl::getThisObjectType() * CXXMethodDecl::getThisArgType() This change then revisits all uses of `getThisType()`, and in cases where the only use was to resolve the pointee type, it replaces the call with `getThisObjectType()`. In other cases it evaluates whether the desired returned type is the type of the `this` expr, or the type of the `this` function argument. The `this` expr type is used for creating additional expr AST nodes and for member lookup, while the argument type is used mostly for code generation. Additionally some cases that used `getThisType` in simple queries could be substituted for `getThisObjectType`. Since `getThisType` is implemented in terms of `getThisObjectType` calling the later should be more efficient if the former isn't needed. Reviewed By: aaron.ballman, bogner Differential Revision: https://reviews.llvm.org/D159247
1 parent 68e94f1 commit 400d326

21 files changed

+69
-66
lines changed

clang/include/clang/AST/ExprCXX.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,16 +1146,21 @@ class CXXUuidofExpr : public Expr {
11461146
/// };
11471147
/// \endcode
11481148
class CXXThisExpr : public Expr {
1149-
public:
1150-
CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit)
1151-
: Expr(CXXThisExprClass, Ty, VK_PRValue, OK_Ordinary) {
1149+
CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit, ExprValueKind VK)
1150+
: Expr(CXXThisExprClass, Ty, VK, OK_Ordinary) {
11521151
CXXThisExprBits.IsImplicit = IsImplicit;
11531152
CXXThisExprBits.Loc = L;
11541153
setDependence(computeDependence(this));
11551154
}
11561155

11571156
CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}
11581157

1158+
public:
1159+
static CXXThisExpr *Create(const ASTContext &Ctx, SourceLocation L,
1160+
QualType Ty, bool IsImplicit);
1161+
1162+
static CXXThisExpr *CreateEmpty(const ASTContext &Ctx);
1163+
11591164
SourceLocation getLocation() const { return CXXThisExprBits.Loc; }
11601165
void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; }
11611166

clang/lib/AST/ASTImporter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8173,8 +8173,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
81738173
if (!ToLocationOrErr)
81748174
return ToLocationOrErr.takeError();
81758175

8176-
return new (Importer.getToContext()) CXXThisExpr(
8177-
*ToLocationOrErr, *ToTypeOrErr, E->isImplicit());
8176+
return CXXThisExpr::Create(Importer.getToContext(), *ToLocationOrErr,
8177+
*ToTypeOrErr, E->isImplicit());
81788178
}
81798179

81808180
ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {

clang/lib/AST/DeclCXX.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2492,7 +2492,8 @@ QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT,
24922492
const CXXRecordDecl *Decl) {
24932493
ASTContext &C = Decl->getASTContext();
24942494
QualType ObjectTy = ::getThisObjectType(C, FPT, Decl);
2495-
return C.getPointerType(ObjectTy);
2495+
return C.getLangOpts().HLSL ? C.getLValueReferenceType(ObjectTy)
2496+
: C.getPointerType(ObjectTy);
24962497
}
24972498

24982499
QualType CXXMethodDecl::getThisObjectType(const FunctionProtoType *FPT,

clang/lib/AST/ExprCXX.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,16 @@ CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
15151515
EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope);
15161516
}
15171517

1518+
CXXThisExpr *CXXThisExpr::Create(const ASTContext &Ctx, SourceLocation L,
1519+
QualType Ty, bool IsImplicit) {
1520+
return new (Ctx) CXXThisExpr(L, Ty, IsImplicit,
1521+
Ctx.getLangOpts().HLSL ? VK_LValue : VK_PRValue);
1522+
}
1523+
1524+
CXXThisExpr *CXXThisExpr::CreateEmpty(const ASTContext &Ctx) {
1525+
return new (Ctx) CXXThisExpr(EmptyShell());
1526+
}
1527+
15181528
static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin,
15191529
UnresolvedSetIterator end) {
15201530
do {

clang/lib/Analysis/Consumed.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
771771
void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {
772772
CXXConstructorDecl *Constructor = Call->getConstructor();
773773

774-
QualType ThisType = Constructor->getThisType()->getPointeeType();
774+
QualType ThisType = Constructor->getThisObjectType();
775775

776776
if (!isConsumableType(ThisType))
777777
return;
@@ -1199,7 +1199,7 @@ void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
11991199
const FunctionDecl *D) {
12001200
QualType ReturnType;
12011201
if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
1202-
ReturnType = Constructor->getThisType()->getPointeeType();
1202+
ReturnType = Constructor->getThisObjectType();
12031203
} else
12041204
ReturnType = D->getCallResultType();
12051205

clang/lib/CodeGen/CGCall.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2585,7 +2585,7 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
25852585
llvm::AttrBuilder Attrs(getLLVMContext());
25862586

25872587
QualType ThisTy =
2588-
FI.arg_begin()->type.castAs<PointerType>()->getPointeeType();
2588+
FI.arg_begin()->type.getTypePtr()->getPointeeType();
25892589

25902590
if (!CodeGenOpts.NullPointerIsValid &&
25912591
getTypes().getTargetAddressSpace(FI.arg_begin()->type) == 0) {

clang/lib/CodeGen/CGClass.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ Address CodeGenFunction::LoadCXXThisAddress() {
138138
CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent());
139139
}
140140

141-
llvm::Type *Ty = ConvertType(MD->getThisType()->getPointeeType());
141+
llvm::Type *Ty = ConvertType(MD->getThisObjectType());
142142
return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull);
143143
}
144144

@@ -2114,8 +2114,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
21142114
CallArgList Args;
21152115
Address This = ThisAVS.getAddress();
21162116
LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace();
2117-
QualType ThisType = D->getThisType();
2118-
LangAS ThisAS = ThisType.getTypePtr()->getPointeeType().getAddressSpace();
2117+
LangAS ThisAS = D->getThisObjectType().getAddressSpace();
21192118
llvm::Value *ThisPtr = This.getPointer();
21202119

21212120
if (SlotAS != ThisAS) {

clang/lib/CodeGen/CGOpenMPRuntime.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8278,7 +8278,7 @@ class MappableExprsHandler {
82788278
// of tofrom.
82798279
// Emit this[:1]
82808280
CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer());
8281-
QualType Ty = MD->getThisType()->getPointeeType();
8281+
QualType Ty = MD->getThisObjectType();
82828282
llvm::Value *Size =
82838283
CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty,
82848284
/*isSigned=*/true);

clang/lib/CodeGen/CGVTables.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn,
201201
// Find the first store of "this", which will be to the alloca associated
202202
// with "this".
203203
Address ThisPtr =
204-
Address(&*AI, ConvertTypeForMem(MD->getThisType()->getPointeeType()),
204+
Address(&*AI, ConvertTypeForMem(MD->getThisObjectType()),
205205
CGM.getClassPointerAlignment(MD->getParent()));
206206
llvm::BasicBlock *EntryBB = &Fn->front();
207207
llvm::BasicBlock::iterator ThisStore =

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,9 @@ struct BuiltinTypeDeclBuilder {
174174
Expr *Call = CallExpr::Create(AST, Fn, {RCExpr}, AST.VoidPtrTy, VK_PRValue,
175175
SourceLocation(), FPOptionsOverride());
176176

177-
CXXThisExpr *This = new (AST) CXXThisExpr(
178-
SourceLocation(),
179-
Constructor->getThisType().getTypePtr()->getPointeeType(), true);
180-
This->setValueKind(ExprValueKind::VK_LValue);
177+
CXXThisExpr *This = CXXThisExpr::Create(
178+
AST, SourceLocation(),
179+
Constructor->getThisObjectType(), true);
181180
Expr *Handle = MemberExpr::CreateImplicit(AST, This, false, Fields["h"],
182181
Fields["h"]->getType(), VK_LValue,
183182
OK_Ordinary);
@@ -261,10 +260,9 @@ struct BuiltinTypeDeclBuilder {
261260
auto FnProtoLoc = TSInfo->getTypeLoc().getAs<FunctionProtoTypeLoc>();
262261
FnProtoLoc.setParam(0, IdxParam);
263262

264-
auto *This = new (AST) CXXThisExpr(
265-
SourceLocation(),
266-
MethodDecl->getThisType().getTypePtr()->getPointeeType(), true);
267-
This->setValueKind(ExprValueKind::VK_LValue);
263+
auto *This = CXXThisExpr::Create(
264+
AST, SourceLocation(),
265+
MethodDecl->getThisObjectType(), true);
268266
auto *HandleAccess = MemberExpr::CreateImplicit(
269267
AST, This, false, Handle, Handle->getType(), VK_LValue, OK_Ordinary);
270268

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
7878
// ref-qualifier or with the & ref-qualifier
7979
// -- "rvalue reference to cv X" for functions declared with the &&
8080
// ref-qualifier
81-
QualType T = MD->getThisType()->castAs<PointerType>()->getPointeeType();
81+
QualType T = MD->getThisObjectType();
8282
T = FnType->getRefQualifier() == RQ_RValue
8383
? S.Context.getRValueReferenceType(T)
8484
: S.Context.getLValueReferenceType(T, /*SpelledAsLValue*/ true);
@@ -565,7 +565,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
565565
auto *FD = cast<FunctionDecl>(CurContext);
566566
bool IsThisDependentType = [&] {
567567
if (auto *MD = dyn_cast_or_null<CXXMethodDecl>(FD))
568-
return MD->isInstance() && MD->getThisType()->isDependentType();
568+
return MD->isInstance() && MD->getThisObjectType()->isDependentType();
569569
else
570570
return false;
571571
}();

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11969,7 +11969,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
1196911969
// struct B { struct Y { ~Y(); }; using X = Y; };
1197011970
// template struct A<B>;
1197111971
if (NewFD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None ||
11972-
!Destructor->getThisType()->isDependentType()) {
11972+
!Destructor->getThisObjectType()->isDependentType()) {
1197311973
CXXRecordDecl *Record = Destructor->getParent();
1197411974
QualType ClassType = Context.getTypeDeclType(Record);
1197511975

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,7 @@ static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12341234

12351235
static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
12361236
const ParsedAttr &AL) {
1237-
QualType ThisType = MD->getThisType()->getPointeeType();
1237+
QualType ThisType = MD->getThisObjectType();
12381238

12391239
if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
12401240
if (!RD->hasAttr<ConsumableAttr>()) {
@@ -1343,7 +1343,7 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
13431343
//
13441344
//} else if (const CXXConstructorDecl *Constructor =
13451345
// dyn_cast<CXXConstructorDecl>(D)) {
1346-
// ReturnType = Constructor->getThisType()->getPointeeType();
1346+
// ReturnType = Constructor->getThisObjectType();
13471347
//
13481348
//} else {
13491349
//

clang/lib/Sema/SemaExpr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3220,8 +3220,8 @@ Sema::PerformObjectMemberConversion(Expr *From,
32203220
if (Method->isStatic())
32213221
return From;
32223222

3223-
DestType = Method->getThisType();
3224-
DestRecordType = DestType->getPointeeType();
3223+
DestType = Method->getThisType().getNonReferenceType();
3224+
DestRecordType = Method->getThisObjectType();
32253225

32263226
if (FromType->getAs<PointerType>()) {
32273227
FromRecordType = FromType->getPointeeType();

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,7 @@ QualType Sema::getCurrentThisType() {
12171217

12181218
if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
12191219
if (method && method->isInstance())
1220-
ThisTy = method->getThisType();
1220+
ThisTy = method->getThisType().getNonReferenceType();
12211221
}
12221222

12231223
if (ThisTy.isNull() && isLambdaCallOperator(CurContext) &&
@@ -1259,7 +1259,8 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
12591259
QualType T = S.Context.getRecordType(Record);
12601260
T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals);
12611261

1262-
S.CXXThisTypeOverride = S.Context.getPointerType(T);
1262+
S.CXXThisTypeOverride =
1263+
S.Context.getLangOpts().HLSL ? T : S.Context.getPointerType(T);
12631264

12641265
this->Enabled = true;
12651266
}
@@ -1406,14 +1407,7 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
14061407

14071408
Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type,
14081409
bool IsImplicit) {
1409-
if (getLangOpts().HLSL && Type.getTypePtr()->isPointerType()) {
1410-
auto *This = new (Context)
1411-
CXXThisExpr(Loc, Type.getTypePtr()->getPointeeType(), IsImplicit);
1412-
This->setValueKind(ExprValueKind::VK_LValue);
1413-
MarkThisReferenced(This);
1414-
return This;
1415-
}
1416-
auto *This = new (Context) CXXThisExpr(Loc, Type, IsImplicit);
1410+
auto *This = CXXThisExpr::Create(Context, Loc, Type, IsImplicit);
14171411
MarkThisReferenced(This);
14181412
return This;
14191413
}
@@ -3966,7 +3960,7 @@ void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
39663960
if (getSourceManager().isInSystemHeader(PointeeRD->getLocation()))
39673961
return;
39683962

3969-
QualType ClassType = dtor->getThisType()->getPointeeType();
3963+
QualType ClassType = dtor->getThisObjectType();
39703964
if (PointeeRD->isAbstract()) {
39713965
// If the class is abstract, we warn by default, because we're
39723966
// sure the code has undefined behavior.

clang/lib/Sema/SemaExprMember.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,20 +1897,11 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
18971897
if (SS.getRange().isValid())
18981898
Loc = SS.getRange().getBegin();
18991899
baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true);
1900-
if (getLangOpts().HLSL && ThisTy.getTypePtr()->isPointerType()) {
1901-
ThisTy = ThisTy.getTypePtr()->getPointeeType();
1902-
return BuildMemberReferenceExpr(baseExpr, ThisTy,
1903-
/*OpLoc*/ SourceLocation(),
1904-
/*IsArrow*/ false, SS, TemplateKWLoc,
1905-
/*FirstQualifierInScope*/ nullptr, R,
1906-
TemplateArgs, S);
1907-
}
19081900
}
19091901

1910-
return BuildMemberReferenceExpr(baseExpr, ThisTy,
1911-
/*OpLoc*/ SourceLocation(),
1912-
/*IsArrow*/ true,
1913-
SS, TemplateKWLoc,
1914-
/*FirstQualifierInScope*/ nullptr,
1915-
R, TemplateArgs, S);
1902+
return BuildMemberReferenceExpr(
1903+
baseExpr, ThisTy,
1904+
/*OpLoc=*/SourceLocation(),
1905+
/*IsArrow=*/!getLangOpts().HLSL, SS, TemplateKWLoc,
1906+
/*FirstQualifierInScope=*/nullptr, R, TemplateArgs, S);
19161907
}

clang/lib/Sema/SemaOverload.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3532,14 +3532,14 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
35323532
case OR_Success: {
35333533
// Record the standard conversion we used and the conversion function.
35343534
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
3535-
QualType ThisType = Constructor->getThisType();
3535+
QualType ThisType = Constructor->getThisObjectType();
35363536
// Initializer lists don't have conversions as such.
35373537
User.Before.setAsIdentityConversion();
35383538
User.HadMultipleCandidates = HadMultipleCandidates;
35393539
User.ConversionFunction = Constructor;
35403540
User.FoundConversionFunction = Best->FoundDecl;
35413541
User.After.setAsIdentityConversion();
3542-
User.After.setFromType(ThisType->castAs<PointerType>()->getPointeeType());
3542+
User.After.setFromType(ThisType);
35433543
User.After.setAllToTypes(ToType);
35443544
return Result;
35453545
}
@@ -3719,7 +3719,6 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
37193719
// sequence converts the source type to the type required by
37203720
// the argument of the constructor.
37213721
//
3722-
QualType ThisType = Constructor->getThisType();
37233722
if (isa<InitListExpr>(From)) {
37243723
// Initializer lists don't have conversions as such.
37253724
User.Before.setAsIdentityConversion();
@@ -3735,7 +3734,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
37353734
User.ConversionFunction = Constructor;
37363735
User.FoundConversionFunction = Best->FoundDecl;
37373736
User.After.setAsIdentityConversion();
3738-
User.After.setFromType(ThisType->castAs<PointerType>()->getPointeeType());
3737+
User.After.setFromType(Constructor->getThisObjectType());
37393738
User.After.setAllToTypes(ToType);
37403739
return Result;
37413740
}
@@ -5639,8 +5638,7 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
56395638
NamedDecl *FoundDecl,
56405639
CXXMethodDecl *Method) {
56415640
QualType FromRecordType, DestType;
5642-
QualType ImplicitParamRecordType =
5643-
Method->getThisType()->castAs<PointerType>()->getPointeeType();
5641+
QualType ImplicitParamRecordType = Method->getThisObjectType();
56445642

56455643
Expr::Classification FromClassification;
56465644
if (const PointerType *PT = From->getType()->getAs<PointerType>()) {

clang/lib/Sema/SemaStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) {
689689
if (CMD->isStatic())
690690
Type.MemberType = FuncType::ft_static_member;
691691
else {
692-
Type.This = CMD->getThisType()->getPointeeType();
692+
Type.This = CMD->getThisObjectType();
693693
Type.MemberType = FuncType::ft_non_static_member;
694694
}
695695
Type.Func = CMD->getType()->castAs<FunctionProtoType>();

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,15 +754,16 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
754754

755755
if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum &&
756756
isa<CXXMethodDecl>(DC) && cast<CXXMethodDecl>(DC)->isInstance()) {
757-
QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType();
757+
QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType().getNonReferenceType();
758758

759759
// Since the 'this' expression is synthesized, we don't need to
760760
// perform the double-lookup check.
761761
NamedDecl *FirstQualifierInScope = nullptr;
762762

763763
return CXXDependentScopeMemberExpr::Create(
764-
Context, /*This*/ nullptr, ThisType, /*IsArrow*/ true,
765-
/*Op*/ SourceLocation(), SS.getWithLocInContext(Context), TemplateKWLoc,
764+
Context, /*This=*/nullptr, ThisType,
765+
/*IsArrow=*/!Context.getLangOpts().HLSL,
766+
/*Op=*/SourceLocation(), SS.getWithLocInContext(Context), TemplateKWLoc,
766767
FirstQualifierInScope, NameInfo, TemplateArgs);
767768
}
768769

clang/lib/Serialization/ASTReaderStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3876,7 +3876,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
38763876
break;
38773877

38783878
case EXPR_CXX_THIS:
3879-
S = new (Context) CXXThisExpr(Empty);
3879+
S = CXXThisExpr::CreateEmpty(Context);
38803880
break;
38813881

38823882
case EXPR_CXX_THROW:

clang/test/CodeGenHLSL/this-reference.hlsl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s | FileCheck %s
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s -debug-info-kind=standalone -dwarf-version=4 | FileCheck %s
22

33
struct Pair {
44
int First;
@@ -26,3 +26,9 @@ void main() {
2626
// CHECK-NEXT: store i32 %call, ptr %First, align 4
2727
// CHECK-NEXT: %call1 = call noundef float @"?getSecond@Pair@@QAAMXZ"(ptr noundef nonnull align 4 dereferenceable(8) %Vals)
2828
// CHECK-NEXT: %Second = getelementptr inbounds %struct.Pair, ptr %Vals, i32 0, i32 1
29+
30+
// CHECK: [[Pair:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Pair"
31+
// CHECK: [[getFirst:![0-9]+]] = distinct !DISubprogram(name: "getFirst"
32+
// CHECK-SAME: scope: [[Pair]]
33+
// CHECK: [[FirstThis:![0-9]+]] = !DILocalVariable(name: "this", arg: 1, scope: [[getFirst]], type: [[thisType:![0-9]+]]
34+
// CHECK: [[thisType]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[Pair]], size: 32)

0 commit comments

Comments
 (0)