|
14 | 14 | #include "clang/AST/ASTContext.h" |
15 | 15 | #include "clang/AST/ASTMutationListener.h" |
16 | 16 | #include "clang/AST/CXXInheritance.h" |
| 17 | +#include "clang/AST/Decl.h" |
17 | 18 | #include "clang/AST/DeclCXX.h" |
18 | 19 | #include "clang/AST/DeclObjC.h" |
19 | 20 | #include "clang/AST/DeclTemplate.h" |
@@ -3834,6 +3835,81 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) { |
3834 | 3835 | S.Context, AL, EncodingIndices.data(), EncodingIndices.size())); |
3835 | 3836 | } |
3836 | 3837 |
|
| 3838 | +static void HandleLifetimeCaptureByAttr(Sema &S, Decl *D, |
| 3839 | + const ParsedAttr &AL) { |
| 3840 | + // Atleast one capture by is required. TODO() |
| 3841 | + if (AL.getNumArgs() == 0) { |
| 3842 | + S.Diag(AL.getLoc(), diag::err_capture_by_attribute_no_entity) |
| 3843 | + << AL.getRange(); |
| 3844 | + return; |
| 3845 | + } |
| 3846 | + |
| 3847 | + ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D); |
| 3848 | + if (!PVD) { |
| 3849 | + llvm::errs() << "Should be attached only to a function parameter;\n"; |
| 3850 | + return; |
| 3851 | + } |
| 3852 | + SmallVector<IdentifierInfo *, 1> ParamIdents; |
| 3853 | + SmallVector<SourceLocation, 1> ParamLocs; |
| 3854 | + for (unsigned I = 0; I < AL.getNumArgs(); ++I) { |
| 3855 | + if (AL.isArgIdent(I)) { |
| 3856 | + IdentifierLoc *IdLoc = AL.getArgAsIdent(I); |
| 3857 | + ParamIdents.push_back(IdLoc->Ident); |
| 3858 | + ParamLocs.push_back(IdLoc->Loc); |
| 3859 | + } else if (AL.isArgExpr(I)) { |
| 3860 | + Expr *E = AL.getArgAsExpr(I); |
| 3861 | + S.Diag(E->getExprLoc(), diag::err_capture_by_attribute_argument_unknown) |
| 3862 | + << E << E->getExprLoc(); |
| 3863 | + } |
| 3864 | + } |
| 3865 | + // Do not allow multiple attributes. |
| 3866 | + if (D->hasAttr<LifetimeCaptureByAttr>()) { |
| 3867 | + S.Diag(AL.getLoc(), diag::err_capture_by_attribute_multiple) |
| 3868 | + << AL.getRange(); |
| 3869 | + return; |
| 3870 | + } |
| 3871 | + SmallVector<int, 1> FakeParamIndices(ParamIdents.size(), -1); |
| 3872 | + LifetimeCaptureByAttr *CapturedBy = ::new (S.Context) LifetimeCaptureByAttr( |
| 3873 | + S.Context, AL, FakeParamIndices.data(), FakeParamIndices.size()); |
| 3874 | + CapturedBy->setArgs(std::move(ParamIdents), std::move(ParamLocs)); |
| 3875 | + D->addAttr(CapturedBy); |
| 3876 | +} |
| 3877 | + |
| 3878 | +void Sema::lazyProcessLifetimeCaptureByParams(FunctionDecl *FD) { |
| 3879 | + bool HasImplicitThisParam = isInstanceMethod(FD); |
| 3880 | + |
| 3881 | + llvm::StringMap<std::pair<int, QualType>> NameIdxMapping; |
| 3882 | + NameIdxMapping["global"] = {-1, {}}; |
| 3883 | + NameIdxMapping["unknown"] = {-1, {}}; |
| 3884 | + int Idx = 0; |
| 3885 | + if (HasImplicitThisParam) { |
| 3886 | + NameIdxMapping["this"] = {0, dyn_cast<CXXMethodDecl>(FD)->getThisType()}; |
| 3887 | + Idx++; |
| 3888 | + } |
| 3889 | + for (const ParmVarDecl *PVD : FD->parameters()) |
| 3890 | + NameIdxMapping[PVD->getName()] = {Idx++, PVD->getType()}; |
| 3891 | + for (ParmVarDecl *PVD : FD->parameters()) { |
| 3892 | + auto *CapturedBy = PVD->getAttr<LifetimeCaptureByAttr>(); |
| 3893 | + if (!CapturedBy) |
| 3894 | + continue; |
| 3895 | + const auto &Entities = CapturedBy->getArgIdents(); |
| 3896 | + for (size_t I = 0; I < Entities.size(); ++I) { |
| 3897 | + StringRef Name = Entities[I]->getName(); |
| 3898 | + auto It = NameIdxMapping.find(Name); |
| 3899 | + if (It == NameIdxMapping.end()) { |
| 3900 | + auto Loc = CapturedBy->getArgLocs()[I]; |
| 3901 | + if (!HasImplicitThisParam && Name == "this") |
| 3902 | + Diag(Loc, diag::err_capture_by_implicit_this_not_available) << Loc; |
| 3903 | + else |
| 3904 | + Diag(Loc, diag::err_capture_by_attribute_argument_unknown) |
| 3905 | + << Entities[I] << Loc; |
| 3906 | + continue; |
| 3907 | + } |
| 3908 | + CapturedBy->setParamIdx(I, It->second.first); |
| 3909 | + } |
| 3910 | + } |
| 3911 | +} |
| 3912 | + |
3837 | 3913 | static bool isFunctionLike(const Type &T) { |
3838 | 3914 | // Check for explicit function types. |
3839 | 3915 | // 'called_once' is only supported in Objective-C and it has |
@@ -6618,6 +6694,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, |
6618 | 6694 | case ParsedAttr::AT_Callback: |
6619 | 6695 | handleCallbackAttr(S, D, AL); |
6620 | 6696 | break; |
| 6697 | + case ParsedAttr::AT_LifetimeCaptureBy: |
| 6698 | + HandleLifetimeCaptureByAttr(S, D, AL); |
| 6699 | + break; |
6621 | 6700 | case ParsedAttr::AT_CalledOnce: |
6622 | 6701 | handleCalledOnceAttr(S, D, AL); |
6623 | 6702 | break; |
|
0 commit comments