Skip to content

Commit 67b6824

Browse files
authored
Merge branch 'main' into issue_161208
2 parents 9cac506 + 44331d2 commit 67b6824

File tree

189 files changed

+3617
-4836
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

189 files changed

+3617
-4836
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,34 +3273,43 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
32733273
}
32743274

32753275
if (T->isArrayType()) {
3276-
const ConstantArrayType *CAT =
3277-
Ctx.getASTContext().getAsConstantArrayType(E->getType());
3278-
if (!CAT)
3279-
return false;
3280-
3281-
size_t NumElems = CAT->getZExtSize();
32823276
const Function *Func = getFunction(E->getConstructor());
32833277
if (!Func)
32843278
return false;
32853279

3286-
// FIXME(perf): We're calling the constructor once per array element here,
3287-
// in the old intepreter we had a special-case for trivial constructors.
3288-
for (size_t I = 0; I != NumElems; ++I) {
3289-
if (!this->emitConstUint64(I, E))
3290-
return false;
3291-
if (!this->emitArrayElemPtrUint64(E))
3292-
return false;
3280+
if (!this->emitDupPtr(E))
3281+
return false;
32933282

3294-
// Constructor arguments.
3295-
for (const auto *Arg : E->arguments()) {
3296-
if (!this->visit(Arg))
3297-
return false;
3283+
std::function<bool(QualType)> initArrayDimension;
3284+
initArrayDimension = [&](QualType T) -> bool {
3285+
if (!T->isArrayType()) {
3286+
// Constructor arguments.
3287+
for (const auto *Arg : E->arguments()) {
3288+
if (!this->visit(Arg))
3289+
return false;
3290+
}
3291+
3292+
return this->emitCall(Func, 0, E);
32983293
}
32993294

3300-
if (!this->emitCall(Func, 0, E))
3295+
const ConstantArrayType *CAT =
3296+
Ctx.getASTContext().getAsConstantArrayType(T);
3297+
if (!CAT)
33013298
return false;
3302-
}
3303-
return true;
3299+
QualType ElemTy = CAT->getElementType();
3300+
unsigned NumElems = CAT->getZExtSize();
3301+
for (size_t I = 0; I != NumElems; ++I) {
3302+
if (!this->emitConstUint64(I, E))
3303+
return false;
3304+
if (!this->emitArrayElemPtrUint64(E))
3305+
return false;
3306+
if (!initArrayDimension(ElemTy))
3307+
return false;
3308+
}
3309+
return this->emitPopPtr(E);
3310+
};
3311+
3312+
return initArrayDimension(E->getType());
33043313
}
33053314

33063315
return false;
@@ -3599,8 +3608,6 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
35993608
if (PlacementDest) {
36003609
if (!this->visit(PlacementDest))
36013610
return false;
3602-
if (!this->emitStartLifetime(E))
3603-
return false;
36043611
if (!this->emitGetLocal(SizeT, ArrayLen, E))
36053612
return false;
36063613
if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))
@@ -3740,10 +3747,9 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
37403747
if (PlacementDest) {
37413748
if (!this->visit(PlacementDest))
37423749
return false;
3743-
if (!this->emitStartLifetime(E))
3744-
return false;
37453750
if (!this->emitCheckNewTypeMismatch(E, E))
37463751
return false;
3752+
37473753
} else {
37483754
// Allocate just one element.
37493755
if (!this->emitAlloc(Desc, E))

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1903,12 +1903,19 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
19031903
if (Ptr.inUnion() && Ptr.getBase().getRecord()->isUnion())
19041904
Ptr.activate();
19051905

1906+
if (Ptr.isZero()) {
1907+
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
1908+
<< AK_Construct;
1909+
return false;
1910+
}
1911+
19061912
if (!Ptr.isBlockPointer())
19071913
return false;
19081914

1915+
startLifetimeRecurse(Ptr);
1916+
19091917
// Similar to CheckStore(), but with the additional CheckTemporary() call and
19101918
// the AccessKinds are different.
1911-
19121919
if (!Ptr.block()->isAccessible()) {
19131920
if (!CheckExtern(S, OpPC, Ptr))
19141921
return false;

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -866,19 +866,13 @@ def Free : Opcode {
866866
let Args = [ArgBool, ArgBool];
867867
}
868868

869-
def CheckNewTypeMismatch : Opcode {
870-
let Args = [ArgExpr];
871-
}
872-
873-
def InvalidNewDeleteExpr : Opcode {
874-
let Args = [ArgExpr];
875-
}
876-
869+
def CheckNewTypeMismatch : Opcode { let Args = [ArgExpr]; }
877870
def CheckNewTypeMismatchArray : Opcode {
878871
let Types = [IntegerTypeClass];
879872
let Args = [ArgExpr];
880873
let HasGroup = 1;
881874
}
875+
def InvalidNewDeleteExpr : Opcode { let Args = [ArgExpr]; }
882876

883877
def IsConstantContext: Opcode;
884878
def CheckAllocations : Opcode;

clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ class RawPtrRefLambdaCapturesChecker
5050
llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIgnore;
5151
llvm::DenseSet<const LambdaExpr *> LambdasToIgnore;
5252
llvm::DenseSet<const ValueDecl *> ProtectedThisDecls;
53+
llvm::DenseSet<const CallExpr *> CallToIgnore;
5354
llvm::DenseSet<const CXXConstructExpr *> ConstructToIgnore;
55+
llvm::DenseMap<const VarDecl *, const LambdaExpr *> LambdaOwnerMap;
5456

5557
QualType ClsType;
5658

@@ -101,10 +103,60 @@ class RawPtrRefLambdaCapturesChecker
101103
auto *Init = VD->getInit();
102104
if (!Init)
103105
return true;
104-
auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts());
105-
if (!L)
106+
if (auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts())) {
107+
LambdasToIgnore.insert(L); // Evaluate lambdas in VisitDeclRefExpr.
108+
return true;
109+
}
110+
if (!VD->hasLocalStorage())
106111
return true;
107-
LambdasToIgnore.insert(L); // Evaluate lambdas in VisitDeclRefExpr.
112+
if (auto *E = dyn_cast<ExprWithCleanups>(Init))
113+
Init = E->getSubExpr();
114+
if (auto *E = dyn_cast<CXXBindTemporaryExpr>(Init))
115+
Init = E->getSubExpr();
116+
if (auto *CE = dyn_cast<CallExpr>(Init)) {
117+
if (auto *Callee = CE->getDirectCallee()) {
118+
auto FnName = safeGetName(Callee);
119+
unsigned ArgCnt = CE->getNumArgs();
120+
if (FnName == "makeScopeExit" && ArgCnt == 1) {
121+
auto *Arg = CE->getArg(0);
122+
if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
123+
Arg = E->getSubExpr();
124+
if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
125+
LambdaOwnerMap.insert(std::make_pair(VD, L));
126+
CallToIgnore.insert(CE);
127+
LambdasToIgnore.insert(L);
128+
}
129+
} else if (FnName == "makeVisitor") {
130+
for (unsigned ArgIndex = 0; ArgIndex < ArgCnt; ++ArgIndex) {
131+
auto *Arg = CE->getArg(ArgIndex);
132+
if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
133+
Arg = E->getSubExpr();
134+
if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
135+
LambdaOwnerMap.insert(std::make_pair(VD, L));
136+
CallToIgnore.insert(CE);
137+
LambdasToIgnore.insert(L);
138+
}
139+
}
140+
}
141+
}
142+
} else if (auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
143+
if (auto *Ctor = CE->getConstructor()) {
144+
if (auto *Cls = Ctor->getParent()) {
145+
auto FnName = safeGetName(Cls);
146+
unsigned ArgCnt = CE->getNumArgs();
147+
if (FnName == "ScopeExit" && ArgCnt == 1) {
148+
auto *Arg = CE->getArg(0);
149+
if (auto *E = dyn_cast<MaterializeTemporaryExpr>(Arg))
150+
Arg = E->getSubExpr();
151+
if (auto *L = dyn_cast<LambdaExpr>(Arg)) {
152+
LambdaOwnerMap.insert(std::make_pair(VD, L));
153+
ConstructToIgnore.insert(CE);
154+
LambdasToIgnore.insert(L);
155+
}
156+
}
157+
}
158+
}
159+
}
108160
return true;
109161
}
110162

