Skip to content

Commit 28a5f09

Browse files
committed
Fix compile time regression and memory leak
1 parent 3c233df commit 28a5f09

File tree

3 files changed

+46
-43
lines changed

3 files changed

+46
-43
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,25 +1896,22 @@ def LifetimeCaptureBy : DeclOrTypeAttr {
18961896
let Documentation = [LifetimeCaptureByDocs];
18971897
let AdditionalMembers = [{
18981898
private:
1899-
SmallVector<IdentifierInfo*, 1> ArgIdents;
1900-
SmallVector<SourceLocation, 1> ArgLocs;
1899+
IdentifierInfo** ArgIdents;
1900+
SourceLocation* ArgLocs;
19011901

19021902
public:
19031903
static constexpr int THIS = 0;
19041904
static constexpr int INVALID = -1;
19051905
static constexpr int UNKNOWN = -2;
19061906
static constexpr int GLOBAL = -3;
19071907

1908-
void setArgs(SmallVector<IdentifierInfo*>&& Idents,
1909-
SmallVector<SourceLocation>&& Locs) {
1910-
assert(Idents.size() == Locs.size());
1911-
assert(Idents.size() == params_Size);
1912-
ArgIdents = std::move(Idents);
1913-
ArgLocs = std::move(Locs);
1908+
void setArgs(IdentifierInfo **Idents, SourceLocation *Locs) {
1909+
ArgIdents = Idents;
1910+
ArgLocs = Locs;
19141911
}
19151912

1916-
ArrayRef<IdentifierInfo*> getArgIdents() const { return ArgIdents; }
1917-
ArrayRef<SourceLocation> getArgLocs() const { return ArgLocs; }
1913+
auto getArgIdents() const { return ArrayRef<IdentifierInfo*>(ArgIdents, params_Size); }
1914+
auto getArgLocs() const { return ArrayRef<SourceLocation>(ArgLocs, params_Size); }
19181915
void setParamIdx(size_t Idx, int Val) {
19191916
assert(Idx < params_Size);
19201917
params_[Idx] = Val;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include "llvm/ADT/StringExtras.h"
6666
#include "llvm/Demangle/Demangle.h"
6767
#include "llvm/IR/Assumptions.h"
68+
#include "llvm/IR/DerivedTypes.h"
6869
#include "llvm/MC/MCSectionMachO.h"
6970
#include "llvm/Support/Error.h"
7071
#include "llvm/Support/MathExtras.h"
@@ -3876,33 +3877,38 @@ LifetimeCaptureByAttr *Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL,
38763877
<< AL.getRange();
38773878
return nullptr;
38783879
}
3879-
SmallVector<IdentifierInfo *, 1> ParamIdents;
3880-
SmallVector<SourceLocation, 1> ParamLocs;
3881-
for (unsigned I = 0; I < AL.getNumArgs(); ++I) {
3880+
unsigned N = AL.getNumArgs();
3881+
IdentifierInfo **ParamIdents = new (Context) IdentifierInfo *[N];
3882+
SourceLocation *ParamLocs = new (Context) SourceLocation[N];
3883+
bool IsValid = true;
3884+
for (unsigned I = 0; I < N; ++I) {
38823885
if (AL.isArgExpr(I)) {
38833886
Expr *E = AL.getArgAsExpr(I);
38843887
Diag(E->getExprLoc(), diag::err_capture_by_attribute_argument_unknown)
38853888
<< E << E->getExprLoc();
3889+
IsValid = false;
38863890
continue;
38873891
}
38883892
assert(AL.isArgIdent(I));
38893893
IdentifierLoc *IdLoc = AL.getArgAsIdent(I);
38903894
if (IdLoc->Ident->getName() == ParamName) {
38913895
Diag(IdLoc->Loc, diag::err_capture_by_references_itself) << IdLoc->Loc;
3896+
IsValid = false;
38923897
continue;
38933898
}
3894-
ParamIdents.push_back(IdLoc->Ident);
3895-
ParamLocs.push_back(IdLoc->Loc);
3899+
ParamIdents[I] = IdLoc->Ident;
3900+
ParamLocs[I] = IdLoc->Loc;
38963901
}
3897-
SmallVector<int, 1> FakeParamIndices(ParamIdents.size(),
3898-
LifetimeCaptureByAttr::INVALID);
3902+
if (!IsValid)
3903+
return nullptr;
3904+
SmallVector<int> FakeParamIndices(N, LifetimeCaptureByAttr::INVALID);
38993905
LifetimeCaptureByAttr *CapturedBy = ::new (Context) LifetimeCaptureByAttr(
39003906
Context, AL, FakeParamIndices.data(), FakeParamIndices.size());
3901-
CapturedBy->setArgs(std::move(ParamIdents), std::move(ParamLocs));
3907+
CapturedBy->setArgs(ParamIdents, ParamLocs);
39023908
return CapturedBy;
39033909
}
39043910

3905-
static void HandleLifetimeCaptureByAttr(Sema &S, Decl *D,
3911+
static void handleLifetimeCaptureByAttr(Sema &S, Decl *D,
39063912
const ParsedAttr &AL) {
39073913
// Do not allow multiple attributes.
39083914
if (D->hasAttr<LifetimeCaptureByAttr>()) {
@@ -3919,10 +3925,27 @@ static void HandleLifetimeCaptureByAttr(Sema &S, Decl *D,
39193925

39203926
void Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
39213927
bool HasImplicitThisParam = isInstanceMethod(FD);
3922-
3923-
llvm::StringMap<int> NameIdxMapping;
3924-
NameIdxMapping["global"] = LifetimeCaptureByAttr::GLOBAL;
3925-
NameIdxMapping["unknown"] = LifetimeCaptureByAttr::UNKNOWN;
3928+
SmallVector<LifetimeCaptureByAttr *, 1> Attrs;
3929+
for (ParmVarDecl *PVD : FD->parameters())
3930+
if (auto *A = PVD->getAttr<LifetimeCaptureByAttr>())
3931+
Attrs.push_back(A);
3932+
if (HasImplicitThisParam) {
3933+
TypeSourceInfo *TSI = FD->getTypeSourceInfo();
3934+
if (!TSI)
3935+
return;
3936+
AttributedTypeLoc ATL;
3937+
for (TypeLoc TL = TSI->getTypeLoc();
3938+
(ATL = TL.getAsAdjusted<AttributedTypeLoc>());
3939+
TL = ATL.getModifiedLoc()) {
3940+
if (auto *A = ATL.getAttrAs<LifetimeCaptureByAttr>())
3941+
Attrs.push_back(const_cast<LifetimeCaptureByAttr *>(A));
3942+
}
3943+
}
3944+
if (Attrs.empty())
3945+
return;
3946+
llvm::StringMap<int> NameIdxMapping = {
3947+
{"global", LifetimeCaptureByAttr::GLOBAL},
3948+
{"unknown", LifetimeCaptureByAttr::UNKNOWN}};
39263949
int Idx = 0;
39273950
if (HasImplicitThisParam) {
39283951
NameIdxMapping["this"] = 0;
@@ -3936,9 +3959,7 @@ void Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
39363959
Diag(PVD->getLocation(), diag::err_capture_by_param_uses_reserved_name)
39373960
<< (PVD->getName() == "unknown");
39383961
};
3939-
auto HandleCaptureBy = [&](LifetimeCaptureByAttr *CapturedBy) {
3940-
if (!CapturedBy)
3941-
return;
3962+
for (auto *CapturedBy : Attrs) {
39423963
const auto &Entities = CapturedBy->getArgIdents();
39433964
for (size_t I = 0; I < Entities.size(); ++I) {
39443965
StringRef Name = Entities[I]->getName();
@@ -3956,22 +3977,6 @@ void Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) {
39563977
DisallowReservedParams(Name);
39573978
CapturedBy->setParamIdx(I, It->second);
39583979
}
3959-
};
3960-
for (ParmVarDecl *PVD : FD->parameters())
3961-
HandleCaptureBy(PVD->getAttr<LifetimeCaptureByAttr>());
3962-
if (!HasImplicitThisParam)
3963-
return;
3964-
TypeSourceInfo *TSI = FD->getTypeSourceInfo();
3965-
if (!TSI)
3966-
return;
3967-
AttributedTypeLoc ATL;
3968-
for (TypeLoc TL = TSI->getTypeLoc();
3969-
(ATL = TL.getAsAdjusted<AttributedTypeLoc>());
3970-
TL = ATL.getModifiedLoc()) {
3971-
auto *A = ATL.getAttrAs<LifetimeCaptureByAttr>();
3972-
if (!A)
3973-
continue;
3974-
HandleCaptureBy(const_cast<LifetimeCaptureByAttr *>(A));
39753980
}
39763981
}
39773982

@@ -6753,7 +6758,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
67536758
handleCallbackAttr(S, D, AL);
67546759
break;
67556760
case ParsedAttr::AT_LifetimeCaptureBy:
6756-
HandleLifetimeCaptureByAttr(S, D, AL);
6761+
handleLifetimeCaptureByAttr(S, D, AL);
67576762
break;
67586763
case ParsedAttr::AT_CalledOnce:
67596764
handleCalledOnceAttr(S, D, AL);

clang/test/SemaCXX/attr-lifetime-capture-by.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ void nonMember(
2222
x7)]], // expected-error {{'lifetime_capture_by' argument references itself}}
2323
const int &x8 [[clang::lifetime_capture_by(global)]],
2424
const int &x9 [[clang::lifetime_capture_by(unknown)]],
25+
const int &test_memory_leak[[clang::lifetime_capture_by(x1,x2, x3, x4, x5, x6, x7, x8, x9)]],
2526
const S& u
2627
)
2728
{

0 commit comments

Comments
 (0)