|
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"
|
|
64 | 65 | #include "llvm/ADT/StringExtras.h"
|
65 | 66 | #include "llvm/Demangle/Demangle.h"
|
66 | 67 | #include "llvm/IR/Assumptions.h"
|
| 68 | +#include "llvm/IR/DerivedTypes.h" |
67 | 69 | #include "llvm/MC/MCSectionMachO.h"
|
68 | 70 | #include "llvm/Support/Error.h"
|
69 | 71 | #include "llvm/Support/MathExtras.h"
|
@@ -3867,6 +3869,119 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
3867 | 3869 | S.Context, AL, EncodingIndices.data(), EncodingIndices.size()));
|
3868 | 3870 | }
|
3869 | 3871 |
|
| 3872 | +LifetimeCaptureByAttr *Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL, |
| 3873 | + StringRef ParamName) { |
| 3874 | + // Atleast one capture by is required. |
| 3875 | + if (AL.getNumArgs() == 0) { |
| 3876 | + Diag(AL.getLoc(), diag::err_capture_by_attribute_no_entity) |
| 3877 | + << AL.getRange(); |
| 3878 | + return nullptr; |
| 3879 | + } |
| 3880 | + unsigned N = AL.getNumArgs(); |
| 3881 | + auto ParamIdents = |
| 3882 | + MutableArrayRef<IdentifierInfo *>(new (Context) IdentifierInfo *[N], N); |
| 3883 | + auto ParamLocs = |
| 3884 | + MutableArrayRef<SourceLocation>(new (Context) SourceLocation[N], N); |
| 3885 | + bool IsValid = true; |
| 3886 | + for (unsigned I = 0; I < N; ++I) { |
| 3887 | + if (AL.isArgExpr(I)) { |
| 3888 | + Expr *E = AL.getArgAsExpr(I); |
| 3889 | + Diag(E->getExprLoc(), diag::err_capture_by_attribute_argument_unknown) |
| 3890 | + << E << E->getExprLoc(); |
| 3891 | + IsValid = false; |
| 3892 | + continue; |
| 3893 | + } |
| 3894 | + assert(AL.isArgIdent(I)); |
| 3895 | + IdentifierLoc *IdLoc = AL.getArgAsIdent(I); |
| 3896 | + if (IdLoc->Ident->getName() == ParamName) { |
| 3897 | + Diag(IdLoc->Loc, diag::err_capture_by_references_itself) << IdLoc->Loc; |
| 3898 | + IsValid = false; |
| 3899 | + continue; |
| 3900 | + } |
| 3901 | + ParamIdents[I] = IdLoc->Ident; |
| 3902 | + ParamLocs[I] = IdLoc->Loc; |
| 3903 | + } |
| 3904 | + if (!IsValid) |
| 3905 | + return nullptr; |
| 3906 | + SmallVector<int> FakeParamIndices(N, LifetimeCaptureByAttr::INVALID); |
| 3907 | + auto *CapturedBy = |
| 3908 | + LifetimeCaptureByAttr::Create(Context, FakeParamIndices.data(), N, AL); |
| 3909 | + CapturedBy->setArgs(ParamIdents, ParamLocs); |
| 3910 | + return CapturedBy; |
| 3911 | +} |
| 3912 | + |
| 3913 | +static void handleLifetimeCaptureByAttr(Sema &S, Decl *D, |
| 3914 | + const ParsedAttr &AL) { |
| 3915 | + // Do not allow multiple attributes. |
| 3916 | + if (D->hasAttr<LifetimeCaptureByAttr>()) { |
| 3917 | + S.Diag(AL.getLoc(), diag::err_capture_by_attribute_multiple) |
| 3918 | + << AL.getRange(); |
| 3919 | + return; |
| 3920 | + } |
| 3921 | + auto *PVD = dyn_cast<ParmVarDecl>(D); |
| 3922 | + assert(PVD); |
| 3923 | + auto *CaptureByAttr = S.ParseLifetimeCaptureByAttr(AL, PVD->getName()); |
| 3924 | + if (CaptureByAttr) |
| 3925 | + D->addAttr(CaptureByAttr); |
| 3926 | +} |
| 3927 | + |
| 3928 | +void Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) { |
| 3929 | + bool HasImplicitThisParam = isInstanceMethod(FD); |
| 3930 | + SmallVector<LifetimeCaptureByAttr *, 1> Attrs; |
| 3931 | + for (ParmVarDecl *PVD : FD->parameters()) |
| 3932 | + if (auto *A = PVD->getAttr<LifetimeCaptureByAttr>()) |
| 3933 | + Attrs.push_back(A); |
| 3934 | + if (HasImplicitThisParam) { |
| 3935 | + TypeSourceInfo *TSI = FD->getTypeSourceInfo(); |
| 3936 | + if (!TSI) |
| 3937 | + return; |
| 3938 | + AttributedTypeLoc ATL; |
| 3939 | + for (TypeLoc TL = TSI->getTypeLoc(); |
| 3940 | + (ATL = TL.getAsAdjusted<AttributedTypeLoc>()); |
| 3941 | + TL = ATL.getModifiedLoc()) { |
| 3942 | + if (auto *A = ATL.getAttrAs<LifetimeCaptureByAttr>()) |
| 3943 | + Attrs.push_back(const_cast<LifetimeCaptureByAttr *>(A)); |
| 3944 | + } |
| 3945 | + } |
| 3946 | + if (Attrs.empty()) |
| 3947 | + return; |
| 3948 | + llvm::StringMap<int> NameIdxMapping = { |
| 3949 | + {"global", LifetimeCaptureByAttr::GLOBAL}, |
| 3950 | + {"unknown", LifetimeCaptureByAttr::UNKNOWN}}; |
| 3951 | + int Idx = 0; |
| 3952 | + if (HasImplicitThisParam) { |
| 3953 | + NameIdxMapping["this"] = 0; |
| 3954 | + Idx++; |
| 3955 | + } |
| 3956 | + for (const ParmVarDecl *PVD : FD->parameters()) |
| 3957 | + NameIdxMapping[PVD->getName()] = Idx++; |
| 3958 | + auto DisallowReservedParams = [&](StringRef Reserved) { |
| 3959 | + for (const ParmVarDecl *PVD : FD->parameters()) |
| 3960 | + if (PVD->getName() == Reserved) |
| 3961 | + Diag(PVD->getLocation(), diag::err_capture_by_param_uses_reserved_name) |
| 3962 | + << (PVD->getName() == "unknown"); |
| 3963 | + }; |
| 3964 | + for (auto *CapturedBy : Attrs) { |
| 3965 | + const auto &Entities = CapturedBy->getArgIdents(); |
| 3966 | + for (size_t I = 0; I < Entities.size(); ++I) { |
| 3967 | + StringRef Name = Entities[I]->getName(); |
| 3968 | + auto It = NameIdxMapping.find(Name); |
| 3969 | + if (It == NameIdxMapping.end()) { |
| 3970 | + auto Loc = CapturedBy->getArgLocs()[I]; |
| 3971 | + if (!HasImplicitThisParam && Name == "this") |
| 3972 | + Diag(Loc, diag::err_capture_by_implicit_this_not_available) << Loc; |
| 3973 | + else |
| 3974 | + Diag(Loc, diag::err_capture_by_attribute_argument_unknown) |
| 3975 | + << Entities[I] << Loc; |
| 3976 | + continue; |
| 3977 | + } |
| 3978 | + if (Name == "unknown" || Name == "global") |
| 3979 | + DisallowReservedParams(Name); |
| 3980 | + CapturedBy->setParamIdx(I, It->second); |
| 3981 | + } |
| 3982 | + } |
| 3983 | +} |
| 3984 | + |
3870 | 3985 | static bool isFunctionLike(const Type &T) {
|
3871 | 3986 | // Check for explicit function types.
|
3872 | 3987 | // 'called_once' is only supported in Objective-C and it has
|
@@ -6644,6 +6759,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
|
6644 | 6759 | case ParsedAttr::AT_Callback:
|
6645 | 6760 | handleCallbackAttr(S, D, AL);
|
6646 | 6761 | break;
|
| 6762 | + case ParsedAttr::AT_LifetimeCaptureBy: |
| 6763 | + handleLifetimeCaptureByAttr(S, D, AL); |
| 6764 | + break; |
6647 | 6765 | case ParsedAttr::AT_CalledOnce:
|
6648 | 6766 | handleCalledOnceAttr(S, D, AL);
|
6649 | 6767 | break;
|
|
0 commit comments