Skip to content

Commit 319c66a

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:080fb3e5b73b into amd-gfx:7c4daea7af99
Local branch amd-gfx 7c4daea Merged main:ba8565fbcb97 into amd-gfx:ee21db2b70bf Remote branch main 080fb3e [lit] Clean up internal shell parse errors with ScriptFatal (llvm#68496)
2 parents 7c4daea + 080fb3e commit 319c66a

File tree

136 files changed

+4618
-331
lines changed

Some content is hidden

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

136 files changed

+4618
-331
lines changed

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,6 +2462,13 @@ struct CFISnapshot {
24622462
case MCCFIInstruction::OpDefCfaRegister:
24632463
CFAReg = Instr.getRegister();
24642464
CFARule = UNKNOWN;
2465+
2466+
// This shouldn't happen according to the spec but GNU binutils on RISC-V
2467+
// emits a DW_CFA_def_cfa_register in CIE's which leaves the offset
2468+
// unspecified. Both readelf and llvm-dwarfdump interpret the offset as 0
2469+
// in this case so let's do the same.
2470+
if (CFAOffset == UNKNOWN)
2471+
CFAOffset = 0;
24652472
break;
24662473
case MCCFIInstruction::OpDefCfaOffset:
24672474
CFAOffset = Instr.getOffset();

bolt/test/RISCV/Inputs/cie-gnu.yaml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
## Compiled and stripped-down version of:
2+
## (riscv64-linux-gnu-gcc -nostdlib -static -Wl,-q cie-gnu.s)
3+
# .text
4+
# .globl _start
5+
# .type _start, @function
6+
# _start:
7+
# .cfi_startproc
8+
# beq a0, a1, 1f
9+
# ret
10+
# 1:
11+
# .cfi_undefined t0 # Arbitrary cfi command to force a new state
12+
# ret
13+
# .cfi_endproc
14+
# .size _start, .-_start
15+
16+
--- !ELF
17+
FileHeader:
18+
Class: ELFCLASS64
19+
Data: ELFDATA2LSB
20+
Type: ET_EXEC
21+
Machine: EM_RISCV
22+
Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_DOUBLE ]
23+
Entry: 0x10144
24+
ProgramHeaders:
25+
- Type: PT_LOAD
26+
Flags: [ PF_X, PF_R ]
27+
FirstSec: .text
28+
LastSec: .eh_frame
29+
VAddr: 0x10000
30+
Align: 0x1000
31+
Offset: 0x0
32+
Sections:
33+
- Name: .text
34+
Type: SHT_PROGBITS
35+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
36+
Address: 0x10144
37+
AddressAlign: 0x2
38+
Offset: 0x144
39+
Content: 6303B50082808280
40+
- Name: .eh_frame
41+
Type: SHT_PROGBITS
42+
Flags: [ SHF_ALLOC ]
43+
Address: 0x10150
44+
AddressAlign: 0x8
45+
Content: 1000000000000000037A5200017C01011B0D02001000000018000000D8FFFFFF0800000000460705
46+
- Name: .rela.text
47+
Type: SHT_RELA
48+
Flags: [ SHF_INFO_LINK ]
49+
Link: .symtab
50+
AddressAlign: 0x8
51+
Info: .text
52+
Relocations:
53+
- Offset: 0x10144
54+
Symbol: ".L1\x021"
55+
Type: R_RISCV_BRANCH
56+
- Name: .rela.eh_frame
57+
Type: SHT_RELA
58+
Flags: [ SHF_INFO_LINK ]
59+
Link: .symtab
60+
AddressAlign: 0x8
61+
Info: .eh_frame
62+
Relocations:
63+
- Offset: 0x1016C
64+
Symbol: '.L0 '
65+
Type: R_RISCV_32_PCREL
66+
- Offset: 0x10170
67+
Symbol: '.L0 (1)'
68+
Type: R_RISCV_ADD32
69+
- Offset: 0x10170
70+
Symbol: '.L0 '
71+
Type: R_RISCV_SUB32
72+
- Offset: 0x10175
73+
Symbol: '.L0 (2)'
74+
Type: R_RISCV_SET6
75+
- Offset: 0x10175
76+
Symbol: '.L0 '
77+
Type: R_RISCV_SUB6
78+
- Type: SectionHeaderTable
79+
Sections:
80+
- Name: .text
81+
- Name: .rela.text
82+
- Name: .eh_frame
83+
- Name: .rela.eh_frame
84+
- Name: .symtab
85+
- Name: .strtab
86+
- Name: .shstrtab
87+
Symbols:
88+
- Name: '$x'
89+
Section: .text
90+
Value: 0x10144
91+
- Name: ".L1\x021"
92+
Section: .text
93+
Value: 0x1014A
94+
- Name: '.L0 '
95+
Section: .text
96+
Value: 0x10144
97+
- Name: '.L0 (1)'
98+
Section: .text
99+
Value: 0x1014C
100+
- Name: '.L0 (2)'
101+
Section: .text
102+
Value: 0x1014A
103+
- Name: _start
104+
Type: STT_FUNC
105+
Section: .text
106+
Binding: STB_GLOBAL
107+
Value: 0x10144
108+
Size: 0x8
109+
...

bolt/test/RISCV/cie-gnu.test

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Test that BOLT can handle CIE's produced by GNU as. On RISC-V, GNU as produces
2+
# the following initial instruction:
3+
# DW_CFA_def_cfa_register: r2
4+
# While I believe it is technically incorrect to use this instruction without
5+
# first using a DW_CFA_def_cfa (since the offset is unspecified), both readelf
6+
# and llvm-dwarfdump accept this and implicitly set the offset to 0.
7+
# In BOLT, this used to trigger an assert, however, since it (correctly)
8+
# believed the offset was not set. This test checks we can handle this
9+
# situation.
10+
11+
RUN: yaml2obj -o %t %p/Inputs/cie-gnu.yaml
12+
RUN: llvm-bolt -o %t.bolt %t --reorder-blocks=reverse
13+
RUN: llvm-dwarfdump --debug-frame %t.bolt | FileCheck %s
14+
15+
CHECK: 0x400000: CFA=X2
16+
CHECK: 0x400004: CFA=X2: X5=undefined
17+
CHECK: 0x400006: CFA=X2

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "BadSignalToKillThreadCheck.h"
1717
#include "BoolPointerImplicitConversionCheck.h"
1818
#include "BranchCloneCheck.h"
19+
#include "CastingThroughVoidCheck.h"
1920
#include "ComparePointerToMemberVirtualFunctionCheck.h"
2021
#include "CopyConstructorInitCheck.h"
2122
#include "DanglingHandleCheck.h"
@@ -104,6 +105,8 @@ class BugproneModule : public ClangTidyModule {
104105
CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
105106
"bugprone-bool-pointer-implicit-conversion");
106107
CheckFactories.registerCheck<BranchCloneCheck>("bugprone-branch-clone");
108+
CheckFactories.registerCheck<CastingThroughVoidCheck>(
109+
"bugprone-casting-through-void");
107110
CheckFactories.registerCheck<ComparePointerToMemberVirtualFunctionCheck>(
108111
"bugprone-compare-pointer-to-member-virtual-function");
109112
CheckFactories.registerCheck<CopyConstructorInitCheck>(

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_clang_library(clangTidyBugproneModule
1111
BoolPointerImplicitConversionCheck.cpp
1212
BranchCloneCheck.cpp
1313
BugproneTidyModule.cpp
14+
CastingThroughVoidCheck.cpp
1415
ComparePointerToMemberVirtualFunctionCheck.cpp
1516
CopyConstructorInitCheck.cpp
1617
DanglingHandleCheck.cpp
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//===--- CastingThroughVoidCheck.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 "CastingThroughVoidCheck.h"
10+
#include "clang/AST/ASTContext.h"
11+
#include "clang/AST/Expr.h"
12+
#include "clang/AST/Type.h"
13+
#include "clang/ASTMatchers/ASTMatchFinder.h"
14+
#include "clang/ASTMatchers/ASTMatchers.h"
15+
#include "llvm/ADT/StringSet.h"
16+
17+
using namespace clang::ast_matchers;
18+
19+
namespace clang::tidy::bugprone {
20+
21+
void CastingThroughVoidCheck::registerMatchers(MatchFinder *Finder) {
22+
Finder->addMatcher(
23+
explicitCastExpr(
24+
hasDestinationType(
25+
qualType(unless(hasCanonicalType(pointsTo(voidType()))))
26+
.bind("target_type")),
27+
hasSourceExpression(
28+
explicitCastExpr(
29+
hasSourceExpression(
30+
expr(hasType(qualType().bind("source_type")))),
31+
hasDestinationType(
32+
qualType(pointsTo(voidType())).bind("void_type")))
33+
.bind("cast"))),
34+
this);
35+
}
36+
37+
void CastingThroughVoidCheck::check(const MatchFinder::MatchResult &Result) {
38+
const auto TT = *Result.Nodes.getNodeAs<QualType>("target_type");
39+
const auto ST = *Result.Nodes.getNodeAs<QualType>("source_type");
40+
const auto VT = *Result.Nodes.getNodeAs<QualType>("void_type");
41+
const auto *CE = Result.Nodes.getNodeAs<ExplicitCastExpr>("cast");
42+
diag(CE->getExprLoc(), "do not cast %0 to %1 through %2") << ST << TT << VT;
43+
}
44+
45+
} // namespace clang::tidy::bugprone
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===--- CastingThroughVoidCheck.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_CASTINGTHROUGHVOIDCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CASTINGTHROUGHVOIDCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang::tidy::bugprone {
15+
16+
/// Detects unsafe or redundant two-step casting operations involving ``void*``.
17+
/// For the user-facing documentation see:
18+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/casting-through-void.html
19+
class CastingThroughVoidCheck : public ClangTidyCheck {
20+
public:
21+
CastingThroughVoidCheck(StringRef Name, ClangTidyContext *Context)
22+
: ClangTidyCheck(Name, Context) {}
23+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
24+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
25+
std::optional<TraversalKind> getCheckTraversalKind() const override {
26+
return TK_IgnoreUnlessSpelledInSource;
27+
}
28+
};
29+
30+
} // namespace clang::tidy::bugprone
31+
32+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CASTINGTHROUGHVOIDCHECK_H

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ Improvements to clang-tidy
130130
New checks
131131
^^^^^^^^^^
132132

133+
- New :doc:`bugprone-casting-through-void
134+
<clang-tidy/checks/bugprone/casting-through-void>` check.
135+
136+
Detects unsafe or redundant two-step casting operations involving ``void*``.
137+
133138
- New :doc:`bugprone-compare-pointer-to-member-virtual-function
134139
<clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function>` check.
135140

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.. title:: clang-tidy - bugprone-casting-through-void
2+
3+
bugprone-casting-through-void
4+
=============================
5+
6+
Detects unsafe or redundant two-step casting operations involving ``void*``.
7+
8+
Two-step type conversions via ``void*`` are discouraged for several reasons.
9+
10+
- They obscure code and impede its understandability, complicating maintenance.
11+
- These conversions bypass valuable compiler support, erasing warnings related
12+
to pointer alignment. It may violate strict aliasing rule and leading to
13+
undefined behavior.
14+
- In scenarios involving multiple inheritance, ambiguity and unexpected outcomes
15+
can arise due to the loss of type information, posing runtime issues.
16+
17+
In summary, avoiding two-step type conversions through ``void*`` ensures clearer code,
18+
maintains essential compiler warnings, and prevents ambiguity and potential runtime
19+
errors, particularly in complex inheritance scenarios.
20+
21+
Examples:
22+
23+
.. code-block:: c++
24+
25+
using IntegerPointer = int *;
26+
double *ptr;
27+
28+
static_cast<IntegerPointer>(static_cast<void *>(ptr)); // WRONG
29+
reinterpret_cast<IntegerPointer>(reinterpret_cast<void *>(ptr)); // WRONG
30+
(IntegerPointer)(void *)ptr; // WRONG
31+
IntegerPointer(static_cast<void *>(ptr)); // WRONG

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Clang-Tidy Checks
8282
:doc:`bugprone-bad-signal-to-kill-thread <bugprone/bad-signal-to-kill-thread>`,
8383
:doc:`bugprone-bool-pointer-implicit-conversion <bugprone/bool-pointer-implicit-conversion>`, "Yes"
8484
:doc:`bugprone-branch-clone <bugprone/branch-clone>`,
85+
:doc:`bugprone-casting-through-void <bugprone/casting-through-void>`,
8586
:doc:`bugprone-compare-pointer-to-member-virtual-function <bugprone/compare-pointer-to-member-virtual-function>`,
8687
:doc:`bugprone-copy-constructor-init <bugprone/copy-constructor-init>`, "Yes"
8788
:doc:`bugprone-dangling-handle <bugprone/dangling-handle>`,
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// RUN: %check_clang_tidy %s bugprone-casting-through-void %t
2+
3+
using V = void*;
4+
using CV = const void*;
5+
6+
int i = 100;
7+
double d = 100;
8+
const int ci = 100;
9+
const double cd = 100;
10+
11+
void normal_test() {
12+
static_cast<int *>(static_cast<void *>(&d));
13+
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not cast 'double *' to 'int *' through 'void *' [bugprone-casting-through-void]
14+
static_cast<int *>(static_cast<V>(&d));
15+
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not cast 'double *' to 'int *' through 'V' (aka 'void *') [bugprone-casting-through-void]
16+
static_cast<int *>(static_cast<void *>(&i));
17+
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not cast 'int *' to 'int *' through 'void *' [bugprone-casting-through-void]
18+
19+
static_cast<void *>(static_cast<void *>(&i));
20+
}
21+
22+
void const_pointer_test() {
23+
static_cast<int *const>(static_cast<void *>(&d));
24+
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not cast 'double *' to 'int *const' through 'void *' [bugprone-casting-through-void]
25+
static_cast<int *const>(static_cast<V>(&d));
26+
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not cast 'double *' to 'int *const' through 'V' (aka 'void *') [bugprone-casting-through-void]
27+
static_cast<int *const>(static_cast<void *>(&i));
28+
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not cast 'int *' to 'int *const' through 'void *' [bugprone-casting-through-void]
29+
30+
static_cast<void *const>(static_cast<void *>(&i));
31+
}
32+
33+
void const_test() {
34+
static_cast<const int *>(static_cast<const void *>(&d));
35+
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not cast 'double *' to 'const int *' through 'const void *' [bugprone-casting-through-void]
36+
static_cast<const int *>(static_cast<const V>(&d));
37+
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not cast 'double *' to 'const int *' through 'const V' (aka 'void *const') [bugprone-casting-through-void]
38+
static_cast<const int *>(static_cast<const void *>(&i));
39+
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not cast 'int *' to 'const int *' through 'const void *' [bugprone-casting-through-void]
40+
41+
static_cast<const void *>(static_cast<const void *>(&i));
42+
43+
static_cast<const int *>(static_cast<const void *>(&cd));
44+
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not cast 'const double *' to 'const int *' through 'const void *' [bugprone-casting-through-void]
45+
static_cast<const int *>(static_cast<const CV>(&cd));
46+
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not cast 'const double *' to 'const int *' through 'const CV' (aka 'const void *const') [bugprone-casting-through-void]
47+
static_cast<const int *>(static_cast<const void *>(&ci));
48+
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not cast 'const int *' to 'const int *' through 'const void *' [bugprone-casting-through-void]
49+
50+
static_cast<const void *>(static_cast<const void *>(&ci));
51+
}
52+
53+
54+
void reinterpret_cast_test() {
55+
static_cast<int *>(reinterpret_cast<void *>(&d));
56+
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not cast 'double *' to 'int *' through 'void *' [bugprone-casting-through-void]
57+
reinterpret_cast<int *>(static_cast<void *>(&d));
58+
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not cast 'double *' to 'int *' through 'void *' [bugprone-casting-through-void]
59+
reinterpret_cast<int *>(reinterpret_cast<void *>(&d));
60+
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not cast 'double *' to 'int *' through 'void *' [bugprone-casting-through-void]
61+
62+
static_cast<void *>(reinterpret_cast<void *>(&i));
63+
reinterpret_cast<void *>(reinterpret_cast<void *>(&i));
64+
reinterpret_cast<void *>(static_cast<void *>(&i));
65+
}
66+
67+
void c_style_cast_test() {
68+
static_cast<int *>((void *)&d);
69+
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not cast 'double *' to 'int *' through 'void *' [bugprone-casting-through-void]
70+
(int *)(void *)&d;
71+
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not cast 'double *' to 'int *' through 'void *' [bugprone-casting-through-void]
72+
static_cast<int *>((void *)&d);
73+
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not cast 'double *' to 'int *' through 'void *' [bugprone-casting-through-void]
74+
75+
static_cast<void *>((void *)&i);
76+
}
77+
78+
struct A {
79+
A(void*);
80+
};
81+
using I = int *;
82+
void cxx_functional_cast() {
83+
A(static_cast<void*>(&d));
84+
I(static_cast<void*>(&d));
85+
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not cast 'double *' to 'I' (aka 'int *') through 'void *' [bugprone-casting-through-void]
86+
}
87+
88+
void bit_cast() {
89+
__builtin_bit_cast(int *, static_cast<void *>(&d));
90+
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: do not cast 'double *' to 'int *' through 'void *' [bugprone-casting-through-void]
91+
}

0 commit comments

Comments
 (0)