Skip to content

Commit 4a00abb

Browse files
committed
try
Created using spr 1.3.4
2 parents 311e6a6 + 6b902ef commit 4a00abb

File tree

17 files changed

+3120
-61
lines changed

17 files changed

+3120
-61
lines changed

.ci/monolithic-windows.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,5 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
8181

8282
echo "--- ninja"
8383
# Targets are not escaped as they are passed as separate arguments.
84+
ninja -C "${BUILD_DIR}" -k 0
8485
ninja -C "${BUILD_DIR}" -k 0 ${targets}

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ Improvements to Clang's diagnostics
127127
- The ``-Wunique-object-duplication`` warning has been added to warn about objects
128128
which are supposed to only exist once per program, but may get duplicated when
129129
built into a shared library.
130+
- Fixed a bug where Clang's Analysis did not correctly model the destructor behavior of ``union`` members (#GH119415).
130131

131132
Improvements to Clang's time-trace
132133
----------------------------------

clang/lib/Analysis/CFG.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,8 @@ void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
20412041
}
20422042

20432043
// First destroy member objects.
2044+
if (RD->isUnion())
2045+
return;
20442046
for (auto *FI : RD->fields()) {
20452047
// Check for constant size array. Set type to array element type.
20462048
QualType QT = FI->getType();

clang/test/Analysis/NewDelete-checker-test.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,3 +441,31 @@ void testLeakBecauseNTTPIsNotDeallocation() {
441441
void* p = ::operator new(10);
442442
deallocate_via_nttp<not_free>(p);
443443
} // leak-warning{{Potential leak of memory pointed to by 'p'}}
444+
445+
namespace optional_union {
446+
template <typename T>
447+
class unique_ptr {
448+
T *q;
449+
public:
450+
unique_ptr() : q(new T) {}
451+
~unique_ptr() {
452+
delete q;
453+
}
454+
};
455+
456+
union custom_union_t {
457+
unique_ptr<int> present;
458+
char notpresent;
459+
custom_union_t() : present(unique_ptr<int>()) {}
460+
~custom_union_t() {}
461+
};
462+
463+
void testUnionCorrect() {
464+
custom_union_t a;
465+
a.present.~unique_ptr<int>();
466+
}
467+
468+
void testUnionLeak() {
469+
custom_union_t a;
470+
} // leak-warning{{Potential leak of memory pointed to by 'a.present.q'}}
471+
}

clang/test/Analysis/dtor-union.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=destructors -verify -std=c++11 %s
2+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=destructors -verify -std=c++17 %s
3+
4+
void clang_analyzer_eval(bool);
5+
6+
struct InlineDtor {
7+
static int cnt;
8+
static int dtorCalled;
9+
~InlineDtor() {
10+
++dtorCalled;
11+
}
12+
};
13+
14+
int InlineDtor::cnt = 0;
15+
int InlineDtor::dtorCalled = 0;
16+
17+
void testUnionDtor() {
18+
static int unionDtorCalled;
19+
InlineDtor::cnt = 0;
20+
InlineDtor::dtorCalled = 0;
21+
unionDtorCalled = 0;
22+
{
23+
union UnionDtor {
24+
InlineDtor kind1;
25+
char kind2;
26+
~UnionDtor() { unionDtorCalled++; }
27+
};
28+
UnionDtor u1{.kind1{}};
29+
UnionDtor u2{.kind2{}};
30+
auto u3 = new UnionDtor{.kind1{}};
31+
auto u4 = new UnionDtor{.kind2{}};
32+
delete u3;
33+
delete u4;
34+
}
35+
36+
clang_analyzer_eval(unionDtorCalled == 4); // expected-warning {{TRUE}}
37+
clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}}
38+
}

llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,17 +1048,29 @@ bool X86InstructionSelector::selectFCmp(MachineInstr &I,
10481048
break;
10491049
}
10501050

1051+
assert((LhsReg.isVirtual() && RhsReg.isVirtual()) &&
1052+
"Both arguments of FCMP need to be virtual!");
1053+
auto *LhsBank = RBI.getRegBank(LhsReg, MRI, TRI);
1054+
[[maybe_unused]] auto *RhsBank = RBI.getRegBank(RhsReg, MRI, TRI);
1055+
assert((LhsBank == RhsBank) &&
1056+
"Both banks assigned to FCMP arguments need to be same!");
1057+
10511058
// Compute the opcode for the CMP instruction.
10521059
unsigned OpCmp;
10531060
LLT Ty = MRI.getType(LhsReg);
10541061
switch (Ty.getSizeInBits()) {
10551062
default:
10561063
return false;
10571064
case 32:
1058-
OpCmp = X86::UCOMISSrr;
1065+
OpCmp = LhsBank->getID() == X86::PSRRegBankID ? X86::UCOM_FpIr32
1066+
: X86::UCOMISSrr;
10591067
break;
10601068
case 64:
1061-
OpCmp = X86::UCOMISDrr;
1069+
OpCmp = LhsBank->getID() == X86::PSRRegBankID ? X86::UCOM_FpIr64
1070+
: X86::UCOMISDrr;
1071+
break;
1072+
case 80:
1073+
OpCmp = X86::UCOM_FpIr80;
10621074
break;
10631075
}
10641076

llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,9 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
452452

453453
// fp comparison
454454
getActionDefinitionsBuilder(G_FCMP)
455-
.legalIf([=](const LegalityQuery &Query) {
456-
return (HasSSE1 && typePairInSet(0, 1, {{s8, s32}})(Query)) ||
457-
(HasSSE2 && typePairInSet(0, 1, {{s8, s64}})(Query));
458-
})
455+
.legalFor(HasSSE1 || UseX87, {s8, s32})
456+
.legalFor(HasSSE2 || UseX87, {s8, s64})
457+
.legalFor(UseX87, {s8, s80})
459458
.clampScalar(0, s8, s8)
460459
.clampScalar(1, s32, HasSSE2 ? s64 : s32)
461460
.widenScalarToNextPow2(1);

llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,8 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
321321

322322
unsigned Size = Ty1.getSizeInBits();
323323
(void)Size;
324-
assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
325-
324+
assert((Size == 32 || Size == 64 || Size == 80) &&
325+
"Unsupported size for G_FCMP");
326326
auto FpRegBank = getPartialMappingIdx(MI, Ty1, /* isFP= */ true);
327327
OpRegBankIdx = {PMI_GPR8,
328328
/* Predicate */ PMI_None, FpRegBank, FpRegBank};

llvm/lib/Transforms/Instrumentation/MemProfiler.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,7 @@ static void
970970
readMemprof(Module &M, Function &F, IndexedInstrProfReader *MemProfReader,
971971
const TargetLibraryInfo &TLI,
972972
std::map<uint64_t, AllocMatchInfo> &FullStackIdToAllocMatchInfo,
973+
std::set<std::vector<uint64_t>> &MatchedCallSites,
973974
DenseMap<uint64_t, LocToLocMap> &UndriftMaps) {
974975
auto &Ctx = M.getContext();
975976
// Previously we used getIRPGOFuncName() here. If F is local linkage,
@@ -1210,6 +1211,13 @@ readMemprof(Module &M, Function &F, IndexedInstrProfReader *MemProfReader,
12101211
addCallsiteMetadata(I, InlinedCallStack, Ctx);
12111212
// Only need to find one with a matching call stack and add a single
12121213
// callsite metadata.
1214+
1215+
// Accumulate call site matching information upon request.
1216+
if (ClPrintMemProfMatchInfo) {
1217+
std::vector<uint64_t> CallStack;
1218+
append_range(CallStack, InlinedCallStack);
1219+
MatchedCallSites.insert(std::move(CallStack));
1220+
}
12131221
break;
12141222
}
12151223
}
@@ -1266,13 +1274,17 @@ PreservedAnalyses MemProfUsePass::run(Module &M, ModuleAnalysisManager &AM) {
12661274
// it to an allocation in the IR.
12671275
std::map<uint64_t, AllocMatchInfo> FullStackIdToAllocMatchInfo;
12681276

1277+
// Set of the matched call sites, each expressed as a sequence of an inline
1278+
// call stack.
1279+
std::set<std::vector<uint64_t>> MatchedCallSites;
1280+
12691281
for (auto &F : M) {
12701282
if (F.isDeclaration())
12711283
continue;
12721284

12731285
const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
12741286
readMemprof(M, F, MemProfReader.get(), TLI, FullStackIdToAllocMatchInfo,
1275-
UndriftMaps);
1287+
MatchedCallSites, UndriftMaps);
12761288
}
12771289

12781290
if (ClPrintMemProfMatchInfo) {
@@ -1281,6 +1293,13 @@ PreservedAnalyses MemProfUsePass::run(Module &M, ModuleAnalysisManager &AM) {
12811293
<< " context with id " << Id << " has total profiled size "
12821294
<< Info.TotalSize << (Info.Matched ? " is" : " not")
12831295
<< " matched\n";
1296+
1297+
for (const auto &CallStack : MatchedCallSites) {
1298+
errs() << "MemProf callsite match for inline call stack";
1299+
for (uint64_t StackId : CallStack)
1300+
errs() << " " << StackId;
1301+
errs() << "\n";
1302+
}
12841303
}
12851304

12861305
return PreservedAnalyses::none();

0 commit comments

Comments
 (0)