diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2171,6 +2171,7 @@ /// See getThisType() for usage restriction. QualType getThisObjectType() const; + static QualType getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl); diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1146,9 +1146,8 @@ /// }; /// \endcode class CXXThisExpr : public Expr { -public: - CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit) - : Expr(CXXThisExprClass, Ty, VK_PRValue, OK_Ordinary) { + CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit, ExprValueKind VK) + : Expr(CXXThisExprClass, Ty, VK, OK_Ordinary) { CXXThisExprBits.IsImplicit = IsImplicit; CXXThisExprBits.Loc = L; setDependence(computeDependence(this)); @@ -1156,6 +1155,12 @@ CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} +public: + static CXXThisExpr *Create(const ASTContext &Ctx, SourceLocation L, + QualType Ty, bool IsImplicit); + + static CXXThisExpr *CreateEmpty(const ASTContext &Ctx); + SourceLocation getLocation() const { return CXXThisExprBits.Loc; } void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8089,8 +8089,8 @@ if (!ToLocationOrErr) return ToLocationOrErr.takeError(); - return new (Importer.getToContext()) CXXThisExpr( - *ToLocationOrErr, *ToTypeOrErr, E->isImplicit()); + return CXXThisExpr::Create(Importer.getToContext(), *ToLocationOrErr, + *ToTypeOrErr, E->isImplicit()); } ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2492,7 +2492,8 @@ const CXXRecordDecl *Decl) { ASTContext &C = Decl->getASTContext(); QualType ObjectTy = ::getThisObjectType(C, FPT, Decl); - return C.getPointerType(ObjectTy); + return C.getLangOpts().HLSL ? C.getLValueReferenceType(ObjectTy) + : C.getPointerType(ObjectTy); } QualType CXXMethodDecl::getThisObjectType(const FunctionProtoType *FPT, diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1515,6 +1515,16 @@ EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope); } +CXXThisExpr *CXXThisExpr::Create(const ASTContext &Ctx, SourceLocation L, + QualType Ty, bool IsImplicit) { + return new (Ctx) CXXThisExpr(L, Ty, IsImplicit, + Ctx.getLangOpts().HLSL ? VK_LValue : VK_PRValue); +} + +CXXThisExpr *CXXThisExpr::CreateEmpty(const ASTContext &Ctx) { + return new (Ctx) CXXThisExpr(EmptyShell()); +} + static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin, UnresolvedSetIterator end) { do { diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -771,7 +771,7 @@ void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) { CXXConstructorDecl *Constructor = Call->getConstructor(); - QualType ThisType = Constructor->getThisType()->getPointeeType(); + QualType ThisType = Constructor->getThisObjectType(); if (!isConsumableType(ThisType)) return; @@ -1199,7 +1199,7 @@ const FunctionDecl *D) { QualType ReturnType; if (const auto *Constructor = dyn_cast(D)) { - ReturnType = Constructor->getThisType()->getPointeeType(); + ReturnType = Constructor->getThisObjectType(); } else ReturnType = D->getCallResultType(); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2607,7 +2607,7 @@ llvm::AttrBuilder Attrs(getLLVMContext()); QualType ThisTy = - FI.arg_begin()->type.castAs()->getPointeeType(); + FI.arg_begin()->type.getTypePtr()->getPointeeType(); if (!CodeGenOpts.NullPointerIsValid && getTypes().getTargetAddressSpace(FI.arg_begin()->type) == 0) { diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -138,7 +138,7 @@ CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent()); } - llvm::Type *Ty = ConvertType(MD->getThisType()->getPointeeType()); + llvm::Type *Ty = ConvertType(MD->getThisObjectType()); return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull); } @@ -2114,8 +2114,7 @@ CallArgList Args; Address This = ThisAVS.getAddress(); LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace(); - QualType ThisType = D->getThisType(); - LangAS ThisAS = ThisType.getTypePtr()->getPointeeType().getAddressSpace(); + LangAS ThisAS = D->getThisObjectType().getAddressSpace(); llvm::Value *ThisPtr = This.getPointer(); if (SlotAS != ThisAS) { diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -8278,7 +8278,7 @@ // of tofrom. // Emit this[:1] CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer()); - QualType Ty = MD->getThisType()->getPointeeType(); + QualType Ty = MD->getThisObjectType(); llvm::Value *Size = CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty, /*isSigned=*/true); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -201,7 +201,7 @@ // Find the first store of "this", which will be to the alloca associated // with "this". Address ThisPtr = - Address(&*AI, ConvertTypeForMem(MD->getThisType()->getPointeeType()), + Address(&*AI, ConvertTypeForMem(MD->getThisObjectType()), CGM.getClassPointerAlignment(MD->getParent())); llvm::BasicBlock *EntryBB = &Fn->front(); llvm::BasicBlock::iterator ThisStore = diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -174,10 +174,9 @@ Expr *Call = CallExpr::Create(AST, Fn, {RCExpr}, AST.VoidPtrTy, VK_PRValue, SourceLocation(), FPOptionsOverride()); - CXXThisExpr *This = new (AST) CXXThisExpr( - SourceLocation(), - Constructor->getThisType().getTypePtr()->getPointeeType(), true); - This->setValueKind(ExprValueKind::VK_LValue); + CXXThisExpr *This = CXXThisExpr::Create( + AST, SourceLocation(), + Constructor->getThisObjectType(), true); Expr *Handle = MemberExpr::CreateImplicit(AST, This, false, Fields["h"], Fields["h"]->getType(), VK_LValue, OK_Ordinary); @@ -261,10 +260,9 @@ auto FnProtoLoc = TSInfo->getTypeLoc().getAs(); FnProtoLoc.setParam(0, IdxParam); - auto *This = new (AST) CXXThisExpr( - SourceLocation(), - MethodDecl->getThisType().getTypePtr()->getPointeeType(), true); - This->setValueKind(ExprValueKind::VK_LValue); + auto *This = CXXThisExpr::Create( + AST, SourceLocation(), + MethodDecl->getThisObjectType(), true); auto *HandleAccess = MemberExpr::CreateImplicit( AST, This, false, Handle, Handle->getType(), VK_LValue, OK_Ordinary); diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -78,7 +78,7 @@ // ref-qualifier or with the & ref-qualifier // -- "rvalue reference to cv X" for functions declared with the && // ref-qualifier - QualType T = MD->getThisType()->castAs()->getPointeeType(); + QualType T = MD->getThisObjectType(); T = FnType->getRefQualifier() == RQ_RValue ? S.Context.getRValueReferenceType(T) : S.Context.getLValueReferenceType(T, /*SpelledAsLValue*/ true); @@ -565,7 +565,7 @@ auto *FD = cast(CurContext); bool IsThisDependentType = [&] { if (auto *MD = dyn_cast_or_null(FD)) - return MD->isInstance() && MD->getThisType()->isDependentType(); + return MD->isInstance() && MD->getThisObjectType()->isDependentType(); else return false; }(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11969,7 +11969,7 @@ // struct B { struct Y { ~Y(); }; using X = Y; }; // template struct A; if (NewFD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None || - !Destructor->getThisType()->isDependentType()) { + !Destructor->getThisObjectType()->isDependentType()) { CXXRecordDecl *Record = Destructor->getParent(); QualType ClassType = Context.getTypeDeclType(Record); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1234,7 +1234,7 @@ static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, const ParsedAttr &AL) { - QualType ThisType = MD->getThisType()->getPointeeType(); + QualType ThisType = MD->getThisObjectType(); if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { if (!RD->hasAttr()) { @@ -1343,7 +1343,7 @@ // //} else if (const CXXConstructorDecl *Constructor = // dyn_cast(D)) { - // ReturnType = Constructor->getThisType()->getPointeeType(); + // ReturnType = Constructor->getThisObjectType(); // //} else { // diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3211,8 +3211,8 @@ if (Method->isStatic()) return From; - DestType = Method->getThisType(); - DestRecordType = DestType->getPointeeType(); + DestType = Method->getThisType().getNonReferenceType(); + DestRecordType = Method->getThisObjectType(); if (FromType->getAs()) { FromRecordType = FromType->getPointeeType(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1216,7 +1216,7 @@ if (CXXMethodDecl *method = dyn_cast(DC)) { if (method && method->isInstance()) - ThisTy = method->getThisType(); + ThisTy = method->getThisType().getNonReferenceType(); } if (ThisTy.isNull() && isLambdaCallOperator(CurContext) && @@ -1258,7 +1258,8 @@ QualType T = S.Context.getRecordType(Record); T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals); - S.CXXThisTypeOverride = S.Context.getPointerType(T); + S.CXXThisTypeOverride = + S.Context.getLangOpts().HLSL ? T : S.Context.getPointerType(T); this->Enabled = true; } @@ -1405,14 +1406,7 @@ Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit) { - if (getLangOpts().HLSL && Type.getTypePtr()->isPointerType()) { - auto *This = new (Context) - CXXThisExpr(Loc, Type.getTypePtr()->getPointeeType(), IsImplicit); - This->setValueKind(ExprValueKind::VK_LValue); - MarkThisReferenced(This); - return This; - } - auto *This = new (Context) CXXThisExpr(Loc, Type, IsImplicit); + auto *This = CXXThisExpr::Create(Context, Loc, Type, IsImplicit); MarkThisReferenced(This); return This; } @@ -3965,7 +3959,7 @@ if (getSourceManager().isInSystemHeader(PointeeRD->getLocation())) return; - QualType ClassType = dtor->getThisType()->getPointeeType(); + QualType ClassType = dtor->getThisObjectType(); if (PointeeRD->isAbstract()) { // If the class is abstract, we warn by default, because we're // sure the code has undefined behavior. diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1897,19 +1897,11 @@ if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true); - if (getLangOpts().HLSL && ThisTy.getTypePtr()->isPointerType()) { - ThisTy = ThisTy.getTypePtr()->getPointeeType(); - return BuildMemberReferenceExpr(baseExpr, ThisTy, - /*OpLoc*/ SourceLocation(), - /*IsArrow*/ false, SS, TemplateKWLoc, - /*FirstQualifierInScope*/ nullptr, R, - TemplateArgs, S); - } } return BuildMemberReferenceExpr(baseExpr, ThisTy, /*OpLoc*/ SourceLocation(), - /*IsArrow*/ true, + /*IsArrow*/ !getLangOpts().HLSL, SS, TemplateKWLoc, /*FirstQualifierInScope*/ nullptr, R, TemplateArgs, S); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3532,14 +3532,14 @@ case OR_Success: { // Record the standard conversion we used and the conversion function. CXXConstructorDecl *Constructor = cast(Best->Function); - QualType ThisType = Constructor->getThisType(); + QualType ThisType = Constructor->getThisObjectType(); // Initializer lists don't have conversions as such. User.Before.setAsIdentityConversion(); User.HadMultipleCandidates = HadMultipleCandidates; User.ConversionFunction = Constructor; User.FoundConversionFunction = Best->FoundDecl; User.After.setAsIdentityConversion(); - User.After.setFromType(ThisType->castAs()->getPointeeType()); + User.After.setFromType(ThisType); User.After.setAllToTypes(ToType); return Result; } @@ -3719,7 +3719,6 @@ // sequence converts the source type to the type required by // the argument of the constructor. // - QualType ThisType = Constructor->getThisType(); if (isa(From)) { // Initializer lists don't have conversions as such. User.Before.setAsIdentityConversion(); @@ -3735,7 +3734,7 @@ User.ConversionFunction = Constructor; User.FoundConversionFunction = Best->FoundDecl; User.After.setAsIdentityConversion(); - User.After.setFromType(ThisType->castAs()->getPointeeType()); + User.After.setFromType(Constructor->getThisObjectType()); User.After.setAllToTypes(ToType); return Result; } @@ -5639,8 +5638,7 @@ NamedDecl *FoundDecl, CXXMethodDecl *Method) { QualType FromRecordType, DestType; - QualType ImplicitParamRecordType = - Method->getThisType()->castAs()->getPointeeType(); + QualType ImplicitParamRecordType = Method->getThisObjectType(); Expr::Classification FromClassification; if (const PointerType *PT = From->getType()->getAs()) { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -689,7 +689,7 @@ if (CMD->isStatic()) Type.MemberType = FuncType::ft_static_member; else { - Type.This = CMD->getThisType()->getPointeeType(); + Type.This = CMD->getThisObjectType(); Type.MemberType = FuncType::ft_non_static_member; } Type.Func = CMD->getType()->castAs(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -753,14 +753,15 @@ if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum && isa(DC) && cast(DC)->isInstance()) { - QualType ThisType = cast(DC)->getThisType(); + QualType ThisType = cast(DC)->getThisType().getNonReferenceType(); // Since the 'this' expression is synthesized, we don't need to // perform the double-lookup check. NamedDecl *FirstQualifierInScope = nullptr; return CXXDependentScopeMemberExpr::Create( - Context, /*This*/ nullptr, ThisType, /*IsArrow*/ true, + Context, /*This*/ nullptr, ThisType, + /*IsArrow*/ !Context.getLangOpts().HLSL, /*Op*/ SourceLocation(), SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -3880,7 +3880,7 @@ break; case EXPR_CXX_THIS: - S = new (Context) CXXThisExpr(Empty); + S = CXXThisExpr::CreateEmpty(Context); break; case EXPR_CXX_THROW: diff --git a/clang/test/CodeGenHLSL/this-reference.hlsl b/clang/test/CodeGenHLSL/this-reference.hlsl --- a/clang/test/CodeGenHLSL/this-reference.hlsl +++ b/clang/test/CodeGenHLSL/this-reference.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s | FileCheck %s +// 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 struct Pair { int First; @@ -26,3 +26,9 @@ // CHECK-NEXT: store i32 %call, ptr %First, align 4 // CHECK-NEXT: %call1 = call noundef float @"?getSecond@Pair@@QAAMXZ"(ptr noundef nonnull align 4 dereferenceable(8) %Vals) // CHECK-NEXT: %Second = getelementptr inbounds %struct.Pair, ptr %Vals, i32 0, i32 1 + +// CHECK: [[Pair:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Pair" +// CHECK: [[getFirst:![0-9]+]] = distinct !DISubprogram(name: "getFirst" +// CHECK-SAME: scope: [[Pair]] +// CHECK: [[FirstThis:![0-9]+]] = !DILocalVariable(name: "this", arg: 1, scope: [[getFirst]], type: [[thisType:![0-9]+]] +// CHECK: [[thisType]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[Pair]], size: 32)