Skip to content

Commit 22ff0d6

Browse files
author
Jenkins
committed
merge main into amd-staging
Change-Id: I12b99821259d4e2a76c157ce5cff239a3e17bc03
2 parents 2f2ce7e + fb0ef6b commit 22ff0d6

Some content is hidden

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

59 files changed

+1106
-4370
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===--- BitwisePointerCastCheck.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 "BitwisePointerCastCheck.h"
10+
#include "clang/ASTMatchers/ASTMatchFinder.h"
11+
12+
using namespace clang::ast_matchers;
13+
14+
namespace clang::tidy::bugprone {
15+
16+
void BitwisePointerCastCheck::registerMatchers(MatchFinder *Finder) {
17+
if (getLangOpts().CPlusPlus20) {
18+
auto IsPointerType = refersToType(qualType(isAnyPointer()));
19+
Finder->addMatcher(callExpr(hasDeclaration(functionDecl(allOf(
20+
hasName("::std::bit_cast"),
21+
hasTemplateArgument(0, IsPointerType),
22+
hasTemplateArgument(1, IsPointerType)))))
23+
.bind("bit_cast"),
24+
this);
25+
}
26+
27+
auto IsDoublePointerType =
28+
hasType(qualType(pointsTo(qualType(isAnyPointer()))));
29+
Finder->addMatcher(callExpr(hasArgument(0, IsDoublePointerType),
30+
hasArgument(1, IsDoublePointerType),
31+
hasDeclaration(functionDecl(hasName("::memcpy"))))
32+
.bind("memcpy"),
33+
this);
34+
}
35+
36+
void BitwisePointerCastCheck::check(const MatchFinder::MatchResult &Result) {
37+
if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("bit_cast"))
38+
diag(Call->getBeginLoc(),
39+
"do not use 'std::bit_cast' to cast between pointers")
40+
<< Call->getSourceRange();
41+
else if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("memcpy"))
42+
diag(Call->getBeginLoc(), "do not use 'memcpy' to cast between pointers")
43+
<< Call->getSourceRange();
44+
}
45+
46+
} // namespace clang::tidy::bugprone
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===--- BitwisePointerCastCheck.h - clang-tidy -----------------*- 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_BITWISEPOINTERCASTCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BITWISEPOINTERCASTCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang::tidy::bugprone {
15+
16+
/// Warns about code that tries to cast between pointers by means of
17+
/// ``std::bit_cast`` or ``memcpy``.
18+
///
19+
/// For the user-facing documentation see:
20+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/bitwise-pointer-cast.html
21+
class BitwisePointerCastCheck : public ClangTidyCheck {
22+
public:
23+
BitwisePointerCastCheck(StringRef Name, ClangTidyContext *Context)
24+
: ClangTidyCheck(Name, Context) {}
25+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
26+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
27+
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
28+
return LangOpts.CPlusPlus;
29+
}
30+
};
31+
32+
} // namespace clang::tidy::bugprone
33+
34+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BITWISEPOINTERCASTCHECK_H

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "AssertSideEffectCheck.h"
1515
#include "AssignmentInIfConditionCheck.h"
1616
#include "BadSignalToKillThreadCheck.h"
17+
#include "BitwisePointerCastCheck.h"
1718
#include "BoolPointerImplicitConversionCheck.h"
1819
#include "BranchCloneCheck.h"
1920
#include "CastingThroughVoidCheck.h"
@@ -109,6 +110,8 @@ class BugproneModule : public ClangTidyModule {
109110
"bugprone-assignment-in-if-condition");
110111
CheckFactories.registerCheck<BadSignalToKillThreadCheck>(
111112
"bugprone-bad-signal-to-kill-thread");
113+
CheckFactories.registerCheck<BitwisePointerCastCheck>(
114+
"bugprone-bitwise-pointer-cast");
112115
CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
113116
"bugprone-bool-pointer-implicit-conversion");
114117
CheckFactories.registerCheck<BranchCloneCheck>("bugprone-branch-clone");

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ add_clang_library(clangTidyBugproneModule
88
AssertSideEffectCheck.cpp
99
AssignmentInIfConditionCheck.cpp
1010
BadSignalToKillThreadCheck.cpp
11+
BitwisePointerCastCheck.cpp
1112
BoolPointerImplicitConversionCheck.cpp
1213
BranchCloneCheck.cpp
1314
BugproneTidyModule.cpp

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ Improvements to clang-tidy
109109
New checks
110110
^^^^^^^^^^
111111

112+
- New :doc:`bugprone-bitwise-pointer-cast
113+
<clang-tidy/checks/bugprone/bitwise-pointer-cast>` check.
114+
115+
Warns about code that tries to cast between pointers by means of
116+
``std::bit_cast`` or ``memcpy``.
117+
112118
- New :doc:`bugprone-tagged-union-member-count
113119
<clang-tidy/checks/bugprone/tagged-union-member-count>` check.
114120

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
.. title:: clang-tidy - bugprone-bitwise-pointer-cast
2+
3+
bugprone-bitwise-pointer-cast
4+
=============================
5+
6+
Warns about code that tries to cast between pointers by means of
7+
``std::bit_cast`` or ``memcpy``.
8+
9+
The motivation is that ``std::bit_cast`` is advertised as the safe alternative
10+
to type punning via ``reinterpret_cast`` in modern C++. However, one should not
11+
blindly replace ``reinterpret_cast`` with ``std::bit_cast``, as follows:
12+
13+
.. code-block:: c++
14+
15+
int x{};
16+
-float y = *reinterpret_cast<float*>(&x);
17+
+float y = *std::bit_cast<float*>(&x);
18+
19+
The drop-in replacement behaves exactly the same as ``reinterpret_cast``, and
20+
Undefined Behavior is still invoked. ``std::bit_cast`` is copying the bytes of
21+
the input pointer, not the pointee, into an output pointer of a different type,
22+
which may violate the strict aliasing rules. However, simply looking at the
23+
code, it looks "safe", because it uses ``std::bit_cast`` which is advertised as
24+
safe.
25+
26+
The solution to safe type punning is to apply ``std::bit_cast`` on value types,
27+
not on pointer types:
28+
29+
.. code-block:: c++
30+
31+
int x{};
32+
float y = std::bit_cast<float>(x);
33+
34+
This way, the bytes of the input object are copied into the output object, which
35+
is much safer. Do note that Undefined Behavior can still occur, if there is no
36+
value of type ``To`` corresponding to the value representation produced.
37+
Compilers may be able to optimize this copy and generate identical assembly to
38+
the original ``reinterpret_cast`` version.
39+
40+
Code before C++20 may backport ``std::bit_cast`` by means of ``memcpy``, or
41+
simply call ``memcpy`` directly, which is equally problematic. This is also
42+
detected by this check:
43+
44+
.. code-block:: c++
45+
46+
int* x{};
47+
float* y{};
48+
std::memcpy(&y, &x, sizeof(x));
49+
50+
Alternatively, if a cast between pointers is truly wanted, ``reinterpret_cast``
51+
should be used, to clearly convey the intent and enable warnings from compilers
52+
and linters, which should be addressed accordingly.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ Clang-Tidy Checks
8181
:doc:`bugprone-assert-side-effect <bugprone/assert-side-effect>`,
8282
:doc:`bugprone-assignment-in-if-condition <bugprone/assignment-in-if-condition>`,
8383
:doc:`bugprone-bad-signal-to-kill-thread <bugprone/bad-signal-to-kill-thread>`,
84+
:doc:`bugprone-bitwise-pointer-cast <bugprone/bitwise-pointer-cast>`,
8485
:doc:`bugprone-bool-pointer-implicit-conversion <bugprone/bool-pointer-implicit-conversion>`, "Yes"
8586
:doc:`bugprone-branch-clone <bugprone/branch-clone>`,
8687
:doc:`bugprone-casting-through-void <bugprone/casting-through-void>`,
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// RUN: %check_clang_tidy -std=c++20 %s bugprone-bitwise-pointer-cast %t
2+
3+
void memcpy(void* to, void* dst, unsigned long long size)
4+
{
5+
// Dummy implementation for the purpose of the test
6+
}
7+
8+
namespace std
9+
{
10+
template <typename To, typename From>
11+
To bit_cast(From from)
12+
{
13+
// Dummy implementation for the purpose of the test
14+
To to{};
15+
return to;
16+
}
17+
18+
using ::memcpy;
19+
}
20+
21+
void pointer2pointer()
22+
{
23+
int x{};
24+
float bad = *std::bit_cast<float*>(&x); // UB, but looks safe due to std::bit_cast
25+
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use 'std::bit_cast' to cast between pointers [bugprone-bitwise-pointer-cast]
26+
float good = std::bit_cast<float>(x); // Well-defined
27+
28+
using IntPtr = int*;
29+
using FloatPtr = float*;
30+
IntPtr x2{};
31+
float bad2 = *std::bit_cast<FloatPtr>(x2);
32+
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: do not use 'std::bit_cast' to cast between pointers [bugprone-bitwise-pointer-cast]
33+
}
34+
35+
void pointer2pointer_memcpy()
36+
{
37+
int x{};
38+
int* px{};
39+
float y{};
40+
float* py{};
41+
42+
memcpy(&py, &px, sizeof(px));
43+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'memcpy' to cast between pointers [bugprone-bitwise-pointer-cast]
44+
std::memcpy(&py, &px, sizeof(px));
45+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'memcpy' to cast between pointers [bugprone-bitwise-pointer-cast]
46+
47+
std::memcpy(&y, &x, sizeof(x));
48+
}
49+
50+
// Pointer-integer conversions are allowed by this check
51+
void int2pointer()
52+
{
53+
unsigned long long addr{};
54+
float* p = std::bit_cast<float*>(addr);
55+
std::memcpy(&p, &addr, sizeof(addr));
56+
}
57+
58+
void pointer2int()
59+
{
60+
float* p{};
61+
auto addr = std::bit_cast<unsigned long long>(p);
62+
std::memcpy(&addr, &p, sizeof(p));
63+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %check_clang_tidy %s bugprone-bitwise-pointer-cast %t
2+
3+
void memcpy(void* to, void* dst, unsigned long long size)
4+
{
5+
// Dummy implementation for the purpose of the test
6+
}
7+
8+
namespace std
9+
{
10+
using ::memcpy;
11+
}
12+
13+
void pointer2pointer()
14+
{
15+
int x{};
16+
int* px{};
17+
float y{};
18+
float* py{};
19+
20+
memcpy(&py, &px, sizeof(px));
21+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'memcpy' to cast between pointers [bugprone-bitwise-pointer-cast]
22+
std::memcpy(&py, &px, sizeof(px));
23+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'memcpy' to cast between pointers [bugprone-bitwise-pointer-cast]
24+
25+
std::memcpy(&y, &x, sizeof(x));
26+
}
27+
28+
// Pointer-integer conversions are allowed by this check
29+
void int2pointer()
30+
{
31+
unsigned long long addr{};
32+
float* p{};
33+
std::memcpy(&p, &addr, sizeof(addr));
34+
}
35+
36+
void pointer2int()
37+
{
38+
unsigned long long addr{};
39+
float* p{};
40+
std::memcpy(&addr, &p, sizeof(p));
41+
}

libc/src/__support/StringUtil/tables/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ add_header_library(
33
HDRS
44
stdc_errors.h
55
DEPENDS
6-
libc.src.errno.errno
6+
libc.hdr.errno_macros
77
libc.src.__support.StringUtil.message_mapper
88
)
99

libc/src/__support/StringUtil/tables/stdc_errors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_TABLES_STDC_ERRORS_H
1010
#define LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_TABLES_STDC_ERRORS_H
1111

12+
#include "hdr/errno_macros.h"
1213
#include "src/__support/StringUtil/message_mapper.h"
1314
#include "src/__support/macros/config.h"
1415

libcxx/include/__system_error/errc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
133133
// enum class errc
134134
//
135135
// LWG3869 deprecates the UNIX STREAMS macros and enum values.
136-
// This makes the code clumbersome:
136+
// This makes the code cumbersome:
137137
// - the enum value is deprecated and should show a diagnostic,
138138
// - the macro is deprecated and should _not_ show a diagnostic in this
139139
// context, and

lld/ELF/AArch64ErrataFix.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ static uint64_t scanCortexA53Errata843419(InputSection *isec, uint64_t &off,
372372

373373
class elf::Patch843419Section final : public SyntheticSection {
374374
public:
375-
Patch843419Section(InputSection *p, uint64_t off);
375+
Patch843419Section(Ctx &, InputSection *p, uint64_t off);
376376

377377
void writeTo(Ctx &, uint8_t *buf) override;
378378

@@ -392,7 +392,7 @@ class elf::Patch843419Section final : public SyntheticSection {
392392
Symbol *patchSym;
393393
};
394394

395-
Patch843419Section::Patch843419Section(InputSection *p, uint64_t off)
395+
Patch843419Section::Patch843419Section(Ctx &ctx, InputSection *p, uint64_t off)
396396
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4,
397397
".text.patch"),
398398
patchee(p), patcheeOffset(off) {
@@ -529,7 +529,7 @@ void AArch64Err843419Patcher::insertPatches(
529529
// instruction that we need to patch at patcheeOffset from the start of
530530
// InputSection isec, create a Patch843419 Section and add it to the
531531
// Patches that we need to insert.
532-
static void implementPatch(uint64_t adrpAddr, uint64_t patcheeOffset,
532+
static void implementPatch(Ctx &ctx, uint64_t adrpAddr, uint64_t patcheeOffset,
533533
InputSection *isec,
534534
std::vector<Patch843419Section *> &patches) {
535535
// There may be a relocation at the same offset that we are patching. There
@@ -556,7 +556,7 @@ static void implementPatch(uint64_t adrpAddr, uint64_t patcheeOffset,
556556
log("detected cortex-a53-843419 erratum sequence starting at " +
557557
utohexstr(adrpAddr) + " in unpatched output.");
558558

559-
auto *ps = make<Patch843419Section>(isec, patcheeOffset);
559+
auto *ps = make<Patch843419Section>(ctx, isec, patcheeOffset);
560560
patches.push_back(ps);
561561

562562
auto makeRelToPatch = [](uint64_t offset, Symbol *patchSym) {
@@ -599,7 +599,7 @@ AArch64Err843419Patcher::patchInputSectionDescription(
599599
uint64_t startAddr = isec->getVA(off);
600600
if (uint64_t patcheeOffset =
601601
scanCortexA53Errata843419(isec, off, limit))
602-
implementPatch(startAddr, patcheeOffset, isec, patches);
602+
implementPatch(ctx, startAddr, patcheeOffset, isec, patches);
603603
}
604604
if (dataSym == mapSyms.end())
605605
break;

0 commit comments

Comments
 (0)