26 changes: 12 additions & 14 deletions bolt/test/X86/dwarf4-df-dualcu.test
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,14 @@
; BOLT-NEXT: 00000010 [[#%.16x,ADDR1:]] [[#%.16x,ADDRB1:]]
; BOLT-NEXT: 00000010 [[#%.16x,ADDR2:]] [[#%.16x,ADDRB2:]]
; BOLT-NEXT: 00000010 <End of list>
; BOLT-NEXT: 00000040 [[#%.16x,ADDR1:]] [[#%.16x,ADDRB1:]]
; BOLT-NEXT: 00000040 <End of list>
; BOLT-NEXT: 00000050 [[#%.16x,ADDR1:]] [[#%.16x,ADDRB1:]]
; BOLT-NEXT: 00000050 <End of list>
; BOLT-NEXT: 00000070 [[#%.16x,ADDR2:]] [[#%.16x,ADDRB2:]]
; BOLT-NEXT: 00000070 <End of list>
; BOLT-NEXT: 00000090 [[#%.16x,ADDR3:]] [[#%.16x,ADDRB3:]]
; BOLT-NEXT: 00000090 <End of list>
; BOLT-NEXT: 000000b0 <End of list>
; BOLT-NEXT: 000000c0 [[#%.16x,ADDR3:]] [[#%.16x,ADDRB3:]]
; BOLT-NEXT: 000000c0 <End of list>
; BOLT-NEXT: 00000060 [[#%.16x,ADDR2:]] [[#%.16x,ADDRB2:]]
; BOLT-NEXT: 00000060 <End of list>
; BOLT-NEXT: 00000080 [[#%.16x,ADDR3:]] [[#%.16x,ADDRB3:]]
; BOLT-NEXT: 00000080 <End of list>
; BOLT-NEXT: 000000a0 [[#%.16x,ADDR3:]] [[#%.16x,ADDRB3:]]
; BOLT-NEXT: 000000a0 <End of list>

; BOLT: DW_TAG_compile_unit
; BOLT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000016] = "main.dwo.dwo")
Expand All @@ -65,10 +63,10 @@
; BOLT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000023] = "helper.dwo.dwo")
; BOLT-NEXT: DW_AT_GNU_dwo_id
; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
; BOLT-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000090
; BOLT-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000080
; BOLT-NEXT: [0x[[#ADDR3]], 0x[[#ADDRB3]])
; BOLT-NEXT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] (0x00000010)
; BOLT-NEXT: DW_AT_GNU_ranges_base [DW_FORM_sec_offset] (0x000000b0)
; BOLT-NEXT: DW_AT_GNU_ranges_base [DW_FORM_sec_offset] (0x000000a0)

; PRE-BOLT-DWO-MAIN: version = 0x0004
; PRE-BOLT-DWO-MAIN: DW_TAG_compile_unit
Expand Down Expand Up @@ -115,13 +113,13 @@
; BOLT-DWO-MAIN-NEXT: DW_AT_decl_line
; BOLT-DWO-MAIN-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x1)
; BOLT-DWO-MAIN: DW_TAG_subprogram [4]
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000010
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
; BOLT-DWO-MAIN-NEXT: )
; BOLT-DWO-MAIN-NEXT: DW_AT_frame_base
; BOLT-DWO-MAIN-NEXT: DW_AT_linkage_name [DW_FORM_GNU_str_index] (indexed (00000003) string = "_Z3usePiS_")
; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000004) string = "use")
; BOLT-DWO-MAIN: DW_TAG_subprogram [6]
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000030
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000020
; BOLT-DWO-MAIN-NEXT: )
; BOLT-DWO-MAIN-NEXT: DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_reg6 RBP)
; BOLT-DWO-MAIN-NEXT: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000005) string = "main")
Expand Down Expand Up @@ -162,4 +160,4 @@
; BOLT-DWO-HELPER-NEXT: DW_AT_decl_line
; BOLT-DWO-HELPER-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x1)
; BOLT-DWO-HELPER: DW_TAG_subprogram [4]
; BOLT-DWO-HELPER-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000010
; BOLT-DWO-HELPER-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
60 changes: 29 additions & 31 deletions bolt/test/X86/dwarf4-df-input-lowpc-ranges-cus.test
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,30 @@
; BOLT-NEXT: 00000010 [[#%.16x,ADDR6:]] [[#%.16x,ADDRB6:]]
; BOLT-NEXT: 00000010 [[#%.16x,ADDR7:]] [[#%.16x,ADDRB7:]]
; BOLT-NEXT: 00000010 <End of list>
; BOLT-NEXT: 00000090 [[#%.16x,ADDR1:]] [[#%.16x,ADDRB1:]]
; BOLT-NEXT: 00000090 [[#%.16x,ADDR2:]] [[#%.16x,ADDRB2:]]
; BOLT-NEXT: 00000090 [[#%.16x,ADDR3:]] [[#%.16x,ADDRB3:]]
; BOLT-NEXT: 00000090 <End of list>
; BOLT-NEXT: 000000a0 [[#%.16x,ADDR1:]] [[#%.16x,ADDRB1:]]
; BOLT-NEXT: 000000a0 [[#%.16x,ADDR2:]] [[#%.16x,ADDRB2:]]
; BOLT-NEXT: 000000a0 [[#%.16x,ADDR3:]] [[#%.16x,ADDRB3:]]
; BOLT-NEXT: 000000a0 <End of list>
; BOLT-NEXT: 000000e0 [[#%.16x,ADDR5:]] [[#%.16x,ADDRB5:]]
; BOLT-NEXT: 000000e0 [[#%.16x,ADDR6:]] [[#%.16x,ADDRB6:]]
; BOLT-NEXT: 000000e0 [[#%.16x,ADDR7:]] [[#%.16x,ADDRB7:]]
; BOLT-NEXT: 000000e0 <End of list>
; BOLT-NEXT: 00000120 [[#%.16x,ADDR8:]] [[#%.16x,ADDRB8:]]
; BOLT-NEXT: 00000120 [[#%.16x,ADDR9:]] [[#%.16x,ADDRB9:]]
; BOLT-NEXT: 00000120 [[#%.16x,ADDR10:]] [[#%.16x,ADDRB10:]]
; BOLT-NEXT: 00000120 [[#%.16x,ADDR11:]] [[#%.16x,ADDRB11:]]
; BOLT-NEXT: 00000120 [[#%.16x,ADDR12:]] [[#%.16x,ADDRB12:]]
; BOLT-NEXT: 00000120 [[#%.16x,ADDR13:]] [[#%.16x,ADDRB13:]]
; BOLT-NEXT: 00000120 [[#%.16x,ADDR14:]] [[#%.16x,ADDRB14:]]
; BOLT-NEXT: 00000120 <End of list>
; BOLT-NEXT: 000001a0 <End of list>
; BOLT-NEXT: 000001b0 [[#%.16x,ADDR8:]] [[#%.16x,ADDRB8:]]
; BOLT-NEXT: 000001b0 [[#%.16x,ADDR9:]] [[#%.16x,ADDRB9:]]
; BOLT-NEXT: 000001b0 [[#%.16x,ADDR10:]] [[#%.16x,ADDRB10:]]
; BOLT-NEXT: 000001b0 <End of list>
; BOLT-NEXT: 000001f0 [[#%.16x,ADDR12:]] [[#%.16x,ADDRB12:]]
; BOLT-NEXT: 000001f0 [[#%.16x,ADDR13:]] [[#%.16x,ADDRB13:]]
; BOLT-NEXT: 000001f0 [[#%.16x,ADDR14:]] [[#%.16x,ADDRB14:]]
; BOLT-NEXT: 000001f0 <End of list>
; BOLT-NEXT: 000000d0 [[#%.16x,ADDR5:]] [[#%.16x,ADDRB5:]]
; BOLT-NEXT: 000000d0 [[#%.16x,ADDR6:]] [[#%.16x,ADDRB6:]]
; BOLT-NEXT: 000000d0 [[#%.16x,ADDR7:]] [[#%.16x,ADDRB7:]]
; BOLT-NEXT: 000000d0 <End of list>
; BOLT-NEXT: 00000110 [[#%.16x,ADDR8:]] [[#%.16x,ADDRB8:]]
; BOLT-NEXT: 00000110 [[#%.16x,ADDR9:]] [[#%.16x,ADDRB9:]]
; BOLT-NEXT: 00000110 [[#%.16x,ADDR10:]] [[#%.16x,ADDRB10:]]
; BOLT-NEXT: 00000110 [[#%.16x,ADDR11:]] [[#%.16x,ADDRB11:]]
; BOLT-NEXT: 00000110 [[#%.16x,ADDR12:]] [[#%.16x,ADDRB12:]]
; BOLT-NEXT: 00000110 [[#%.16x,ADDR13:]] [[#%.16x,ADDRB13:]]
; BOLT-NEXT: 00000110 [[#%.16x,ADDR14:]] [[#%.16x,ADDRB14:]]
; BOLT-NEXT: 00000110 <End of list>
; BOLT-NEXT: 00000190 [[#%.16x,ADDR8:]] [[#%.16x,ADDRB8:]]
; BOLT-NEXT: 00000190 [[#%.16x,ADDR9:]] [[#%.16x,ADDRB9:]]
; BOLT-NEXT: 00000190 [[#%.16x,ADDR10:]] [[#%.16x,ADDRB10:]]
; BOLT-NEXT: 00000190 <End of list>
; BOLT-NEXT: 000001d0 [[#%.16x,ADDR12:]] [[#%.16x,ADDRB12:]]
; BOLT-NEXT: 000001d0 [[#%.16x,ADDR13:]] [[#%.16x,ADDRB13:]]
; BOLT-NEXT: 000001d0 [[#%.16x,ADDR14:]] [[#%.16x,ADDRB14:]]
; BOLT-NEXT: 000001d0 <End of list>

; BOLT: DW_TAG_compile_unit
; BOLT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-fA-F]+}}] = "main.dwo.dwo")
Expand All @@ -71,9 +69,9 @@
; BOLT: DW_TAG_compile_unit
; BOLT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-fA-F]+}}] = "mainOther.dwo.dwo")
; BOLT-NEXT: DW_AT_GNU_dwo_id
; BOLT-NEXT: DW_AT_GNU_ranges_base [DW_FORM_sec_offset] (0x000001a0)
; BOLT-NEXT: DW_AT_GNU_ranges_base [DW_FORM_sec_offset] (0x00000190)
; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
; BOLT-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000120
; BOLT-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000110
; BOLT-NEXT: [0x[[#ADDR8]], 0x[[#ADDRB8]])
; BOLT-NEXT: [0x[[#ADDR9]], 0x[[#ADDRB9]])
; BOLT-NEXT: [0x[[#ADDR10]], 0x[[#ADDRB10]])
Expand All @@ -85,17 +83,17 @@
; BOLT: {{^$}}

; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000010
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000050
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000040

; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000010
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000050
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000040
19 changes: 9 additions & 10 deletions bolt/test/X86/dwarf4-df-input-lowpc-ranges.test
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@
; BOLT-NEXT: 00000010 [[#%.16x,ADDR6:]] [[#%.16x,ADDRB6:]]
; BOLT-NEXT: 00000010 [[#%.16x,ADDR7:]] [[#%.16x,ADDRB7:]]
; BOLT-NEXT: 00000010 <End of list>
; BOLT-NEXT: 00000090 [[#%.16x,ADDR1:]] [[#%.16x,ADDRB1:]]
; BOLT-NEXT: 00000090 [[#%.16x,ADDR2:]] [[#%.16x,ADDRB2:]]
; BOLT-NEXT: 00000090 [[#%.16x,ADDR3:]] [[#%.16x,ADDRB3:]]
; BOLT-NEXT: 00000090 <End of list>
; BOLT-NEXT: 000000a0 [[#%.16x,ADDR1:]] [[#%.16x,ADDRB1:]]
; BOLT-NEXT: 000000a0 [[#%.16x,ADDR2:]] [[#%.16x,ADDRB2:]]
; BOLT-NEXT: 000000a0 [[#%.16x,ADDR3:]] [[#%.16x,ADDRB3:]]
; BOLT-NEXT: 000000a0 <End of list>
; BOLT-NEXT: 000000e0 [[#%.16x,ADDR5:]] [[#%.16x,ADDRB5:]]
; BOLT-NEXT: 000000e0 [[#%.16x,ADDR6:]] [[#%.16x,ADDRB6:]]
; BOLT-NEXT: 000000e0 [[#%.16x,ADDR7:]] [[#%.16x,ADDRB7:]]
; BOLT-NEXT: 000000e0 <End of list>
; BOLT-NEXT: 000000d0 [[#%.16x,ADDR5:]] [[#%.16x,ADDRB5:]]
; BOLT-NEXT: 000000d0 [[#%.16x,ADDR6:]] [[#%.16x,ADDRB6:]]
; BOLT-NEXT: 000000d0 [[#%.16x,ADDR7:]] [[#%.16x,ADDRB7:]]
; BOLT-NEXT: 000000d0 <End of list>

; BOLT: DW_TAG_compile_unit
; BOLT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-fA-F]+}}] = "main.dwo.dwo")
Expand All @@ -49,9 +48,9 @@
; BOLT-NEXT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] (0x00000000)

; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000010
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000050
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_sec_offset] (0x00000040
162 changes: 162 additions & 0 deletions bolt/test/X86/match-functions-with-calls-as-anchors.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
## Tests blocks matching by called function names in inferStaleProfile.

# REQUIRES: system-linux
# RUN: split-file %s %t
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib
# RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml --profile-ignore-hash -v=1 \
# RUN: --dyno-stats --print-cfg --infer-stale-profile=1 --debug 2>&1 | FileCheck %s

# CHECK: BOLT-INFO: applying profile inference for "qux"
# CHECK: Matched yaml block (bid = 1) with hash 4 to BB (index = 0) with hash 314e1bc10000
# CHECK: loose match

# CHECK: BOLT-INFO: applying profile inference for "fred"
# CHECK: Matched yaml block (bid = 1) with hash 5 to BB (index = 0) with hash 7541bc10000
# CHECK: loose match

#--- main.s
.globl foo # -- Begin function foo
.p2align 4, 0x90
.type foo,@function
foo: # @foo
# %bb.0:
pushq %rbp
movq %rsp, %rbp
popq %rbp
retq
.Lfunc_end0:
.size foo, .Lfunc_end0-foo
# -- End function
.globl bar # -- Begin function bar
.p2align 4, 0x90
.type bar,@function
bar: # @bar
# %bb.0:
pushq %rbp
movq %rsp, %rbp
popq %rbp
retq
.Lfunc_end1:
.size bar, .Lfunc_end1-bar
# -- End function
.globl qux # -- Begin function qux
.p2align 4, 0x90
.type qux,@function
qux: # @qux
# %bb.0:
pushq %rbp
movq %rsp, %rbp
callq foo
callq bar
popq %rbp
retq
.Lfunc_end2:
.size qux, .Lfunc_end2-qux
# -- End function
.globl fred # -- Begin function fred
.p2align 4, 0x90
.type fred,@function
fred: # @fred
# %bb.0:
pushq %rbp
movq %rsp, %rbp
callq foo
callq qux
callq bar
callq bar
callq foo
popq %rbp
retq
.Lfunc_end3:
.size fred, .Lfunc_end3-fred
# -- End function
.globl main # -- Begin function main
.p2align 4, 0x90
.type main,@function
main: # @main
# %bb.0:
pushq %rbp
movq %rsp, %rbp
xorl %eax, %eax
popq %rbp
retq
.Lfunc_end4:
.size main, .Lfunc_end4-main
# -- End function
.addrsig
.addrsig_sym foo
.addrsig_sym bar
.addrsig_sym qux

#--- yaml
---
header:
profile-version: 1
binary-name: 'match-functions-with-calls-as-anchors.s.tmp.exe'
binary-build-id: '<unknown>'
profile-flags: [ lbr ]
profile-origin: branch profile reader
profile-events: ''
dfs-order: false
hash-func: xxh3
functions:
- name: main
fid: 0
hash: 0x0000000000000001
exec: 1
nblocks: 6
blocks:
- bid: 1
hash: 0x0000000000000001
insns: 1
succ: [ { bid: 3, cnt: 1} ]
- name: foo
fid: 1
hash: 0x0000000000000002
exec: 1
nblocks: 6
blocks:
- bid: 1
hash: 0x0000000000000002
insns: 1
succ: [ { bid: 3, cnt: 1} ]

- name: bar
fid: 2
hash: 0x0000000000000003
exec: 1
nblocks: 6
blocks:
- bid: 1
hash: 0x0000000000000003
insns: 1
succ: [ { bid: 3, cnt: 1} ]
- name: qux
fid: 3
hash: 0x0000000000000004
exec: 4
nblocks: 6
blocks:
- bid: 1
hash: 0x0000000000000004
insns: 1
succ: [ { bid: 3, cnt: 1} ]
calls: [ { off : 0, fid : 1, cnt : 0},
{ off : 0, fid : 2, cnt : 0} ]
- name: fred
fid: 4
hash: 0x0000000000000005
exec: 1
nblocks: 6
blocks:
- bid: 1
hash: 0x0000000000000005
insns: 1
succ: [ { bid: 3, cnt: 1} ]
calls: [ { off : 0, fid : 3, cnt : 0},
{ off : 0, fid : 1, cnt : 0},
{ off : 0, fid : 2, cnt : 0},
{ off : 0, fid : 1, cnt : 0},
{ off : 0, fid : 2, cnt : 0} ]
...
56 changes: 29 additions & 27 deletions clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ class UseAfterMoveFinder {
// occurs after 'MovingCall' (the expression that performs the move). If a
// use-after-move is found, writes information about it to 'TheUseAfterMove'.
// Returns whether a use-after-move was found.
bool find(Stmt *CodeBlock, const Expr *MovingCall,
const DeclRefExpr *MovedVariable, UseAfterMove *TheUseAfterMove);
std::optional<UseAfterMove> find(Stmt *CodeBlock, const Expr *MovingCall,
const DeclRefExpr *MovedVariable);

private:
bool findInternal(const CFGBlock *Block, const Expr *MovingCall,
const ValueDecl *MovedVariable,
UseAfterMove *TheUseAfterMove);
std::optional<UseAfterMove> findInternal(const CFGBlock *Block,
const Expr *MovingCall,
const ValueDecl *MovedVariable);
void getUsesAndReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
llvm::SmallPtrSetImpl<const Stmt *> *Reinits);
Expand Down Expand Up @@ -95,9 +95,9 @@ static StatementMatcher inDecltypeOrTemplateArg() {
UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
: Context(TheContext) {}

bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
const DeclRefExpr *MovedVariable,
UseAfterMove *TheUseAfterMove) {
std::optional<UseAfterMove>
UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
const DeclRefExpr *MovedVariable) {
// Generate the CFG manually instead of through an AnalysisDeclContext because
// it seems the latter can't be used to generate a CFG for the body of a
// lambda.
Expand All @@ -111,7 +111,7 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
std::unique_ptr<CFG> TheCFG =
CFG::buildCFG(nullptr, CodeBlock, Context, Options);
if (!TheCFG)
return false;
return std::nullopt;

Sequence = std::make_unique<ExprSequence>(TheCFG.get(), CodeBlock, Context);
BlockMap = std::make_unique<StmtToBlockMap>(TheCFG.get(), Context);
Expand All @@ -125,10 +125,10 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
MoveBlock = &TheCFG->getEntry();
}

bool Found = findInternal(MoveBlock, MovingCall, MovedVariable->getDecl(),
TheUseAfterMove);
auto TheUseAfterMove =
findInternal(MoveBlock, MovingCall, MovedVariable->getDecl());

if (Found) {
if (TheUseAfterMove) {
if (const CFGBlock *UseBlock =
BlockMap->blockContainingStmt(TheUseAfterMove->DeclRef)) {
// Does the use happen in a later loop iteration than the move?
Expand All @@ -142,15 +142,14 @@ bool UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall,
: CFA.isReachable(UseBlock, MoveBlock);
}
}
return Found;
return TheUseAfterMove;
}

bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
const Expr *MovingCall,
const ValueDecl *MovedVariable,
UseAfterMove *TheUseAfterMove) {
std::optional<UseAfterMove>
UseAfterMoveFinder::findInternal(const CFGBlock *Block, const Expr *MovingCall,
const ValueDecl *MovedVariable) {
if (Visited.count(Block))
return false;
return std::nullopt;

// Mark the block as visited (except if this is the block containing the
// std::move() and it's being visited the first time).
Expand Down Expand Up @@ -189,17 +188,18 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
}

if (!HaveSavingReinit) {
TheUseAfterMove->DeclRef = Use;
UseAfterMove TheUseAfterMove;
TheUseAfterMove.DeclRef = Use;

// Is this a use-after-move that depends on order of evaluation?
// This is the case if the move potentially comes after the use (and we
// already know that use potentially comes after the move, which taken
// together tells us that the ordering is unclear).
TheUseAfterMove->EvaluationOrderUndefined =
TheUseAfterMove.EvaluationOrderUndefined =
MovingCall != nullptr &&
Sequence->potentiallyAfter(MovingCall, Use);

return true;
return TheUseAfterMove;
}
}
}
Expand All @@ -208,12 +208,15 @@ bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
// successors.
if (Reinits.empty()) {
for (const auto &Succ : Block->succs()) {
if (Succ && findInternal(Succ, nullptr, MovedVariable, TheUseAfterMove))
return true;
if (Succ) {
if (auto Found = findInternal(Succ, nullptr, MovedVariable)) {
return Found;
}
}
}
}

return false;
return std::nullopt;
}

void UseAfterMoveFinder::getUsesAndReinits(
Expand Down Expand Up @@ -518,9 +521,8 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {

for (Stmt *CodeBlock : CodeBlocks) {
UseAfterMoveFinder Finder(Result.Context);
UseAfterMove Use;
if (Finder.find(CodeBlock, MovingCall, Arg, &Use))
emitDiagnostic(MovingCall, Arg, Use, this, Result.Context,
if (auto Use = Finder.find(CodeBlock, MovingCall, Arg))
emitDiagnostic(MovingCall, Arg, *Use, this, Result.Context,
determineMoveType(MoveDecl));
}
}
Expand Down
6 changes: 6 additions & 0 deletions clang/docs/CommandGuide/clang.rst
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,12 @@ number of cross compilers, or may only support a native target.
allowed to generate instructions that are valid on i486 and later processors,
but which may not exist on earlier ones.

.. option:: --print-enabled-extensions

Prints the list of extensions that are enabled for the target specified by the
combination of `--target`, `-march`, and `-mcpu` values. Currently, this
option is only supported on AArch64 and RISC-V. On RISC-V, this option also
prints out the ISA string of enabled extensions.

Code Generation Options
~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
62 changes: 54 additions & 8 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ C23 Feature Support
- Clang now supports `N3017 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm>`_
``#embed`` - a scannable, tooling-friendly binary resource inclusion mechanism.

- Added the ``FLT_NORM_MAX``, ``DBL_NORM_MAX``, and ``LDBL_NORM_MAX`` to the
freestanding implementation of ``<float.h>`` that ships with Clang.

Non-comprehensive list of changes in this release
-------------------------------------------------

Expand Down Expand Up @@ -454,6 +457,9 @@ New Compiler Flags
that relies on it. Users should carefully consider this possibiilty when using
the flag.

- For the ARM target, added ``-Warm-interrupt-vfp-clobber`` that will emit a
diagnostic when an interrupt handler is declared and VFP is enabled.

Deprecated Compiler Flags
-------------------------

Expand Down Expand Up @@ -496,6 +502,13 @@ Modified Compiler Flags
now include dianostics about C++26 features that are not present in older
versions.

- Removed the "arm interrupt calling convention" warning that was included in
``-Wextra`` without its own flag. This warning suggested adding
``__attribute__((interrupt))`` to functions that are called from interrupt
handlers to prevent clobbering VFP registers. Following this suggestion leads
to unpredictable behavior by causing multiple exception returns from one
exception. Fixes #GH34876.

Removed Compiler Flags
-------------------------

Expand Down Expand Up @@ -690,6 +703,8 @@ Improvements to Clang's diagnostics
- Clang no longer emits a "no previous prototype" warning for Win32 entry points under ``-Wmissing-prototypes``.
Fixes #GH94366.

- For the ARM target, calling an interrupt handler from another function is now an error. #GH95359.

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

Expand Down Expand Up @@ -798,6 +813,8 @@ Bug Fixes in This Version

- Fixed `static_cast` to array of unknown bound. Fixes (#GH62863).

- Fixed Clang crashing when failing to perform some C++ Initialization Sequences. (#GH98102)

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -1197,27 +1214,56 @@ libclang
Static Analyzer
---------------

New features
^^^^^^^^^^^^

- The attribute ``[[clang::suppress]]`` can now be applied to declarations.
(#GH80371)

- Support C++23 static operator calls. (#GH84972)

Crash and bug fixes
^^^^^^^^^^^^^^^^^^^

- Fixed crashing on loops if the loop variable was declared in switch blocks
but not under any case blocks if ``unroll-loops=true`` analyzer config is
set. (#GH68819)
- Support C++23 static operator calls. (#GH84972)

- Fixed a crash in ``security.cert.env.InvalidPtr`` checker when accidentally
matched user-defined ``strerror`` and similar library functions. (GH#88181)
matched user-defined ``strerror`` and similar library functions. (#GH88181)

- Fixed a crash when storing through an address that refers to the address of
a label. (GH#89185)
a label. (#GH89185)

New features
^^^^^^^^^^^^

Crash and bug fixes
^^^^^^^^^^^^^^^^^^^
- Z3 crosschecking (aka. Z3 refutation) is now bounded, and can't consume
more total time than the eymbolic execution itself. (#GH97298)

Improvements
^^^^^^^^^^^^

Moved checkers
^^^^^^^^^^^^^^

- Moved ``alpha.cplusplus.ArrayDelete`` out of the ``alpha`` package
to ``cplusplus.ArrayDelete``. (#GH83985)
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#cplusplus-arraydelete-c>`__.

- Moved ``alpha.unix.Stream`` out of the ``alpha`` package to
``unix.Stream``. (#GH89247)
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#unix-stream-c>`__.

- Moved ``alpha.unix.BlockInCriticalSection`` out of the ``alpha`` package to
``unix.BlockInCriticalSection``. (#GH93815)
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#unix-blockincriticalsection-c-c>`__.

- Moved ``alpha.security.cert.pos.34c`` out of the ``alpha`` package to
``security.PutenvStackArray``. (#GH92424, #GH93815)
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#security-putenvstackarray-c>`__.

- Moved ``alpha.core.SizeofPtr`` into ``clang-tidy``
``bugprone-sizeof-expression``. (#GH95118, #GH94356)
`Documentation <https://clang.llvm.org/extra/clang-tidy/checks/bugprone/sizeof-expression.html>`__.

.. _release-notes-sanitizers:

Sanitizers
Expand Down
11 changes: 4 additions & 7 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1003,17 +1003,14 @@ array new C++ operator is tainted (potentially attacker controlled).
If an attacker can inject a large value as the size parameter, memory exhaustion
denial of service attack can be carried out.
The ``alpha.security.taint.TaintPropagation`` checker also needs to be enabled for
this checker to give warnings.
The analyzer emits warning only if it cannot prove that the size parameter is
within reasonable bounds (``<= SIZE_MAX/4``). This functionality partially
covers the SEI Cert coding standard rule `INT04-C
<https://wiki.sei.cmu.edu/confluence/display/c/INT04-C.+Enforce+limits+on+integer+values+originating+from+tainted+sources>`_.
You can silence this warning either by bound checking the ``size`` parameter, or
by explicitly marking the ``size`` parameter as sanitized. See the
:ref:`alpha-security-taint-TaintPropagation` checker for more details.
:ref:`alpha-security-taint-GenericTaint` checker for an example.
.. code-block:: c
Expand Down Expand Up @@ -3011,10 +3008,10 @@ alpha.security.taint
Checkers implementing
`taint analysis <https://en.wikipedia.org/wiki/Taint_checking>`_.
.. _alpha-security-taint-TaintPropagation:
.. _alpha-security-taint-GenericTaint:
alpha.security.taint.TaintPropagation (C, C++)
""""""""""""""""""""""""""""""""""""""""""""""
alpha.security.taint.GenericTaint (C, C++)
""""""""""""""""""""""""""""""""""""""""""
Taint analysis identifies potential security vulnerabilities where the
attacker can inject malicious data to the program to execute an attack
Expand Down
13 changes: 8 additions & 5 deletions clang/docs/analyzer/user-docs/TaintAnalysisConfiguration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
Taint Analysis Configuration
============================

The Clang Static Analyzer uses taint analysis to detect security-related issues in code.
The backbone of taint analysis in the Clang SA is the `GenericTaintChecker`, which the user can access via the :ref:`alpha-security-taint-TaintPropagation` checker alias and this checker has a default taint-related configuration.
The built-in default settings are defined in code, and they are always in effect once the checker is enabled, either directly or via the alias.
The checker also provides a configuration interface for extending the default settings by providing a configuration file in `YAML <http://llvm.org/docs/YamlIO.html#introduction-to-yaml>`_ format.
The Clang Static Analyzer uses taint analysis to detect injection vulnerability related issues in code.
The backbone of taint analysis in the Clang SA is the ``TaintPropagation`` modeling checker.
The reports are emitted via the :ref:`alpha-security-taint-GenericTaint` checker.
The ``TaintPropagation`` checker has a default taint-related configuration.
The built-in default settings are defined in code, and they are always in effect.
The checker also provides a configuration interface for extending the default settings via the ``alpha.security.taint.TaintPropagation:Config`` checker config parameter
by providing a configuration file to the in `YAML <http://llvm.org/docs/YamlIO.html#introduction-to-yaml>`_ format.
This documentation describes the syntax of the configuration file and gives the informal semantics of the configuration options.

.. contents::
Expand All @@ -18,7 +21,7 @@ ________

Taint analysis works by checking for the occurrence of special operations during the symbolic execution of the program.
Taint analysis defines sources, sinks, and propagation rules. It identifies errors by detecting a flow of information that originates from a taint source, reaches a taint sink, and propagates through the program paths via propagation rules.
A source, sink, or an operation that propagates taint is mainly domain-specific knowledge, but there are some built-in defaults provided by :ref:`alpha-security-taint-TaintPropagation`.
A source, sink, or an operation that propagates taint is mainly domain-specific knowledge, but there are some built-in defaults provided by the ``TaintPropagation`` checker.
It is possible to express that a statement sanitizes tainted values by providing a ``Filters`` section in the external configuration (see :ref:`clangsa-taint-configuration-example` and :ref:`clangsa-taint-filter-details`).
There are no default filters defined in the built-in settings.
The checker's documentation also specifies how to provide a custom taint configuration with command-line options.
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/APINotes/APINotesReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class APINotesReader {
/// \param Name The name of the class we're looking for.
///
/// \returns The information about the class, if known.
VersionedInfo<ObjCContextInfo> lookupObjCClassInfo(llvm::StringRef Name);
VersionedInfo<ContextInfo> lookupObjCClassInfo(llvm::StringRef Name);

/// Look for the context ID of the given Objective-C protocol.
///
Expand All @@ -115,7 +115,7 @@ class APINotesReader {
/// \param Name The name of the protocol we're looking for.
///
/// \returns The information about the protocol, if known.
VersionedInfo<ObjCContextInfo> lookupObjCProtocolInfo(llvm::StringRef Name);
VersionedInfo<ContextInfo> lookupObjCProtocolInfo(llvm::StringRef Name);

/// Look for information regarding the given Objective-C property in
/// the given context.
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/APINotes/APINotesWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ class APINotesWriter {
///
/// \returns the ID of the class, protocol, or namespace, which can be used to
/// add properties and methods to the class/protocol/namespace.
ContextID addObjCContext(std::optional<ContextID> ParentCtxID,
llvm::StringRef Name, ContextKind Kind,
const ObjCContextInfo &Info,
llvm::VersionTuple SwiftVersion);
ContextID addContext(std::optional<ContextID> ParentCtxID,
llvm::StringRef Name, ContextKind Kind,
const ContextInfo &Info,
llvm::VersionTuple SwiftVersion);

/// Add information about a specific Objective-C property.
///
Expand Down
19 changes: 10 additions & 9 deletions clang/include/clang/APINotes/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
return !(LHS == RHS);
}

/// Describes API notes data for an Objective-C class or protocol.
class ObjCContextInfo : public CommonTypeInfo {
/// Describes API notes data for an Objective-C class or protocol or a C++
/// namespace.
class ContextInfo : public CommonTypeInfo {
/// Whether this class has a default nullability.
LLVM_PREFERRED_TYPE(bool)
unsigned HasDefaultNullability : 1;
Expand All @@ -217,7 +218,7 @@ class ObjCContextInfo : public CommonTypeInfo {
unsigned SwiftObjCMembers : 1;

public:
ObjCContextInfo()
ContextInfo()
: HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0),
SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false),
SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {}
Expand Down Expand Up @@ -269,9 +270,9 @@ class ObjCContextInfo : public CommonTypeInfo {
DefaultNullability = 0;
}

friend bool operator==(const ObjCContextInfo &, const ObjCContextInfo &);
friend bool operator==(const ContextInfo &, const ContextInfo &);

ObjCContextInfo &operator|=(const ObjCContextInfo &RHS) {
ContextInfo &operator|=(const ContextInfo &RHS) {
// Merge inherited info.
static_cast<CommonTypeInfo &>(*this) |= RHS;

Expand All @@ -294,15 +295,15 @@ class ObjCContextInfo : public CommonTypeInfo {
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
};

inline bool operator==(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
inline bool operator==(const ContextInfo &LHS, const ContextInfo &RHS) {
return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
LHS.getDefaultNullability() == RHS.getDefaultNullability() &&
LHS.HasDesignatedInits == RHS.HasDesignatedInits &&
LHS.getSwiftImportAsNonGeneric() == RHS.getSwiftImportAsNonGeneric() &&
LHS.getSwiftObjCMembers() == RHS.getSwiftObjCMembers();
}

inline bool operator!=(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
inline bool operator!=(const ContextInfo &LHS, const ContextInfo &RHS) {
return !(LHS == RHS);
}

Expand Down Expand Up @@ -387,7 +388,7 @@ class ObjCPropertyInfo : public VariableInfo {
friend bool operator==(const ObjCPropertyInfo &, const ObjCPropertyInfo &);

/// Merge class-wide information into the given property.
ObjCPropertyInfo &operator|=(const ObjCContextInfo &RHS) {
ObjCPropertyInfo &operator|=(const ContextInfo &RHS) {
static_cast<CommonEntityInfo &>(*this) |= RHS;

// Merge nullability.
Expand Down Expand Up @@ -626,7 +627,7 @@ class ObjCMethodInfo : public FunctionInfo {

friend bool operator==(const ObjCMethodInfo &, const ObjCMethodInfo &);

ObjCMethodInfo &operator|=(const ObjCContextInfo &RHS) {
ObjCMethodInfo &operator|=(const ContextInfo &RHS) {
// Merge Nullability.
if (!NullabilityAudited) {
if (auto Nullable = RHS.getDefaultNullability()) {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticFrontendKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ def err_module_map_not_found : Error<"module map file '%0' not found">,
def err_missing_module_name : Error<
"no module name provided; specify one with -fmodule-name=">,
DefaultFatal;
def err_file_is_not_module : Error<"file '%0' is not a module file">, DefaultFatal;
def err_missing_module : Error<
"no module named '%0' declared in module map file '%1'">, DefaultFatal;
def err_no_submodule : Error<"no submodule named %0 in module '%1'">;
Expand Down
9 changes: 6 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,12 @@ def warn_anyx86_excessive_regsave : Warning<
" with attribute 'no_caller_saved_registers'"
" or be compiled with '-mgeneral-regs-only'">,
InGroup<DiagGroup<"excessive-regsave">>;
def warn_arm_interrupt_calling_convention : Warning<
"call to function without interrupt attribute could clobber interruptee's VFP registers">,
InGroup<Extra>;
def warn_arm_interrupt_vfp_clobber : Warning<
"interrupt service routine with vfp enabled may clobber the "
"interruptee's vfp state">,
InGroup<DiagGroup<"arm-interrupt-vfp-clobber">>;
def err_arm_interrupt_called : Error<
"interrupt service routine cannot be called directly">;
def warn_interrupt_attribute_invalid : Warning<
"%select{MIPS|MSP430|RISC-V}0 'interrupt' attribute only applies to "
"functions that have %select{no parameters|a 'void' return type}1">,
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1434,7 +1434,12 @@ class TargetInfo : public TransferrableTargetInfo,
}

public:
BranchProtectionInfo() = default;
BranchProtectionInfo()
: SignReturnAddr(LangOptions::SignReturnAddressScopeKind::None),
SignKey(LangOptions::SignReturnAddressKeyKind::AKey),
BranchTargetEnforcement(false), BranchProtectionPAuthLR(false),
GuardedControlStack(false) {}

BranchProtectionInfo(const LangOptions &LangOpts) {
SignReturnAddr =
LangOpts.hasSignReturnAddress()
Expand Down
6 changes: 5 additions & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1618,6 +1618,7 @@ def shared_libsan : Flag<["-"], "shared-libsan">,
def static_libsan : Flag<["-"], "static-libsan">,
HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">;
def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;
def : Flag<["-"], "static-libasan">, Alias<static_libsan>;
def fasm : Flag<["-"], "fasm">, Group<f_Group>;

defm assume_unique_vtables : BoolFOption<"assume-unique-vtables",
Expand Down Expand Up @@ -4928,6 +4929,9 @@ foreach i = {1-31} in
def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group<m_Group>,
HelpText<"Reserve the x"#i#" register (AArch64/RISC-V only)">;

def mlr_for_calls_only : Flag<["-"], "mlr-for-calls-only">, Group<m_aarch64_Features_Group>,
HelpText<"Do not allocate the LR register for general purpose usage, only for calls. (AArch64 only)">;

foreach i = {8-15,18} in
def fcall_saved_x#i : Flag<["-"], "fcall-saved-x"#i>, Group<m_aarch64_Features_Group>,
HelpText<"Make the x"#i#" register call-saved (AArch64 only)">;
Expand Down Expand Up @@ -5730,7 +5734,7 @@ def print_supported_extensions : Flag<["-", "--"], "print-supported-extensions">
def print_enabled_extensions : Flag<["-", "--"], "print-enabled-extensions">,
Visibility<[ClangOption, CC1Option, CLOption]>,
HelpText<"Print the extensions enabled by the given target and -march/-mcpu options."
" (AArch64 only)">,
" (AArch64 and RISC-V only)">,
MarshallingInfoFlag<FrontendOpts<"PrintEnabledExtensions">>;
def : Flag<["-"], "mcpu=help">, Alias<print_supported_cpus>;
def : Flag<["-"], "mtune=help">, Alias<print_supported_cpus>;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/aarch64-mlr-for-calls-only.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// RUN: %clang --target=aarch64-none-gnu -mlr-for-calls-only -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK < %t %s
// CHECK: "-target-feature" "+reserve-lr-for-ra"
12 changes: 8 additions & 4 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,7 @@ def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,

let ParentPackage = Taint in {

def GenericTaintChecker : Checker<"TaintPropagation">,
def TaintPropagationChecker : Checker<"TaintPropagation">, // Modelling checker
HelpText<"Generate taint information used by other checkers">,
CheckerOptions<[
CmdLineOption<String,
Expand All @@ -1080,6 +1080,12 @@ def GenericTaintChecker : Checker<"TaintPropagation">,
"",
InAlpha>,
]>,
Documentation<NotDocumented>,
Hidden;

def GenericTaintChecker : Checker<"GenericTaint">,
HelpText<"Reports potential injection vulnerabilities">,
Dependencies<[TaintPropagationChecker]>,
Documentation<HasDocumentation>;

} // end "alpha.security.taint"
Expand Down Expand Up @@ -1717,9 +1723,7 @@ let ParentPackage = TaintOptIn in {
def TaintedAllocChecker: Checker<"TaintedAlloc">,
HelpText<"Check for memory allocations, where the size parameter "
"might be a tainted (attacker controlled) value.">,
Dependencies<[DynamicMemoryModeling]>,
//FIXME: GenericTaintChecker should be a dependency, but only after it
//is transformed into a modeling checker
Dependencies<[DynamicMemoryModeling, TaintPropagationChecker]>,
Documentation<HasDocumentation>;

} // end "optin.taint"
Expand Down
20 changes: 10 additions & 10 deletions clang/lib/APINotes/APINotesFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,26 +132,26 @@ using IdentifierDataLayout = llvm::BCRecordLayout<
>;
} // namespace identifier_block

namespace objc_context_block {
namespace context_block {
enum {
OBJC_CONTEXT_ID_DATA = 1,
OBJC_CONTEXT_INFO_DATA = 2,
CONTEXT_ID_DATA = 1,
CONTEXT_INFO_DATA = 2,
};

using ObjCContextIDLayout =
llvm::BCRecordLayout<OBJC_CONTEXT_ID_DATA, // record ID
using ContextIDLayout =
llvm::BCRecordLayout<CONTEXT_ID_DATA, // record ID
llvm::BCVBR<16>, // table offset within the blob (see
// below)
llvm::BCBlob // map from ObjC class names/protocol (as
// IDs) to context IDs
>;

using ObjCContextInfoLayout = llvm::BCRecordLayout<
OBJC_CONTEXT_INFO_DATA, // record ID
llvm::BCVBR<16>, // table offset within the blob (see below)
llvm::BCBlob // map from ObjC context IDs to context information.
using ContextInfoLayout = llvm::BCRecordLayout<
CONTEXT_INFO_DATA, // record ID
llvm::BCVBR<16>, // table offset within the blob (see below)
llvm::BCBlob // map from ObjC context IDs to context information.
>;
} // namespace objc_context_block
} // namespace context_block

namespace objc_property_block {
enum {
Expand Down
93 changes: 46 additions & 47 deletions clang/lib/APINotes/APINotesReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,9 @@ class IdentifierTableInfo {
}
};

/// Used to deserialize the on-disk Objective-C class table.
class ObjCContextIDTableInfo {
/// Used to deserialize the on-disk table of Objective-C classes and C++
/// namespaces.
class ContextIDTableInfo {
public:
using internal_key_type = ContextTableKey;
using external_key_type = internal_key_type;
Expand Down Expand Up @@ -221,9 +222,8 @@ class ObjCContextIDTableInfo {
};

/// Used to deserialize the on-disk Objective-C property table.
class ObjCContextInfoTableInfo
: public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
ObjCContextInfo> {
class ContextInfoTableInfo
: public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
public:
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
return endian::readNext<uint32_t, llvm::endianness::little>(Data);
Expand All @@ -233,9 +233,9 @@ class ObjCContextInfoTableInfo
return static_cast<size_t>(llvm::hash_value(Key));
}

static ObjCContextInfo readUnversioned(internal_key_type Key,
const uint8_t *&Data) {
ObjCContextInfo Info;
static ContextInfo readUnversioned(internal_key_type Key,
const uint8_t *&Data) {
ContextInfo Info;
ReadCommonTypeInfo(Data, Info);
uint8_t Payload = *Data++;

Expand Down Expand Up @@ -614,17 +614,17 @@ class APINotesReader::Implementation {
/// The identifier table.
std::unique_ptr<SerializedIdentifierTable> IdentifierTable;

using SerializedObjCContextIDTable =
llvm::OnDiskIterableChainedHashTable<ObjCContextIDTableInfo>;
using SerializedContextIDTable =
llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;

/// The Objective-C context ID table.
std::unique_ptr<SerializedObjCContextIDTable> ObjCContextIDTable;
/// The Objective-C / C++ context ID table.
std::unique_ptr<SerializedContextIDTable> ContextIDTable;

using SerializedObjCContextInfoTable =
llvm::OnDiskIterableChainedHashTable<ObjCContextInfoTableInfo>;
using SerializedContextInfoTable =
llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;

/// The Objective-C context info table.
std::unique_ptr<SerializedObjCContextInfoTable> ObjCContextInfoTable;
std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;

using SerializedObjCPropertyTable =
llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
Expand Down Expand Up @@ -685,8 +685,8 @@ class APINotesReader::Implementation {
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCContextBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readContextBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
Expand Down Expand Up @@ -906,7 +906,7 @@ bool APINotesReader::Implementation::readIdentifierBlock(
return false;
}

bool APINotesReader::Implementation::readObjCContextBlock(
bool APINotesReader::Implementation::readContextBlock(
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
return true;
Expand Down Expand Up @@ -950,31 +950,30 @@ bool APINotesReader::Implementation::readObjCContextBlock(
}
unsigned Kind = MaybeKind.get();
switch (Kind) {
case objc_context_block::OBJC_CONTEXT_ID_DATA: {
// Already saw Objective-C context ID table.
if (ObjCContextIDTable)
case context_block::CONTEXT_ID_DATA: {
// Already saw Objective-C / C++ context ID table.
if (ContextIDTable)
return true;

uint32_t tableOffset;
objc_context_block::ObjCContextIDLayout::readRecord(Scratch, tableOffset);
context_block::ContextIDLayout::readRecord(Scratch, tableOffset);
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

ObjCContextIDTable.reset(SerializedObjCContextIDTable::Create(
ContextIDTable.reset(SerializedContextIDTable::Create(
base + tableOffset, base + sizeof(uint32_t), base));
break;
}

case objc_context_block::OBJC_CONTEXT_INFO_DATA: {
// Already saw Objective-C context info table.
if (ObjCContextInfoTable)
case context_block::CONTEXT_INFO_DATA: {
// Already saw Objective-C / C++ context info table.
if (ContextInfoTable)
return true;

uint32_t tableOffset;
objc_context_block::ObjCContextInfoLayout::readRecord(Scratch,
tableOffset);
context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

ObjCContextInfoTable.reset(SerializedObjCContextInfoTable::Create(
ContextInfoTable.reset(SerializedContextInfoTable::Create(
base + tableOffset, base + sizeof(uint32_t), base));
break;
}
Expand Down Expand Up @@ -1678,7 +1677,7 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,

case OBJC_CONTEXT_BLOCK_ID:
if (!HasValidControlBlock ||
Implementation->readObjCContextBlock(Cursor, Scratch)) {
Implementation->readContextBlock(Cursor, Scratch)) {
Failed = true;
return;
}
Expand Down Expand Up @@ -1815,7 +1814,7 @@ APINotesReader::VersionedInfo<T>::VersionedInfo(

auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
Expand All @@ -1824,33 +1823,33 @@ auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)

// ObjC classes can't be declared in C++ namespaces, so use -1 as the global
// context.
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
}

auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
-> VersionedInfo<ObjCContextInfo> {
if (!Implementation->ObjCContextInfoTable)
-> VersionedInfo<ContextInfo> {
if (!Implementation->ContextInfoTable)
return std::nullopt;

std::optional<ContextID> CtxID = lookupObjCClassID(Name);
if (!CtxID)
return std::nullopt;

auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ObjCContextInfoTable->end())
auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ContextInfoTable->end())
return std::nullopt;

return {Implementation->SwiftVersion, *KnownInfo};
}

auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
Expand All @@ -1859,25 +1858,25 @@ auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)

// ObjC classes can't be declared in C++ namespaces, so use -1 as the global
// context.
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
}

auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)
-> VersionedInfo<ObjCContextInfo> {
if (!Implementation->ObjCContextInfoTable)
-> VersionedInfo<ContextInfo> {
if (!Implementation->ContextInfoTable)
return std::nullopt;

std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
if (!CtxID)
return std::nullopt;

auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ObjCContextInfoTable->end())
auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ContextInfoTable->end())
return std::nullopt;

return {Implementation->SwiftVersion, *KnownInfo};
Expand Down Expand Up @@ -2014,7 +2013,7 @@ auto APINotesReader::lookupTypedef(llvm::StringRef Name,
auto APINotesReader::lookupNamespaceID(
llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
Expand All @@ -2023,9 +2022,9 @@ auto APINotesReader::lookupNamespaceID(

uint32_t RawParentNamespaceID =
ParentNamespaceID ? ParentNamespaceID->Value : -1;
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
{RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/APINotes/APINotesTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ LLVM_DUMP_METHOD void CommonTypeInfo::dump(llvm::raw_ostream &OS) const {
OS << '\n';
}

LLVM_DUMP_METHOD void ObjCContextInfo::dump(llvm::raw_ostream &OS) {
LLVM_DUMP_METHOD void ContextInfo::dump(llvm::raw_ostream &OS) {
static_cast<CommonTypeInfo &>(*this).dump(OS);
if (HasDefaultNullability)
OS << "DefaultNullability: " << DefaultNullability << ' ';
Expand Down
71 changes: 35 additions & 36 deletions clang/lib/APINotes/APINotesWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ class APINotesWriter::Implementation {
/// this context and provides both the context ID and information describing
/// the context within that module.
llvm::DenseMap<ContextTableKey,
std::pair<unsigned, VersionedSmallVector<ObjCContextInfo>>>
ObjCContexts;
std::pair<unsigned, VersionedSmallVector<ContextInfo>>>
Contexts;

/// Information about parent contexts for each context.
///
/// Indexed by context ID, provides the parent context ID.
llvm::DenseMap<uint32_t, uint32_t> ParentContexts;

/// Mapping from context IDs to the identifier ID holding the name.
llvm::DenseMap<unsigned, unsigned> ObjCContextNames;
llvm::DenseMap<unsigned, unsigned> ContextNames;

/// Information about Objective-C properties.
///
Expand Down Expand Up @@ -147,7 +147,7 @@ class APINotesWriter::Implementation {
void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
void writeControlBlock(llvm::BitstreamWriter &Stream);
void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
void writeObjCContextBlock(llvm::BitstreamWriter &Stream);
void writeContextBlock(llvm::BitstreamWriter &Stream);
void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
Expand Down Expand Up @@ -178,7 +178,7 @@ void APINotesWriter::Implementation::writeToStream(llvm::raw_ostream &OS) {
writeBlockInfoBlock(Stream);
writeControlBlock(Stream);
writeIdentifierBlock(Stream);
writeObjCContextBlock(Stream);
writeContextBlock(Stream);
writeObjCPropertyBlock(Stream);
writeObjCMethodBlock(Stream);
writeObjCSelectorBlock(Stream);
Expand Down Expand Up @@ -240,7 +240,7 @@ void APINotesWriter::Implementation::writeBlockInfoBlock(
BLOCK_RECORD(identifier_block, IDENTIFIER_DATA);

BLOCK(OBJC_CONTEXT_BLOCK);
BLOCK_RECORD(objc_context_block, OBJC_CONTEXT_ID_DATA);
BLOCK_RECORD(context_block, CONTEXT_ID_DATA);

BLOCK(OBJC_PROPERTY_BLOCK);
BLOCK_RECORD(objc_property_block, OBJC_PROPERTY_DATA);
Expand Down Expand Up @@ -337,7 +337,7 @@ void APINotesWriter::Implementation::writeIdentifierBlock(

namespace {
/// Used to serialize the on-disk Objective-C context table.
class ObjCContextIDTableInfo {
class ContextIDTableInfo {
public:
using key_type = ContextTableKey;
using key_type_ref = key_type;
Expand Down Expand Up @@ -552,9 +552,8 @@ void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
}

/// Used to serialize the on-disk Objective-C property table.
class ObjCContextInfoTableInfo
: public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
ObjCContextInfo> {
class ContextInfoTableInfo
: public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
public:
unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }

Expand All @@ -567,11 +566,11 @@ class ObjCContextInfoTableInfo
return static_cast<size_t>(llvm::hash_value(Key));
}

unsigned getUnversionedInfoSize(const ObjCContextInfo &OCI) {
unsigned getUnversionedInfoSize(const ContextInfo &OCI) {
return getCommonTypeInfoSize(OCI) + 1;
}

void emitUnversionedInfo(raw_ostream &OS, const ObjCContextInfo &OCI) {
void emitUnversionedInfo(raw_ostream &OS, const ContextInfo &OCI) {
emitCommonTypeInfo(OS, OCI);

uint8_t payload = 0;
Expand All @@ -590,19 +589,19 @@ class ObjCContextInfoTableInfo
};
} // namespace

void APINotesWriter::Implementation::writeObjCContextBlock(
void APINotesWriter::Implementation::writeContextBlock(
llvm::BitstreamWriter &Stream) {
llvm::BCBlockRAII restoreBlock(Stream, OBJC_CONTEXT_BLOCK_ID, 3);

if (ObjCContexts.empty())
if (Contexts.empty())
return;

{
llvm::SmallString<4096> HashTableBlob;
uint32_t Offset;
{
llvm::OnDiskChainedHashTableGenerator<ObjCContextIDTableInfo> Generator;
for (auto &OC : ObjCContexts)
llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo> Generator;
for (auto &OC : Contexts)
Generator.insert(OC.first, OC.second.first);

llvm::raw_svector_ostream BlobStream(HashTableBlob);
Expand All @@ -612,16 +611,16 @@ void APINotesWriter::Implementation::writeObjCContextBlock(
Offset = Generator.Emit(BlobStream);
}

objc_context_block::ObjCContextIDLayout ObjCContextID(Stream);
ObjCContextID.emit(Scratch, Offset, HashTableBlob);
context_block::ContextIDLayout ContextID(Stream);
ContextID.emit(Scratch, Offset, HashTableBlob);
}

{
llvm::SmallString<4096> HashTableBlob;
uint32_t Offset;
{
llvm::OnDiskChainedHashTableGenerator<ObjCContextInfoTableInfo> Generator;
for (auto &OC : ObjCContexts)
llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo> Generator;
for (auto &OC : Contexts)
Generator.insert(OC.second.first, OC.second.second);

llvm::raw_svector_ostream BlobStream(HashTableBlob);
Expand All @@ -631,8 +630,8 @@ void APINotesWriter::Implementation::writeObjCContextBlock(
Offset = Generator.Emit(BlobStream);
}

objc_context_block::ObjCContextInfoLayout ObjCContextInfo(Stream);
ObjCContextInfo.emit(Scratch, Offset, HashTableBlob);
context_block::ContextInfoLayout ContextInfo(Stream);
ContextInfo.emit(Scratch, Offset, HashTableBlob);
}
}

Expand Down Expand Up @@ -1263,25 +1262,25 @@ void APINotesWriter::writeToStream(llvm::raw_ostream &OS) {
Implementation->writeToStream(OS);
}

ContextID APINotesWriter::addObjCContext(std::optional<ContextID> ParentCtxID,
StringRef Name, ContextKind Kind,
const ObjCContextInfo &Info,
VersionTuple SwiftVersion) {
ContextID APINotesWriter::addContext(std::optional<ContextID> ParentCtxID,
llvm::StringRef Name, ContextKind Kind,
const ContextInfo &Info,
llvm::VersionTuple SwiftVersion) {
IdentifierID NameID = Implementation->getIdentifier(Name);

uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
ContextTableKey Key(RawParentCtxID, static_cast<uint8_t>(Kind), NameID);
auto Known = Implementation->ObjCContexts.find(Key);
if (Known == Implementation->ObjCContexts.end()) {
unsigned NextID = Implementation->ObjCContexts.size() + 1;
auto Known = Implementation->Contexts.find(Key);
if (Known == Implementation->Contexts.end()) {
unsigned NextID = Implementation->Contexts.size() + 1;

Implementation::VersionedSmallVector<ObjCContextInfo> EmptyVersionedInfo;
Known = Implementation->ObjCContexts
Implementation::VersionedSmallVector<ContextInfo> EmptyVersionedInfo;
Known = Implementation->Contexts
.insert(std::make_pair(
Key, std::make_pair(NextID, EmptyVersionedInfo)))
.first;

Implementation->ObjCContextNames[NextID] = NameID;
Implementation->ContextNames[NextID] = NameID;
Implementation->ParentContexts[NextID] = RawParentCtxID;
}

Expand Down Expand Up @@ -1328,9 +1327,9 @@ void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
uint32_t ParentCtxID = Implementation->ParentContexts[CtxID.Value];
ContextTableKey CtxKey(ParentCtxID,
static_cast<uint8_t>(ContextKind::ObjCClass),
Implementation->ObjCContextNames[CtxID.Value]);
assert(Implementation->ObjCContexts.contains(CtxKey));
auto &VersionedVec = Implementation->ObjCContexts[CtxKey].second;
Implementation->ContextNames[CtxID.Value]);
assert(Implementation->Contexts.contains(CtxKey));
auto &VersionedVec = Implementation->Contexts[CtxKey].second;
bool Found = false;
for (auto &Versioned : VersionedVec) {
if (Versioned.first == SwiftVersion) {
Expand All @@ -1341,7 +1340,7 @@ void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
}

if (!Found) {
VersionedVec.push_back({SwiftVersion, ObjCContextInfo()});
VersionedVec.push_back({SwiftVersion, ContextInfo()});
VersionedVec.back().second.setHasDesignatedInits(true);
}
}
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/APINotes/APINotesYAMLCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ class YAMLConverter {
void convertContext(std::optional<ContextID> ParentContextID, const Class &C,
ContextKind Kind, VersionTuple SwiftVersion) {
// Write the class.
ObjCContextInfo CI;
ContextInfo CI;
convertCommonType(C, CI, C.Name);

if (C.AuditedForNullability)
Expand All @@ -797,7 +797,7 @@ class YAMLConverter {
CI.setSwiftObjCMembers(*C.SwiftObjCMembers);

ContextID CtxID =
Writer.addObjCContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);
Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);

// Write all methods.
llvm::StringMap<std::pair<bool, bool>> KnownMethods;
Expand Down Expand Up @@ -863,12 +863,12 @@ class YAMLConverter {
const Namespace &TheNamespace,
VersionTuple SwiftVersion) {
// Write the namespace.
ObjCContextInfo CI;
ContextInfo CI;
convertCommonEntity(TheNamespace, CI, TheNamespace.Name);

ContextID CtxID =
Writer.addObjCContext(ParentContextID, TheNamespace.Name,
ContextKind::Namespace, CI, SwiftVersion);
Writer.addContext(ParentContextID, TheNamespace.Name,
ContextKind::Namespace, CI, SwiftVersion);

convertTopLevelItems(Context(CtxID, ContextKind::Namespace),
TheNamespace.Items, SwiftVersion);
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/NVPTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

bool useFP16ConversionIntrinsics() const override { return false; }

bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1952,7 +1952,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
Builder.CreateLoad(StateItemsPtr, "stateitems");

// Fetch the value at the current index from the buffer.
llvm::Value *CurrentItemPtr = Builder.CreateGEP(
llvm::Value *CurrentItemPtr = Builder.CreateInBoundsGEP(
ObjCIdType, EnumStateItems, index, "currentitem.ptr");
llvm::Value *CurrentItem =
Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign());
Expand Down Expand Up @@ -2028,7 +2028,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){

// First we check in the local buffer.
llvm::Value *indexPlusOne =
Builder.CreateAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));
Builder.CreateNUWAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));

// If we haven't overrun the buffer yet, we can continue.
// Set the branch weights based on the simplifying assumption that this is
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
ParsedTargetAttr Attr =
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
if (!Attr.BranchProtection.empty()) {
TargetInfo::BranchProtectionInfo BPI;
TargetInfo::BranchProtectionInfo BPI{};
StringRef DiagMsg;
StringRef Arch =
Attr.CPU.empty() ? CGM.getTarget().getTargetOpts().CPU : Attr.CPU;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4367,6 +4367,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
return;
}
if (Opt == options::OPT_print_enabled_extensions &&
!C.getDefaultToolChain().getTriple().isRISCV() &&
!C.getDefaultToolChain().getTriple().isAArch64()) {
C.getDriver().Diag(diag::err_opt_not_valid_on_target)
<< "--print-enabled-extensions";
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ bool SanitizerArgs::needsFuzzerInterceptors() const {

bool SanitizerArgs::needsUbsanRt() const {
// All of these include ubsan.
if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
if (needsAsanRt() || needsMsanRt() || needsNsanRt() || needsHwasanRt() ||
needsTsanRt() || needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
(needsScudoRt() && !requiresMinimalRuntime()))
return false;

Expand Down
20 changes: 12 additions & 8 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,13 @@ static void getAArch64MultilibFlags(const Driver &D,
UnifiedFeatures.end());
std::vector<std::string> MArch;
for (const auto &Ext : AArch64::Extensions)
if (FeatureSet.contains(Ext.PosTargetFeature))
MArch.push_back(Ext.UserVisibleName.str());
if (!Ext.UserVisibleName.empty())
if (FeatureSet.contains(Ext.PosTargetFeature))
MArch.push_back(Ext.UserVisibleName.str());
for (const auto &Ext : AArch64::Extensions)
if (FeatureSet.contains(Ext.NegTargetFeature))
MArch.push_back(("no" + Ext.UserVisibleName).str());
if (!Ext.UserVisibleName.empty())
if (FeatureSet.contains(Ext.NegTargetFeature))
MArch.push_back(("no" + Ext.UserVisibleName).str());
StringRef ArchName;
for (const auto &ArchInfo : AArch64::ArchInfos)
if (FeatureSet.contains(ArchInfo->ArchFeature))
Expand All @@ -221,11 +223,13 @@ static void getARMMultilibFlags(const Driver &D,
UnifiedFeatures.end());
std::vector<std::string> MArch;
for (const auto &Ext : ARM::ARCHExtNames)
if (FeatureSet.contains(Ext.Feature))
MArch.push_back(Ext.Name.str());
if (!Ext.Name.empty())
if (FeatureSet.contains(Ext.Feature))
MArch.push_back(Ext.Name.str());
for (const auto &Ext : ARM::ARCHExtNames)
if (FeatureSet.contains(Ext.NegFeature))
MArch.push_back(("no" + Ext.Name).str());
if (!Ext.Name.empty())
if (FeatureSet.contains(Ext.NegFeature))
MArch.push_back(("no" + Ext.Name).str());
MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
Result.push_back(llvm::join(MArch, "+"));

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
if (Args.hasArg(options::OPT_ffixed_x28))
Features.push_back("+reserve-x28");

if (Args.hasArg(options::OPT_mlr_for_calls_only))
Features.push_back("+reserve-lr-for-ra");

if (Args.hasArg(options::OPT_fcall_saved_x8))
Features.push_back("+call-saved-x8");

Expand Down
8 changes: 3 additions & 5 deletions clang/lib/Driver/ToolChains/Arch/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,11 +591,9 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,

// Add CPU features for generic CPUs
if (CPUName == "native") {
llvm::StringMap<bool> HostFeatures;
if (llvm::sys::getHostCPUFeatures(HostFeatures))
for (auto &F : HostFeatures)
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
for (auto &F : llvm::sys::getHostCPUFeatures())
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
} else if (!CPUName.empty()) {
// This sets the default features for the specified CPU. We certainly don't
// want to override the features that have been explicitly specified on the
Expand Down
8 changes: 3 additions & 5 deletions clang/lib/Driver/ToolChains/Arch/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,9 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
// If -march=native, autodetect the feature list.
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
if (StringRef(A->getValue()) == "native") {
llvm::StringMap<bool> HostFeatures;
if (llvm::sys::getHostCPUFeatures(HostFeatures))
for (auto &F : HostFeatures)
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
for (auto &F : llvm::sys::getHostCPUFeatures())
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
}
}

Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
HelperStaticRuntimes.push_back("memprof-preinit");
}
if (SanArgs.needsNsanRt())
SharedRuntimes.push_back("nsan");
if (SanArgs.needsUbsanRt()) {
if (SanArgs.requiresMinimalRuntime())
SharedRuntimes.push_back("ubsan_minimal");
Expand Down Expand Up @@ -1479,7 +1481,7 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("msan_cxx");
}
if (SanArgs.needsNsanRt())
if (!SanArgs.needsSharedRt() && SanArgs.needsNsanRt())
StaticRuntimes.push_back("nsan");
if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt()) {
StaticRuntimes.push_back("tsan");
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/HLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {
static std::optional<std::string> parseTargetProfile(StringRef TargetProfile);
bool requiresValidation(llvm::opt::DerivedArgList &Args) const;

// Set default DWARF version to 4 for DXIL uses version 4.
unsigned GetDefaultDwarfVersion() const override { return 4; }

private:
mutable std::unique_ptr<tools::hlsl::Validator> Validator;
};
Expand Down
11 changes: 9 additions & 2 deletions clang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,9 +841,16 @@ static StringRef ModuleKindName(Module::ModuleKind MK) {
}

void DumpModuleInfoAction::ExecuteAction() {
assert(isCurrentFileAST() && "dumping non-AST?");
// Set up the output file.
CompilerInstance &CI = getCompilerInstance();

// Don't process files of type other than module to avoid crash
if (!isCurrentFileAST()) {
CI.getDiagnostics().Report(diag::err_file_is_not_module)
<< getCurrentFile();
return;
}

// Set up the output file.
StringRef OutputFileName = CI.getFrontendOpts().OutputFile;
if (!OutputFileName.empty() && OutputFileName != "-") {
std::error_code EC;
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ static T PickFP(const llvm::fltSemantics *Sem, T IEEEHalfVal, T IEEESingleVal,

static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
const llvm::fltSemantics *Sem, StringRef Ext) {
const char *DenormMin, *Epsilon, *Max, *Min;
const char *DenormMin, *NormMax, *Epsilon, *Max, *Min;
NormMax = PickFP(Sem, "6.5504e+4", "3.40282347e+38",
"1.7976931348623157e+308", "1.18973149535723176502e+4932",
"8.98846567431157953864652595394501e+307",
"1.18973149535723176508575932662800702e+4932");
DenormMin = PickFP(Sem, "5.9604644775390625e-8", "1.40129846e-45",
"4.9406564584124654e-324", "3.64519953188247460253e-4951",
"4.94065645841246544176568792868221e-324",
Expand Down Expand Up @@ -144,6 +148,7 @@ static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
DefPrefix += "_";

Builder.defineMacro(DefPrefix + "DENORM_MIN__", Twine(DenormMin)+Ext);
Builder.defineMacro(DefPrefix + "NORM_MAX__", Twine(NormMax)+Ext);
Builder.defineMacro(DefPrefix + "HAS_DENORM__");
Builder.defineMacro(DefPrefix + "DIG__", Twine(Digits));
Builder.defineMacro(DefPrefix + "DECIMAL_DIG__", Twine(DecimalDigits));
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Headers/float.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@
# undef DBL_HAS_SUBNORM
# undef LDBL_HAS_SUBNORM
# endif
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
!defined(__STRICT_ANSI__)
# undef FLT_NORM_MAX
# undef DBL_NORM_MAX
# undef LDBL_NORM_MAX
#endif
#endif

#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
Expand Down Expand Up @@ -166,6 +172,10 @@
/* C23 5.2.5.3.3p29-30 */
# define INFINITY (__builtin_inff())
# define NAN (__builtin_nanf(""))
/* C23 5.2.5.3.3p32 */
# define FLT_NORM_MAX __FLT_NORM_MAX__
# define DBL_NORM_MAX __DBL_NORM_MAX__
# define LDBL_NORM_MAX __LDBL_NORM_MAX__
#endif

#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/InstallAPI/DylibVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,18 @@ bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx,

bool DylibVerifier::shouldIgnoreReexport(const Record *R,
SymbolContext &SymCtx) const {
StringRef SymName = SymCtx.SymbolName;
// Linker directive symbols can never be ignored.
if (SymName.starts_with("$ld$"))
return false;

if (Reexports.empty())
return false;

for (const InterfaceFile &Lib : Reexports) {
if (!Lib.hasTarget(Ctx.Target))
continue;
if (auto Sym =
Lib.getSymbol(SymCtx.Kind, SymCtx.SymbolName, SymCtx.ObjCIFKind))
if (auto Sym = Lib.getSymbol(SymCtx.Kind, SymName, SymCtx.ObjCIFKind))
if ((*Sym)->hasTarget(Ctx.Target))
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaAPINotes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ static void ProcessAPINotes(Sema &S, TypedefNameDecl *D,

/// Process API notes for an Objective-C class or protocol.
static void ProcessAPINotes(Sema &S, ObjCContainerDecl *D,
const api_notes::ObjCContextInfo &Info,
const api_notes::ContextInfo &Info,
VersionedInfoMetadata Metadata) {
// Handle common type information.
ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
Expand All @@ -683,7 +683,7 @@ static void ProcessAPINotes(Sema &S, ObjCContainerDecl *D,

/// Process API notes for an Objective-C class.
static void ProcessAPINotes(Sema &S, ObjCInterfaceDecl *D,
const api_notes::ObjCContextInfo &Info,
const api_notes::ContextInfo &Info,
VersionedInfoMetadata Metadata) {
if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {
handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,10 @@ void SemaARM::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
return;
}

const TargetInfo &TI = getASTContext().getTargetInfo();
if (TI.hasFeature("vfp"))
Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);

D->addAttr(::new (getASTContext())
ARMInterruptAttr(getASTContext(), AL, Kind));
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13313,7 +13313,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
!VDecl->isInvalidDecl() && VDecl->isThisDeclarationADefinition() &&
VDecl->getFormalLinkage() == Linkage::External && !VDecl->isInline() &&
!VDecl->isTemplated() && !isa<VarTemplateSpecializationDecl>(VDecl)) {
!VDecl->isTemplated() && !isa<VarTemplateSpecializationDecl>(VDecl) &&
!VDecl->getInstantiatedFromStaticDataMember()) {
Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit);
VDecl->setInvalidDecl();
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2991,7 +2991,7 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
<< Unsupported << None << CurFeature << Target;
}

TargetInfo::BranchProtectionInfo BPI;
TargetInfo::BranchProtectionInfo BPI{};
StringRef DiagMsg;
if (ParsedAttrs.BranchProtection.empty())
return false;
Expand Down
26 changes: 10 additions & 16 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6625,27 +6625,21 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);

// Functions with 'interrupt' attribute cannot be called directly.
if (FDecl && FDecl->hasAttr<AnyX86InterruptAttr>()) {
Diag(Fn->getExprLoc(), diag::err_anyx86_interrupt_called);
return ExprError();
if (FDecl) {
if (FDecl->hasAttr<AnyX86InterruptAttr>()) {
Diag(Fn->getExprLoc(), diag::err_anyx86_interrupt_called);
return ExprError();
}
if (FDecl->hasAttr<ARMInterruptAttr>()) {
Diag(Fn->getExprLoc(), diag::err_arm_interrupt_called);
return ExprError();
}
}

// Interrupt handlers don't save off the VFP regs automatically on ARM,
// so there's some risk when calling out to non-interrupt handler functions
// that the callee might not preserve them. This is easy to diagnose here,
// but can be very challenging to debug.
// Likewise, X86 interrupt handlers may only call routines with attribute
// X86 interrupt handlers may only call routines with attribute
// no_caller_saved_registers since there is no efficient way to
// save and restore the non-GPR state.
if (auto *Caller = getCurFunctionDecl()) {
if (Caller->hasAttr<ARMInterruptAttr>()) {
bool VFP = Context.getTargetInfo().hasFeature("vfp");
if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>())) {
Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention);
if (FDecl)
Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl;
}
}
if (Caller->hasAttr<AnyX86InterruptAttr>() ||
Caller->hasAttr<AnyX86NoCallerSavedRegistersAttr>()) {
const TargetInfo &TI = Context.getTargetInfo();
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5576,6 +5576,10 @@ static void TryOrBuildParenListInitialization(
ExprResult ER;
ER = IS.Perform(S, SubEntity, SubKind,
Arg ? MultiExprArg(Arg) : std::nullopt);

if (ER.isInvalid())
return false;

if (InitExpr)
*InitExpr = ER.get();
else
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3420,6 +3420,10 @@ Decl *TemplateDeclInstantiator::VisitUsingEnumDecl(UsingEnumDecl *D) {

TypeSourceInfo *TSI = SemaRef.SubstType(D->getEnumType(), TemplateArgs,
D->getLocation(), D->getDeclName());

if (!TSI)
return nullptr;

UsingEnumDecl *NewUD =
UsingEnumDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(),
D->getEnumLoc(), D->getLocation(), TSI);
Expand Down
28 changes: 22 additions & 6 deletions clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/YAMLTraits.h"

#include <limits>
Expand Down Expand Up @@ -391,9 +392,10 @@ class GenericTaintChecker : public Checker<check::PreCall, check::PostCall> {
bool generateReportIfTainted(const Expr *E, StringRef Msg,
CheckerContext &C) const;

private:
const BugType BT{this, "Use of Untrusted Data", categories::TaintedData};
bool isTaintReporterCheckerEnabled = false;
std::optional<BugType> BT;

private:
bool checkUncontrolledFormatString(const CallEvent &Call,
CheckerContext &C) const;

Expand Down Expand Up @@ -1033,20 +1035,23 @@ bool GenericTaintRule::UntrustedEnv(CheckerContext &C) {
bool GenericTaintChecker::generateReportIfTainted(const Expr *E, StringRef Msg,
CheckerContext &C) const {
assert(E);
if (!isTaintReporterCheckerEnabled)
return false;
std::optional<SVal> TaintedSVal =
getTaintedPointeeOrPointer(C.getState(), C.getSVal(E));

if (!TaintedSVal)
return false;

// Generate diagnostic.
if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
auto report = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
assert(BT);
static CheckerProgramPointTag Tag(BT->getCheckerName(), Msg);
if (ExplodedNode *N = C.generateNonFatalErrorNode(C.getState(), &Tag)) {
auto report = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
report->addRange(E->getSourceRange());
for (auto TaintedSym : getTaintedSymbols(C.getState(), *TaintedSVal)) {
report->markInteresting(TaintedSym);
}

C.emitReport(std::move(report));
return true;
}
Expand Down Expand Up @@ -1122,10 +1127,21 @@ void GenericTaintChecker::taintUnsafeSocketProtocol(const CallEvent &Call,
}

/// Checker registration
void ento::registerGenericTaintChecker(CheckerManager &Mgr) {
void ento::registerTaintPropagationChecker(CheckerManager &Mgr) {
Mgr.registerChecker<GenericTaintChecker>();
}

bool ento::shouldRegisterTaintPropagationChecker(const CheckerManager &mgr) {
return true;
}

void ento::registerGenericTaintChecker(CheckerManager &Mgr) {
GenericTaintChecker *checker = Mgr.getChecker<GenericTaintChecker>();
checker->isTaintReporterCheckerEnabled = true;
checker->BT.emplace(Mgr.getCurrentCheckerName(), "Use of Untrusted Data",
categories::TaintedData);
}

bool ento::shouldRegisterGenericTaintChecker(const CheckerManager &mgr) {
return true;
}
10 changes: 8 additions & 2 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2057,11 +2057,17 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
break;

case Stmt::GCCAsmStmtClass:
case Stmt::GCCAsmStmtClass: {
Bldr.takeNodes(Pred);
VisitGCCAsmStmt(cast<GCCAsmStmt>(S), Pred, Dst);
ExplodedNodeSet PreVisit;
getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
ExplodedNodeSet PostVisit;
for (ExplodedNode *const N : PreVisit)
VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);
getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
Bldr.addNodes(Dst);
break;
}

case Stmt::MSAsmStmtClass:
Bldr.takeNodes(Pred);
Expand Down
10 changes: 10 additions & 0 deletions clang/test/CXX/module/module.import/p6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,13 @@ void* tmpl_fn_ok
inline int foo (int a) {
return tmpl_OK (a);
}

template <typename T> struct S2 { static int v; };
template <typename T> int S2<T>::v = 10;

template <typename T> bool b() {
bool b1 = S2<T>::v == 10;
return b1 && true;
}

inline bool B = b<int>();
119 changes: 0 additions & 119 deletions clang/test/CodeGen/builtins-nvptx-native-half-type-err.c

This file was deleted.

117 changes: 117 additions & 0 deletions clang/test/CodeGen/builtins-nvptx-native-half-type-native.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// REQUIRES: nvptx-registered-target
//
// RUN: %clang_cc1 -ffp-contract=off -triple nvptx-unknown-unknown -target-cpu \
// RUN: sm_86 -target-feature +ptx72 -fcuda-is-device -x cuda -emit-llvm -o - %s \
// RUN: | FileCheck %s

#define __device__ __attribute__((device))
typedef __fp16 __fp16v2 __attribute__((ext_vector_type(2)));

// CHECK: call half @llvm.nvvm.ex2.approx.f16(half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.ex2.approx.f16x2(<2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.relu.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.ftz.relu.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.relu.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.ftz.relu.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.ftz.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.sat.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.ftz.sat.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.ftz.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.sat.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.ftz.sat.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fmin.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.ftz.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.nan.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.ftz.nan.f16(half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.ftz.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.nan.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.ftz.nan.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fmin.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.ftz.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.nan.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.ftz.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.nan.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fmax.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.ftz.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.nan.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.ftz.nan.f16(half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.ftz.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.nan.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.ftz.nan.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fmax.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.ftz.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.nan.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.ftz.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.nan.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.ldg.global.f.f16.p0(ptr {{.*}}, i32 2)
// CHECK: call <2 x half> @llvm.nvvm.ldg.global.f.v2f16.p0(ptr {{.*}}, i32 4)
// CHECK: call half @llvm.nvvm.ldu.global.f.f16.p0(ptr {{.*}}, i32 2)
// CHECK: call <2 x half> @llvm.nvvm.ldu.global.f.v2f16.p0(ptr {{.*}}, i32 4)
__device__ void nvvm_native_half_types(void *a, void*b, void*c, __fp16* out) {
__fp16v2 resv2 = {0, 0};
*out += __nvvm_ex2_approx_f16(*(__fp16 *)a);
resv2 = __nvvm_ex2_approx_f16x2(*(__fp16v2*)a);

*out += __nvvm_fma_rn_relu_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16*)c);
*out += __nvvm_fma_rn_ftz_relu_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16 *)c);
resv2 += __nvvm_fma_rn_relu_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
resv2 += __nvvm_fma_rn_ftz_relu_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
*out += __nvvm_fma_rn_ftz_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16*)c);
*out += __nvvm_fma_rn_sat_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16*)c);
*out += __nvvm_fma_rn_ftz_sat_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16*)c);
resv2 += __nvvm_fma_rn_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
resv2 += __nvvm_fma_rn_ftz_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
resv2 += __nvvm_fma_rn_sat_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
resv2 += __nvvm_fma_rn_ftz_sat_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);

*out += __nvvm_fmin_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_ftz_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_nan_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_ftz_nan_f16(*(__fp16*)a, *(__fp16*)b);
resv2 += __nvvm_fmin_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmin_ftz_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmin_nan_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmin_ftz_nan_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
*out += __nvvm_fmin_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_ftz_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_nan_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_ftz_nan_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
resv2 += __nvvm_fmin_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmin_ftz_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmin_nan_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmin_ftz_nan_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);

*out += __nvvm_fmax_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_ftz_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_nan_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_ftz_nan_f16(*(__fp16*)a, *(__fp16*)b);
resv2 += __nvvm_fmax_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmax_ftz_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmax_nan_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmax_ftz_nan_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
*out += __nvvm_fmax_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_ftz_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_nan_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_ftz_nan_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
resv2 += __nvvm_fmax_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmax_ftz_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmax_nan_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmax_ftz_nan_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);

*out += __nvvm_ldg_h((__fp16 *)a);
resv2 += __nvvm_ldg_h2((__fp16v2 *)a);

*out += __nvvm_ldu_h((__fp16 *)a);
resv2 += __nvvm_ldu_h2((__fp16v2 *)a);

*out += resv2[0] + resv2[1];
}
4 changes: 2 additions & 2 deletions clang/test/CodeGenObjC/arc-foreach.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void test0(NSArray *array) {

// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[STATE_T]], ptr [[STATE]], i32 0, i32 1
// CHECK-LP64-NEXT: [[T1:%.*]] = load ptr, ptr [[T0]]
// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr ptr, ptr [[T1]], i64
// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr inbounds ptr, ptr [[T1]], i64
// CHECK-LP64-NEXT: [[T3:%.*]] = load ptr, ptr [[T2]]
// CHECK-LP64-NEXT: store ptr [[T3]], ptr [[X]]

Expand Down Expand Up @@ -100,7 +100,7 @@ void test1(NSArray *array) {

// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[STATE_T]], ptr [[STATE]], i32 0, i32 1
// CHECK-LP64-NEXT: [[T1:%.*]] = load ptr, ptr [[T0]]
// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr ptr, ptr [[T1]], i64
// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr inbounds ptr, ptr [[T1]], i64
// CHECK-LP64-NEXT: [[T3:%.*]] = load ptr, ptr [[T2]]
// CHECK-LP64-NEXT: call ptr @llvm.objc.initWeak(ptr [[X]], ptr [[T3]])

Expand Down
17 changes: 17 additions & 0 deletions clang/test/Driver/aarch64-multilib-rcpc3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang --target=aarch64-none-elf -march=armv8.9-a+rcpc3 -print-multi-flags-experimental -c %s 2>&1 | FileCheck %s

// The purpose of this regression test is to make sure that when
// compile options are converted into multilib selection flags, no
// empty strings are accidentally included in the
// -march=armv8.9-a+foo+bar+baz string, leading to two consecutive +
// signs. With +rcpc3 in the input, this used to generate an empty
// string for the anonymous architecture extension corresponding to
// the SubtargetFeature 'rcpc-immo', which is a dependency of rcpc3
// but has no separate extension name for use on command lines. So we
// check that the two named rcpc options appear, and that no ++
// appears before or after.

// CHECK: -march=armv8.9-a
// CHECK-NOT: ++
// CHECK-SAME: +rcpc+rcpc3+
// CHECK-NOT: ++
3 changes: 2 additions & 1 deletion clang/test/Driver/dxc_debug.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
// CHECK: "-cc1"
// CHECK-CV-SAME: -gcodeview
// CHECK-SAME: "-debug-info-kind=constructor"
// CHECK-DWARF-SAME: -dwarf-version
// Make sure dwarf-version is 4.
// CHECK-DWARF-SAME: -dwarf-version=4
11 changes: 11 additions & 0 deletions clang/test/Driver/ftime-trace-sections.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ def is_before(range1, range2):

log_contents = json.loads(sys.stdin.read())
events = log_contents["traceEvents"]

instants = [event for event in events if event["name"] == "InstantiateFunction"]
codegens = [event for event in events if event["name"] == "CodeGen Function"]
opts = [event for event in events if event["name"] == "OptFunction"]
frontends = [event for event in events if event["name"] == "Frontend"]
backends = [event for event in events if event["name"] == "Backend"]

Expand Down Expand Up @@ -48,3 +51,11 @@ def is_before(range1, range2):
]
):
sys.exit("Not all Frontend section are before all Backend sections!")

# Check that entries for foo exist and are in a demangled form.
if not any(e for e in instants if "foo<int>" in e["args"]["detail"]):
sys.exit("Missing Instantiate entry for foo!")
if not any(e for e in codegens if "foo<int>" in e["args"]["detail"]):
sys.exit("Missing CodeGen entry for foo!")
if not any(e for e in opts if "foo<int>" in e["args"]["detail"]):
sys.exit("Missing Optimize entry for foo!")
Loading