Skip to content

Commit a8dadc1

Browse files
committed
Merge branch 'main' into branch-protection-pauthabi
2 parents 0579818 + b298e2d commit a8dadc1

File tree

119 files changed

+3225
-4028
lines changed

Some content is hidden

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

119 files changed

+3225
-4028
lines changed

.github/workflows/libcxx-build-and-test.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ jobs:
6363
cxx: [ 'clang++-19' ]
6464
include:
6565
- config: 'generic-gcc'
66-
cc: 'gcc-13'
67-
cxx: 'g++-13'
66+
cc: 'gcc-14'
67+
cxx: 'g++-14'
6868
steps:
6969
- uses: actions/checkout@v4
7070
- name: ${{ matrix.config }}.${{ matrix.cxx }}
@@ -101,8 +101,8 @@ jobs:
101101
cxx: [ 'clang++-19' ]
102102
include:
103103
- config: 'generic-gcc-cxx11'
104-
cc: 'gcc-13'
105-
cxx: 'g++-13'
104+
cc: 'gcc-14'
105+
cxx: 'g++-14'
106106
- config: 'generic-cxx23'
107107
cc: 'clang-17'
108108
cxx: 'clang++-17'

bolt/include/bolt/Core/DebugNames.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class DWARF5AcceleratorTable {
9191
uint64_t CurrentUnitOffset = 0;
9292
const DWARFUnit *CurrentUnit = nullptr;
9393
std::unordered_map<uint32_t, uint32_t> AbbrevTagToIndexMap;
94+
/// Contains a map of TU hashes to a Foreign TU indecies.
95+
/// This is used to reduce the size of Foreign TU list since there could be
96+
/// multiple TUs with the same hash.
97+
DenseMap<uint64_t, uint32_t> TUHashToIndexMap;
9498

9599
/// Represents a group of entries with identical name (and hence, hash value).
96100
struct HashData {

bolt/lib/Core/DebugNames.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ void DWARF5AcceleratorTable::addUnit(DWARFUnit &Unit,
9090
auto Iter = CUOffsetsToPatch.insert({*DWOID, CUList.size()});
9191
if (Iter.second)
9292
CUList.push_back(BADCUOFFSET);
93-
ForeignTUList.push_back(cast<DWARFTypeUnit>(&Unit)->getTypeHash());
93+
const uint64_t TUHash = cast<DWARFTypeUnit>(&Unit)->getTypeHash();
94+
if (!TUHashToIndexMap.count(TUHash)) {
95+
TUHashToIndexMap.insert({TUHash, ForeignTUList.size()});
96+
ForeignTUList.push_back(TUHash);
97+
}
9498
} else {
9599
LocalTUList.push_back(CurrentUnitOffset);
96100
}
@@ -231,8 +235,13 @@ DWARF5AcceleratorTable::addAccelTableEntry(
231235
IsTU = Unit.isTypeUnit();
232236
DieTag = Die.getTag();
233237
if (IsTU) {
234-
if (DWOID)
235-
return ForeignTUList.size() - 1;
238+
if (DWOID) {
239+
const uint64_t TUHash = cast<DWARFTypeUnit>(&Unit)->getTypeHash();
240+
auto Iter = TUHashToIndexMap.find(TUHash);
241+
assert(Iter != TUHashToIndexMap.end() &&
242+
"Could not find TU hash in map");
243+
return Iter->second;
244+
}
236245
return LocalTUList.size() - 1;
237246
}
238247
return CUList.size() - 1;

bolt/test/X86/dwarf5-df-types-debug-names.test

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@
1818
; BOLT: type_signature = [[TYPE1:0x[0-9a-f]*]]
1919
; BOLT: Compile Unit
2020
; BOLT: type_signature = [[TYPE2:0x[0-9a-f]*]]
21-
; BOLT: type_signature = [[TYPE3:0x[0-9a-f]*]]
21+
; BOLT: type_signature = [[TYPE1]]
2222
; BOLT: Compile Unit
2323
; BOLT: [[OFFSET:0x[0-9a-f]*]]: Compile Unit
2424
; BOLT: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit
2525

2626
; BOLT: Name Index @ 0x0 {
2727
; BOLT-NEXT: Header {
28-
; BOLT-NEXT: Length: 0x17E
28+
; BOLT-NEXT: Length: 0x176
2929
; BOLT-NEXT: Format: DWARF32
3030
; BOLT-NEXT: Version: 5
3131
; BOLT-NEXT: CU count: 2
3232
; BOLT-NEXT: Local TU count: 0
33-
; BOLT-NEXT: Foreign TU count: 4
33+
; BOLT-NEXT: Foreign TU count: 3
3434
; BOLT-NEXT: Bucket count: 9
3535
; BOLT-NEXT: Name count: 9
3636
; BOLT-NEXT: Abbreviations table size: 0x37
@@ -44,7 +44,6 @@
4444
; BOLT-NEXT: ForeignTU[0]: [[TYPE]]
4545
; BOLT-NEXT: ForeignTU[1]: [[TYPE1]]
4646
; BOLT-NEXT: ForeignTU[2]: [[TYPE2]]
47-
; BOLT-NEXT: ForeignTU[3]: [[TYPE3]]
4847
; BOLT-NEXT: ]
4948
; BOLT-NEXT: Abbreviations [
5049
; BOLT-NEXT: Abbreviation [[ABBREV:0x[0-9a-f]*]] {
@@ -173,7 +172,7 @@
173172
; BOLT-NEXT: Entry @ {{.+}} {
174173
; BOLT-NEXT: Abbrev: [[ABBREV]]
175174
; BOLT-NEXT: Tag: DW_TAG_structure_type
176-
; BOLT-NEXT: DW_IDX_type_unit: 0x03
175+
; BOLT-NEXT: DW_IDX_type_unit: 0x01
177176
; BOLT-NEXT: DW_IDX_compile_unit: 0x01
178177
; BOLT-NEXT: DW_IDX_die_offset: 0x00000021
179178
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
@@ -237,7 +236,7 @@
237236
; BOLT-NEXT: Entry @ {{.+}} {
238237
; BOLT-NEXT: Abbrev: 0x5
239238
; BOLT-NEXT: Tag: DW_TAG_base_type
240-
; BOLT-NEXT: DW_IDX_type_unit: 0x03
239+
; BOLT-NEXT: DW_IDX_type_unit: 0x01
241240
; BOLT-NEXT: DW_IDX_compile_unit: 0x01
242241
; BOLT-NEXT: DW_IDX_die_offset: 0x00000048
243242
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>

clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "NotNullTerminatedResultCheck.h"
5252
#include "OptionalValueConversionCheck.h"
5353
#include "ParentVirtualCallCheck.h"
54+
#include "PointerArithmeticOnPolymorphicObjectCheck.h"
5455
#include "PosixReturnCheck.h"
5556
#include "RedundantBranchConditionCheck.h"
5657
#include "ReservedIdentifierCheck.h"
@@ -171,6 +172,8 @@ class BugproneModule : public ClangTidyModule {
171172
"bugprone-multiple-statement-macro");
172173
CheckFactories.registerCheck<OptionalValueConversionCheck>(
173174
"bugprone-optional-value-conversion");
175+
CheckFactories.registerCheck<PointerArithmeticOnPolymorphicObjectCheck>(
176+
"bugprone-pointer-arithmetic-on-polymorphic-object");
174177
CheckFactories.registerCheck<RedundantBranchConditionCheck>(
175178
"bugprone-redundant-branch-condition");
176179
CheckFactories.registerCheck<cppcoreguidelines::NarrowingConversionsCheck>(

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ add_clang_library(clangTidyBugproneModule
4848
NotNullTerminatedResultCheck.cpp
4949
OptionalValueConversionCheck.cpp
5050
ParentVirtualCallCheck.cpp
51+
PointerArithmeticOnPolymorphicObjectCheck.cpp
5152
PosixReturnCheck.cpp
5253
RedundantBranchConditionCheck.cpp
5354
ReservedIdentifierCheck.cpp
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//===--- PointerArithmeticOnPolymorphicObjectCheck.cpp - clang-tidy--------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "PointerArithmeticOnPolymorphicObjectCheck.h"
10+
#include "clang/AST/ASTContext.h"
11+
#include "clang/ASTMatchers/ASTMatchFinder.h"
12+
13+
using namespace clang::ast_matchers;
14+
15+
namespace clang::tidy::bugprone {
16+
17+
namespace {
18+
AST_MATCHER(CXXRecordDecl, isAbstract) { return Node.isAbstract(); }
19+
AST_MATCHER(CXXRecordDecl, isPolymorphic) { return Node.isPolymorphic(); }
20+
} // namespace
21+
22+
PointerArithmeticOnPolymorphicObjectCheck::
23+
PointerArithmeticOnPolymorphicObjectCheck(StringRef Name,
24+
ClangTidyContext *Context)
25+
: ClangTidyCheck(Name, Context),
26+
IgnoreInheritedVirtualFunctions(
27+
Options.get("IgnoreInheritedVirtualFunctions", false)) {}
28+
29+
void PointerArithmeticOnPolymorphicObjectCheck::storeOptions(
30+
ClangTidyOptions::OptionMap &Opts) {
31+
Options.store(Opts, "IgnoreInheritedVirtualFunctions",
32+
IgnoreInheritedVirtualFunctions);
33+
}
34+
35+
void PointerArithmeticOnPolymorphicObjectCheck::registerMatchers(
36+
MatchFinder *Finder) {
37+
const auto PolymorphicPointerExpr =
38+
expr(hasType(hasCanonicalType(pointerType(pointee(hasCanonicalType(
39+
hasDeclaration(cxxRecordDecl(unless(isFinal()), isPolymorphic())
40+
.bind("pointee"))))))))
41+
.bind("pointer");
42+
43+
const auto PointerExprWithVirtualMethod =
44+
expr(hasType(hasCanonicalType(
45+
pointerType(pointee(hasCanonicalType(hasDeclaration(
46+
cxxRecordDecl(
47+
unless(isFinal()),
48+
anyOf(hasMethod(isVirtualAsWritten()), isAbstract()))
49+
.bind("pointee"))))))))
50+
.bind("pointer");
51+
52+
const auto SelectedPointerExpr = IgnoreInheritedVirtualFunctions
53+
? PointerExprWithVirtualMethod
54+
: PolymorphicPointerExpr;
55+
56+
const auto ArraySubscript = arraySubscriptExpr(hasBase(SelectedPointerExpr));
57+
58+
const auto BinaryOperators =
59+
binaryOperator(hasAnyOperatorName("+", "-", "+=", "-="),
60+
hasEitherOperand(SelectedPointerExpr));
61+
62+
const auto UnaryOperators = unaryOperator(
63+
hasAnyOperatorName("++", "--"), hasUnaryOperand(SelectedPointerExpr));
64+
65+
Finder->addMatcher(ArraySubscript, this);
66+
Finder->addMatcher(BinaryOperators, this);
67+
Finder->addMatcher(UnaryOperators, this);
68+
}
69+
70+
void PointerArithmeticOnPolymorphicObjectCheck::check(
71+
const MatchFinder::MatchResult &Result) {
72+
const auto *PointerExpr = Result.Nodes.getNodeAs<Expr>("pointer");
73+
const auto *PointeeDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("pointee");
74+
75+
diag(PointerExpr->getBeginLoc(),
76+
"pointer arithmetic on polymorphic object of type %0 can result in "
77+
"undefined behavior if the dynamic type differs from the pointer type")
78+
<< PointeeDecl << PointerExpr->getSourceRange();
79+
}
80+
81+
} // namespace clang::tidy::bugprone
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===--- PointerArithmeticOnPolymorphicObjectCheck.h ------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POINTERARITHMETICONPOLYMORPHICOBJECTCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POINTERARITHMETICONPOLYMORPHICOBJECTCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang::tidy::bugprone {
15+
16+
/// Finds pointer arithmetic performed on classes that contain a
17+
/// virtual function.
18+
///
19+
/// For the user-facing documentation see:
20+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/pointer-arithmetic-on-polymorphic-object.html
21+
class PointerArithmeticOnPolymorphicObjectCheck : public ClangTidyCheck {
22+
public:
23+
PointerArithmeticOnPolymorphicObjectCheck(StringRef Name,
24+
ClangTidyContext *Context);
25+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
26+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
27+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
28+
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
29+
return LangOpts.CPlusPlus;
30+
}
31+
std::optional<TraversalKind> getCheckTraversalKind() const override {
32+
return TK_IgnoreUnlessSpelledInSource;
33+
}
34+
35+
private:
36+
const bool IgnoreInheritedVirtualFunctions;
37+
};
38+
39+
} // namespace clang::tidy::bugprone
40+
41+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POINTERARITHMETICONPOLYMORPHICOBJECTCHECK_H

clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../ClangTidyModule.h"
1111
#include "../ClangTidyModuleRegistry.h"
1212
#include "../bugprone/BadSignalToKillThreadCheck.h"
13+
#include "../bugprone/PointerArithmeticOnPolymorphicObjectCheck.h"
1314
#include "../bugprone/ReservedIdentifierCheck.h"
1415
#include "../bugprone/SignalHandlerCheck.h"
1516
#include "../bugprone/SignedCharMisuseCheck.h"
@@ -238,6 +239,10 @@ class CERTModule : public ClangTidyModule {
238239
// CON
239240
CheckFactories.registerCheck<bugprone::SpuriouslyWakeUpFunctionsCheck>(
240241
"cert-con54-cpp");
242+
// CTR
243+
CheckFactories
244+
.registerCheck<bugprone::PointerArithmeticOnPolymorphicObjectCheck>(
245+
"cert-ctr56-cpp");
241246
// DCL
242247
CheckFactories.registerCheck<VariadicFunctionDefCheck>("cert-dcl50-cpp");
243248
CheckFactories.registerCheck<bugprone::ReservedIdentifierCheck>(

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ New checks
137137
Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP
138138
can be constructed outside itself and the derived class.
139139

140+
- New :doc:`bugprone-pointer-arithmetic-on-polymorphic-object
141+
<clang-tidy/checks/bugprone/pointer-arithmetic-on-polymorphic-object>` check.
142+
143+
Finds pointer arithmetic performed on classes that contain a virtual function.
144+
140145
- New :doc:`bugprone-return-const-ref-from-parameter
141146
<clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check.
142147

@@ -199,6 +204,11 @@ New checks
199204
New check aliases
200205
^^^^^^^^^^^^^^^^^
201206

207+
- New alias :doc:`cert-ctr56-cpp <clang-tidy/checks/cert/ctr56-cpp>` to
208+
:doc:`bugprone-pointer-arithmetic-on-polymorphic-object
209+
<clang-tidy/checks/bugprone/pointer-arithmetic-on-polymorphic-object>`
210+
was added.
211+
202212
- New alias :doc:`cert-int09-c <clang-tidy/checks/cert/int09-c>` to
203213
:doc:`readability-enum-initial-value <clang-tidy/checks/readability/enum-initial-value>`
204214
was added.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
.. title:: clang-tidy - bugprone-pointer-arithmetic-on-polymorphic-object
2+
3+
bugprone-pointer-arithmetic-on-polymorphic-object
4+
=================================================
5+
6+
Finds pointer arithmetic performed on classes that contain a virtual function.
7+
8+
Pointer arithmetic on polymorphic objects where the pointer's static type is
9+
different from its dynamic type is undefined behavior, as the two types could
10+
have different sizes, and thus the vtable pointer could point to an
11+
invalid address.
12+
13+
Finding pointers where the static type contains a virtual member function is a
14+
good heuristic, as the pointer is likely to point to a different,
15+
derived object.
16+
17+
Example:
18+
19+
.. code-block:: c++
20+
21+
struct Base {
22+
virtual void ~Base();
23+
};
24+
25+
struct Derived : public Base {};
26+
27+
void foo() {
28+
Base *b = new Derived[10];
29+
30+
b += 1;
31+
// warning: pointer arithmetic on class that declares a virtual function can
32+
// result in undefined behavior if the dynamic type differs from the
33+
// pointer type
34+
35+
delete[] static_cast<Derived*>(b);
36+
}
37+
38+
Options
39+
-------
40+
41+
.. option:: IgnoreInheritedVirtualFunctions
42+
43+
When `true`, objects that only inherit a virtual function are not checked.
44+
Classes that do not declare a new virtual function are excluded
45+
by default, as they make up the majority of false positives.
46+
Default: `false`.
47+
48+
.. code-block:: c++
49+
50+
void bar() {
51+
Base *b = new Base[10];
52+
b += 1; // warning, as Base declares a virtual destructor
53+
54+
delete[] b;
55+
56+
Derived *d = new Derived[10]; // Derived overrides the destructor, and
57+
// declares no other virtual functions
58+
d += 1; // warning only if IgnoreVirtualDeclarationsOnly is set to false
59+
60+
delete[] d;
61+
}
62+
63+
References
64+
----------
65+
66+
This check corresponds to the SEI Cert rule
67+
`CTR56-CPP. Do not use pointer arithmetic on polymorphic objects
68+
<https://wiki.sei.cmu.edu/confluence/display/cplusplus/CTR56-CPP.+Do+not+use+pointer+arithmetic+on+polymorphic+objects>`_.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. title:: clang-tidy - cert-ctr56-cpp
2+
.. meta::
3+
:http-equiv=refresh: 5;URL=../bugprone/pointer-arithmetic-on-polymorphic-object.html
4+
5+
cert-ctr56-cpp
6+
==============
7+
8+
The `cert-ctr56-cpp` check is an alias, please see
9+
:doc:`bugprone-pointer-arithmetic-on-polymorphic-object
10+
<../bugprone/pointer-arithmetic-on-polymorphic-object>` for more information.

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ Clang-Tidy Checks
157157
:doc:`bugprone-unused-raii <bugprone/unused-raii>`, "Yes"
158158
:doc:`bugprone-unused-return-value <bugprone/unused-return-value>`,
159159
:doc:`bugprone-use-after-move <bugprone/use-after-move>`,
160+
:doc:`bugprone-pointer-arithmetic-on-polymorphic-object <bugprone/pointer-arithmetic-on-polymorphic-object>`,
160161
:doc:`bugprone-virtual-near-miss <bugprone/virtual-near-miss>`, "Yes"
161162
:doc:`cert-dcl50-cpp <cert/dcl50-cpp>`,
162163
:doc:`cert-dcl58-cpp <cert/dcl58-cpp>`,

0 commit comments

Comments
 (0)