@@ -114,6 +166,12 @@ class RawPtrRefLambdaCapturesChecker
114166
auto *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl());
115167
if (!VD)
116168
return true;
169+
if (auto It = LambdaOwnerMap.find(VD); It != LambdaOwnerMap.end()) {
170+
auto *L = It->second;
171+
Checker->visitLambdaExpr(L, shouldCheckThis() && !hasProtectedThis(L),
172+
ClsType);
173+
return true;
174+
}
117175
auto *Init = VD->getInit();
118176
if (!Init)
119177
return true;
@@ -167,10 +225,14 @@ class RawPtrRefLambdaCapturesChecker
167225
}
168226

169227
bool VisitCallExpr(CallExpr *CE) override {
228+
if (CallToIgnore.contains(CE))
229+
return true;
170230
checkCalleeLambda(CE);
171-
if (auto *Callee = CE->getDirectCallee())
231+
if (auto *Callee = CE->getDirectCallee()) {
232+
if (isVisitFunction(CE, Callee))
233+
return true;
172234
checkParameters(CE, Callee);
173-
else if (auto *CalleeE = CE->getCallee()) {
235+
} else if (auto *CalleeE = CE->getCallee()) {
174236
if (auto *DRE = dyn_cast<DeclRefExpr>(CalleeE->IgnoreParenCasts())) {
175237
if (auto *Callee = dyn_cast_or_null<FunctionDecl>(DRE->getDecl()))
176238
checkParameters(CE, Callee);
@@ -179,6 +241,34 @@ class RawPtrRefLambdaCapturesChecker
179241
return true;
180242
}
181243

244+
bool isVisitFunction(CallExpr *CallExpr, FunctionDecl *FnDecl) {
245+
bool IsVisitFn = safeGetName(FnDecl) == "visit";
246+
if (!IsVisitFn)
247+
return false;
248+
bool ArgCnt = CallExpr->getNumArgs();
249+
if (!ArgCnt)
250+
return false;
251+
auto *Ns = FnDecl->getParent();
252+
if (!Ns)
253+
return false;
254+
auto NsName = safeGetName(Ns);
255+
if (NsName != "WTF" && NsName != "std")
256+
return false;
257+
auto *Arg = CallExpr->getArg(0);
258+
if (!Arg)
259+
return false;
260+
auto *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenCasts());
261+
if (!DRE)
262+
return false;
263+
auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
264+
if (!VD)
265+
return false;
266+
if (!LambdaOwnerMap.contains(VD))
267+
return false;
268+
DeclRefExprsToIgnore.insert(DRE);
269+
return true;
270+
}
271+
182272
void checkParameters(CallExpr *CE, FunctionDecl *Callee) {
183273
unsigned ArgIndex = isa<CXXOperatorCallExpr>(CE);
184274
bool TreatAllArgsAsNoEscape = shouldTreatAllArgAsNoEscape(Callee);
@@ -280,7 +370,7 @@ class RawPtrRefLambdaCapturesChecker
280370
LambdasToIgnore.insert(L);
281371
}
282372

283-
bool hasProtectedThis(LambdaExpr *L) {
373+
bool hasProtectedThis(const LambdaExpr *L) {
284374
for (const LambdaCapture &OtherCapture : L->captures()) {
285375
if (!OtherCapture.capturesVariable())
286376
continue;
@@ -378,7 +468,8 @@ class RawPtrRefLambdaCapturesChecker
378468
visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
379469
}
380470

381-
void visitLambdaExpr(LambdaExpr *L, bool shouldCheckThis, const QualType T,
471+
void visitLambdaExpr(const LambdaExpr *L, bool shouldCheckThis,
472+
const QualType T,
382473
bool ignoreParamVarDecl = false) const {
383474
if (TFA.isTrivial(L->getBody()))
384475
return;
@@ -410,7 +501,7 @@ class RawPtrRefLambdaCapturesChecker
410501
}
411502

412503
void reportBug(const LambdaCapture &Capture, ValueDecl *CapturedVar,
413-
const QualType T, LambdaExpr *L) const {
504+
const QualType T, const LambdaExpr *L) const {
414505
assert(CapturedVar);
415506

416507
auto Location = Capture.getLocation();

clang/test/AST/ByteCode/arrays.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,3 +820,14 @@ namespace FAM {
820820
return 1;
821821
}
822822
}
823+
824+
namespace MultiDimConstructExpr {
825+
struct a {
826+
a *p = this;
827+
};
828+
struct b {
829+
a m[3][3];
830+
};
831+
constexpr b d;
832+
static_assert(d.m[2][1].p == &d.m[2][1]);
833+
}

clang/test/AST/ByteCode/placement-new.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,3 +494,32 @@ constexpr int modify_const_variable() {
494494
}
495495
static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \
496496
// both-note {{in call to}}
497+
498+
constexpr int nullDest() {
499+
new (nullptr) int{12}; // both-note {{construction of dereferenced null pointer}}
500+
return 0;
501+
}
502+
static_assert(nullDest() == 0); // both-error {{not an integral constant expression}} \
503+
// both-note {{in call to}}
504+
505+
constexpr int nullArrayDest() {
506+
new (nullptr) int{12}; // both-note {{construction of dereferenced null pointer}}
507+
return 0;
508+
}
509+
static_assert(nullArrayDest() == 0); // both-error {{not an integral constant expression}} \
510+
// both-note {{in call to}}
511+
512+
constexpr int intDest() {
513+
new ((void*)2) int{3}; // both-note {{cast that performs the conversions of a reinterpret_cast}}
514+
return 0;
515+
}
516+
static_assert(intDest() == 0); // both-error {{not an integral constant expression}} \
517+
// both-note {{in call to}}
518+
519+
constexpr int intDestArray() {
520+
new ((void*)2) int[4]; // both-note {{cast that performs the conversions of a reinterpret_cast}}
521+
return 0;
522+
}
523+
static_assert(intDestArray() == 0); // both-error {{not an integral constant expression}} \
524+
// both-note {{in call to}}
525+

0 commit comments

Comments
 (0)