Skip to content

Commit c33cc6e

Browse files
Merge branch 'llvm:main' into gh-101657
2 parents e4579f7 + a807bbe commit c33cc6e

36 files changed

+688
-446
lines changed

bolt/unittests/Core/MCPlusBuilder.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,15 @@ INSTANTIATE_TEST_SUITE_P(AArch64, MCPlusBuilderTester,
9090
::testing::Values(Triple::aarch64));
9191

9292
TEST_P(MCPlusBuilderTester, AliasX0) {
93-
uint64_t AliasesX0[] = {AArch64::W0, AArch64::X0, AArch64::W0_W1,
93+
uint64_t AliasesX0[] = {AArch64::W0, AArch64::W0_HI,
94+
AArch64::X0, AArch64::W0_W1,
9495
AArch64::X0_X1, AArch64::X0_X1_X2_X3_X4_X5_X6_X7};
9596
size_t AliasesX0Count = sizeof(AliasesX0) / sizeof(*AliasesX0);
9697
testRegAliases(Triple::aarch64, AArch64::X0, AliasesX0, AliasesX0Count);
9798
}
9899

99100
TEST_P(MCPlusBuilderTester, AliasSmallerX0) {
100-
uint64_t AliasesX0[] = {AArch64::W0, AArch64::X0};
101+
uint64_t AliasesX0[] = {AArch64::W0, AArch64::W0_HI, AArch64::X0};
101102
size_t AliasesX0Count = sizeof(AliasesX0) / sizeof(*AliasesX0);
102103
testRegAliases(Triple::aarch64, AArch64::X0, AliasesX0, AliasesX0Count, true);
103104
}

clang/lib/StaticAnalyzer/Core/BugReporter.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,6 +2416,28 @@ PathSensitiveBugReport::getRanges() const {
24162416
return Ranges;
24172417
}
24182418

2419+
static bool exitingDestructor(const ExplodedNode *N) {
2420+
// Need to loop here, as some times the Error node is already outside of the
2421+
// destructor context, and the previous node is an edge that is also outside.
2422+
while (N && !N->getLocation().getAs<StmtPoint>()) {
2423+
N = N->getFirstPred();
2424+
}
2425+
return N && isa<CXXDestructorDecl>(N->getLocationContext()->getDecl());
2426+
}
2427+
2428+
static const Stmt *
2429+
findReasonableStmtCloseToFunctionExit(const ExplodedNode *N) {
2430+
if (exitingDestructor(N)) {
2431+
// If we are exiting a destructor call, it is more useful to point to
2432+
// the next stmt which is usually the temporary declaration.
2433+
if (const Stmt *S = N->getNextStmtForDiagnostics())
2434+
return S;
2435+
// If next stmt is not found, it is likely the end of a top-level
2436+
// function analysis. find the last execution statement then.
2437+
}
2438+
return N->getPreviousStmtForDiagnostics();
2439+
}
2440+
24192441
PathDiagnosticLocation
24202442
PathSensitiveBugReport::getLocation() const {
24212443
assert(ErrorNode && "Cannot create a location with a null node.");
@@ -2433,15 +2455,7 @@ PathSensitiveBugReport::getLocation() const {
24332455
if (const ReturnStmt *RS = FE->getStmt())
24342456
return PathDiagnosticLocation::createBegin(RS, SM, LC);
24352457

2436-
// If we are exiting a destructor call, it is more useful to point to the
2437-
// next stmt which is usually the temporary declaration.
2438-
// For non-destructor and non-top-level calls, the next stmt will still
2439-
// refer to the last executed stmt of the body.
2440-
S = ErrorNode->getNextStmtForDiagnostics();
2441-
// If next stmt is not found, it is likely the end of a top-level function
2442-
// analysis. find the last execution statement then.
2443-
if (!S)
2444-
S = ErrorNode->getPreviousStmtForDiagnostics();
2458+
S = findReasonableStmtCloseToFunctionExit(ErrorNode);
24452459
}
24462460
if (!S)
24472461
S = ErrorNode->getNextStmtForDiagnostics();

clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ const Stmt *ExplodedNode::getStmtForDiagnostics() const {
349349

350350
const Stmt *ExplodedNode::getNextStmtForDiagnostics() const {
351351
for (const ExplodedNode *N = getFirstSucc(); N; N = N->getFirstSucc()) {
352+
if (N->getLocation().isPurgeKind())
353+
continue;
352354
if (const Stmt *S = N->getStmtForDiagnostics()) {
353355
// Check if the statement is '?' or '&&'/'||'. These are "merges",
354356
// not actual statement points.

clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,14 +353,19 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
353353
ExplodedNodeSet CleanedNodes;
354354
if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
355355
static SimpleProgramPointTag retValBind("ExprEngine", "Bind Return Value");
356-
PostStmt Loc(LastSt, calleeCtx, &retValBind);
356+
auto Loc = isa<ReturnStmt>(LastSt)
357+
? ProgramPoint{PostStmt(LastSt, calleeCtx, &retValBind)}
358+
: ProgramPoint{EpsilonPoint(calleeCtx, /*Data1=*/nullptr,
359+
/*Data2=*/nullptr, &retValBind)};
360+
const CFGBlock *PrePurgeBlock =
361+
isa<ReturnStmt>(LastSt) ? Blk : &CEBNode->getCFG().getExit();
357362
bool isNew;
358363
ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
359364
BindedRetNode->addPredecessor(CEBNode, G);
360365
if (!isNew)
361366
return;
362367

363-
NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
368+
NodeBuilderContext Ctx(getCoreEngine(), PrePurgeBlock, BindedRetNode);
364369
currBldrCtx = &Ctx;
365370
// Here, we call the Symbol Reaper with 0 statement and callee location
366371
// context, telling it to clean up everything in the callee's context

clang/test/Analysis/copy-elision.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -263,17 +263,17 @@ void testVariable() {
263263

264264
struct TestCtorInitializer {
265265
ClassWithDestructor c;
266-
TestCtorInitializer(AddressVector<ClassWithDestructor> &v)
267-
: c(ClassWithDestructor(v)) {}
268-
// no-elide-warning@-1 {{Address of stack memory associated with temporary \
269-
object of type 'ClassWithDestructor' is still referred \
270-
to by the caller variable 'v' upon returning to the caller}}
266+
TestCtorInitializer(AddressVector<ClassWithDestructor> &refParam)
267+
: c(ClassWithDestructor(refParam)) {}
271268
};
272269

273270
void testCtorInitializer() {
274271
AddressVector<ClassWithDestructor> v;
275272
{
276273
TestCtorInitializer t(v);
274+
// no-elide-warning@-1 {{Address of stack memory associated with temporary \
275+
object of type 'ClassWithDestructor' is still referred \
276+
to by the caller variable 'v' upon returning to the caller}}
277277
// Check if the last destructor is an automatic destructor.
278278
// A temporary destructor would have fired by now.
279279
#if ELIDE

clang/test/Analysis/cxx-uninitialized-object-unguarded-access.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ class UnguardedFieldThroughMethodTest {
163163
Volume = 0;
164164
break;
165165
case A:
166-
Area = 0; // expected-warning {{1 uninitialized field}}
167-
break;
166+
Area = 0;
167+
break; // expected-warning {{1 uninitialized field}}
168168
}
169169
}
170170

@@ -201,8 +201,8 @@ class UnguardedPublicFieldsTest {
201201
Volume = 0;
202202
break;
203203
case A:
204-
Area = 0; // expected-warning {{1 uninitialized field}}
205-
break;
204+
Area = 0;
205+
break; // expected-warning {{1 uninitialized field}}
206206
}
207207
}
208208

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -analyzer-output text -verify %s
2+
3+
typedef __typeof(sizeof(int)) size_t;
4+
void *malloc(size_t size);
5+
6+
void inf_loop_break_callee() {
7+
void* data = malloc(10); // expected-note{{Memory is allocated}}
8+
while (1) { // expected-note{{Loop condition is true}}
9+
(void)data;
10+
break; // No note that we jump to the line above from this break
11+
} // expected-note@-1{{Execution jumps to the end of the function}}
12+
} // expected-warning{{Potential leak of memory pointed to by 'data'}}
13+
// expected-note@-1 {{Potential leak of memory pointed to by 'data'}}
14+
15+
void inf_loop_break_caller() {
16+
inf_loop_break_callee(); // expected-note{{Calling 'inf_loop_break_callee'}}
17+
}
18+
19+
void inf_loop_break_top() {
20+
void* data = malloc(10); // expected-note{{Memory is allocated}}
21+
while (1) { // expected-note{{Loop condition is true}}
22+
(void)data;
23+
break; // No note that we jump to the line above from this break
24+
} // expected-note@-1{{Execution jumps to the end of the function}}
25+
} // expected-warning{{Potential leak of memory pointed to by 'data'}}
26+
// expected-note@-1 {{Potential leak of memory pointed to by 'data'}}

llvm/include/llvm/MC/MCRegisterInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ struct MCRegisterDesc {
129129

130130
// Is true for constant registers.
131131
bool IsConstant;
132+
133+
// Is true for artificial registers.
134+
bool IsArtificial;
132135
};
133136

134137
/// MCRegisterInfo base class - We assume that the target defines a static
@@ -396,6 +399,11 @@ class MCRegisterInfo {
396399
/// Returns true if the given register is constant.
397400
bool isConstant(MCRegister RegNo) const { return get(RegNo).IsConstant; }
398401

402+
/// Returns true if the given register is artificial, which means it
403+
/// represents a regunit that is not separately addressable but still needs to
404+
/// be modelled, such as the top 16-bits of a 32-bit GPR.
405+
bool isArtificial(MCRegister RegNo) const { return get(RegNo).IsArtificial; }
406+
399407
/// Return the number of registers this target has (useful for
400408
/// sizing arrays holding per register information)
401409
unsigned getNumRegs() const {

llvm/lib/MCA/HardwareUnits/RegisterFile.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ namespace mca {
2424

2525
const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
2626

27+
static std::function<bool(MCPhysReg)>
28+
isNonArtificial(const MCRegisterInfo &MRI) {
29+
return [&MRI](MCPhysReg R) { return !MRI.isArtificial(R); };
30+
}
31+
2732
WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
2833
: IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
2934
Write(WS) {}
@@ -282,7 +287,8 @@ void RegisterFile::addRegisterWrite(WriteRef Write,
282287
MCPhysReg ZeroRegisterID =
283288
WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
284289
ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
285-
for (MCPhysReg I : MRI.subregs(ZeroRegisterID))
290+
for (MCPhysReg I :
291+
make_filter_range(MRI.subregs(ZeroRegisterID), isNonArtificial(MRI)))
286292
ZeroRegisters.setBitVal(I, IsWriteZero);
287293

288294
// If this move has been eliminated, then method tryEliminateMoveOrSwap should
@@ -304,7 +310,8 @@ void RegisterFile::addRegisterWrite(WriteRef Write,
304310
// Update the mapping for register RegID including its sub-registers.
305311
RegisterMappings[RegID].first = Write;
306312
RegisterMappings[RegID].second.AliasRegID = 0U;
307-
for (MCPhysReg I : MRI.subregs(RegID)) {
313+
for (MCPhysReg I :
314+
make_filter_range(MRI.subregs(RegID), isNonArtificial(MRI))) {
308315
RegisterMappings[I].first = Write;
309316
RegisterMappings[I].second.AliasRegID = 0U;
310317
}
@@ -472,7 +479,8 @@ bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
472479
AliasedReg = RMAlias.AliasRegID;
473480

474481
RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
475-
for (MCPhysReg I : MRI.subregs(AliasReg))
482+
for (MCPhysReg I :
483+
make_filter_range(MRI.subregs(AliasReg), isNonArtificial(MRI)))
476484
RegisterMappings[I].second.AliasRegID = AliasedReg;
477485

478486
if (ZeroRegisters[RS.getRegisterID()]) {

llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1540,7 +1540,10 @@ static bool canRenameMOP(const MachineOperand &MOP,
15401540
// Note that this relies on the structure of the AArch64 register file. In
15411541
// particular, a subregister cannot be written without overwriting the
15421542
// whole register.
1543-
if (RegClass->HasDisjunctSubRegs) {
1543+
if (RegClass->HasDisjunctSubRegs && RegClass->CoveredBySubRegs &&
1544+
(TRI->getSubRegisterClass(RegClass, AArch64::dsub0) ||
1545+
TRI->getSubRegisterClass(RegClass, AArch64::qsub0) ||
1546+
TRI->getSubRegisterClass(RegClass, AArch64::zsub0))) {
15441547
LLVM_DEBUG(
15451548
dbgs()
15461549
<< " Cannot rename operands with multiple disjunct subregisters ("

0 commit comments

Comments
 (0)