Skip to content

Commit 71c0fd4

Browse files
author
Jenkins
committed
merge main into amd-staging
Change-Id: I3f22ab5402113df190587c26aa5dcc8b370cbb35
2 parents 113585a + b1f4a02 commit 71c0fd4

File tree

281 files changed

+15827
-12364
lines changed

Some content is hidden

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

281 files changed

+15827
-12364
lines changed

.github/workflows/docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ jobs:
106106
with:
107107
python-version: '3.11'
108108
cache: 'pip'
109-
cache-dependency-path: 'llvm/docs/requirements.txt'
109+
cache-dependency-path: 'llvm/docs/requirements-hashed.txt'
110110
- name: Install python dependencies
111-
run: pip install -r llvm/docs/requirements.txt
111+
run: pip install -r llvm/docs/requirements-hashed.txt
112112
- name: Install system dependencies
113113
run: |
114114
sudo apt-get update
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t/yaml %t/md
3+
4+
// RUN: clang-doc --doxygen --executor=standalone %s -output=%t/yaml
5+
// RUN: FileCheck %s < %t/yaml/index.yaml --check-prefix=YAML
6+
7+
// RUN: clang-doc --doxygen --executor=standalone %s -output=%t/md --format=md
8+
// RUN: FileCheck %s < %t/md/GlobalNamespace/index.md --check-prefix=MD
9+
10+
// YAML: ---
11+
// YAML-NEXT: USR: '0000000000000000000000000000000000000000'
12+
// YAML-NEXT: ChildFunctions:
13+
14+
// MD: # Global Namespace
15+
// MD: ## Functions
16+
17+
extern bool b();
18+
19+
// YAML-NEXT: - USR: '88A104C263241E354ECF5B55B04AE8CEAD625B71'
20+
// YAML-NEXT: Name: 'b'
21+
// YAML-NEXT: Location:
22+
// YAML-NEXT: - LineNumber: [[# @LINE-5]]
23+
// YAML-NEXT: Filename: '{{.*}}'
24+
// YAML-NEXT: ReturnType:
25+
// YAML-NEXT: Type:
26+
// YAML-NEXT: Name: '_Bool'
27+
// YAML-NEXT: QualName: '_Bool'
28+
29+
// MD: ### b
30+
// MD: *_Bool b()*
31+
32+
char c();
33+
34+
// YAML-NEXT: - USR: 'EA3287837B3F175C8DB154406B4DAD2924F479B5'
35+
// YAML-NEXT: Name: 'c'
36+
// YAML-NEXT: Location:
37+
// YAML-NEXT: - LineNumber: [[# @LINE-5]]
38+
// YAML-NEXT: Filename: '{{.*}}'
39+
// YAML-NEXT: ReturnType:
40+
// YAML-NEXT: Type:
41+
// YAML-NEXT: Name: 'char'
42+
// YAML-NEXT: QualName: 'char'
43+
44+
// MD: ### c
45+
// MD: *char c()*
46+
47+
double d();
48+
49+
// YAML-NEXT: - USR: '60A47E4696CEFC411AB2E1EEFA2DD914E2A7E450'
50+
// YAML-NEXT: Name: 'd'
51+
// YAML-NEXT: Location:
52+
// YAML-NEXT: - LineNumber: [[# @LINE-5]]
53+
// YAML-NEXT: Filename: '{{.*}}'
54+
// YAML-NEXT: ReturnType:
55+
// YAML-NEXT: Type:
56+
// YAML-NEXT: Name: 'double'
57+
// YAML-NEXT: QualName: 'double'
58+
59+
// MD: ### d
60+
// MD: *double d()*
61+
62+
float f();
63+
64+
// YAML-NEXT: - USR: 'B3A9EC6BECD5869CF3ACDFB25153CFE6BBDD5EAB'
65+
// YAML-NEXT: Name: 'f'
66+
// YAML-NEXT: Location:
67+
// YAML-NEXT: - LineNumber: [[# @LINE-5]]
68+
// YAML-NEXT: Filename: '{{.*}}'
69+
// YAML-NEXT: ReturnType:
70+
// YAML-NEXT: Type:
71+
// YAML-NEXT: Name: 'float'
72+
// YAML-NEXT: QualName: 'float'
73+
74+
// MD: ### f
75+
// MD: *float f()*
76+
77+
int i();
78+
79+
// YAML-NEXT: - USR: '307041280A81EB46F949A94AD52587C659FD801C'
80+
// YAML-NEXT: Name: 'i'
81+
// YAML-NEXT: Location:
82+
// YAML-NEXT: - LineNumber: [[# @LINE-5]]
83+
// YAML-NEXT: Filename: '{{.*}}'
84+
// YAML-NEXT: ReturnType:
85+
// YAML-NEXT: Type:
86+
// YAML-NEXT: Name: 'int'
87+
// YAML-NEXT: QualName: 'int'
88+
89+
// MD: ### i
90+
// MD: *int i()*
91+
92+
long l();
93+
94+
// YAML-NEXT: - USR: 'A1CE9AB0064C412F857592E01332C641C1A06F37'
95+
// YAML-NEXT: Name: 'l'
96+
// YAML-NEXT: Location:
97+
// YAML-NEXT: - LineNumber: [[# @LINE-5]]
98+
// YAML-NEXT: Filename: '{{.*}}'
99+
// YAML-NEXT: ReturnType:
100+
// YAML-NEXT: Type:
101+
// YAML-NEXT: Name: 'long'
102+
// YAML-NEXT: QualName: 'long'
103+
104+
// MD: ### l
105+
// MD: *long l()*
106+
107+
long long ll();
108+
109+
// YAML-NEXT: - USR: '5C2C44ED4825C066EF6ED796863586F343C8BCA9'
110+
// YAML-NEXT: Name: 'll'
111+
// YAML-NEXT: Location:
112+
// YAML-NEXT: - LineNumber: [[# @LINE-5]]
113+
// YAML-NEXT: Filename: '{{.*}}'
114+
// YAML-NEXT: ReturnType:
115+
// YAML-NEXT: Type:
116+
// YAML-NEXT: Name: 'long long'
117+
// YAML-NEXT: QualName: 'long long'
118+
119+
// MD: ### ll
120+
// MD: *long long ll()*
121+
122+
short s();
123+
124+
// YAML-NEXT: - USR: '412341570FD3AD2C3A1E9A1DE7B3C01C07BEACFE'
125+
// YAML-NEXT: Name: 's'
126+
// YAML-NEXT: Location:
127+
// YAML-NEXT: - LineNumber: [[# @LINE-5]]
128+
// YAML-NEXT: Filename: '{{.*}}'
129+
// YAML-NEXT: ReturnType:
130+
// YAML-NEXT: Type:
131+
// YAML-NEXT: Name: 'short'
132+
// YAML-NEXT: QualName: 'short'
133+
// YAML-NEXT: ...
134+
135+
// MD: ### s
136+
// MD: *short s()*

clang/docs/ReleaseNotes.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,16 @@ Improvements to Clang's diagnostics
713713
views.push_back(std::string("123")); // warning
714714
}
715715

716+
- Clang now emits a ``-Wtautological-compare`` diagnostic when a check for
717+
pointer addition overflow is always true or false, because overflow would
718+
be undefined behavior.
719+
720+
.. code-block:: c++
721+
722+
bool incorrect_overflow_check(const char *ptr, size_t index) {
723+
return ptr + index < ptr; // warning
724+
}
725+
716726
Improvements to Clang's time-trace
717727
----------------------------------
718728

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10249,7 +10249,7 @@ def warn_dangling_reference_captured_by_unknown : Warning<
1024910249
// should result in a warning, since these always evaluate to a constant.
1025010250
// Array comparisons have similar warnings
1025110251
def warn_comparison_always : Warning<
10252-
"%select{self-|array }0comparison always evaluates to "
10252+
"%select{self-|array |pointer }0comparison always evaluates to "
1025310253
"%select{a constant|true|false|'std::strong_ordering::equal'}1">,
1025410254
InGroup<TautologicalCompare>;
1025510255
def warn_comparison_bitwise_always : Warning<

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 62 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -248,48 +248,76 @@ static SanitizerMask setGroupBits(SanitizerMask Kinds) {
248248
return Kinds;
249249
}
250250

251-
// Computes the sanitizer mask based on the default plus opt-in (if supported)
252-
// minus opt-out.
251+
// Computes the sanitizer mask as:
252+
// Default + Arguments (in or out)
253+
// with arguments parsed from left to right.
254+
//
255+
// Error messages are printed if the AlwaysIn or AlwaysOut invariants are
256+
// violated, but the caller must enforce these invariants themselves.
253257
static SanitizerMask
254258
parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,
255-
bool DiagnoseErrors, SanitizerMask Supported,
256-
SanitizerMask Default, int OptInID, int OptOutID) {
257-
SanitizerMask Remove; // During the loop below, the accumulated set of
258-
// sanitizers disabled by the current sanitizer
259-
// argument or any argument after it.
260-
SanitizerMask Kinds;
261-
SanitizerMask SupportedWithGroups = setGroupBits(Supported);
262-
263-
for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
259+
bool DiagnoseErrors, SanitizerMask Default,
260+
SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID,
261+
int OptOutID) {
262+
assert(!(AlwaysIn & AlwaysOut) &&
263+
"parseSanitizeArgs called with contradictory in/out requirements");
264+
265+
SanitizerMask Output = Default;
266+
// Keep track of which violations we have already reported, to avoid
267+
// duplicate error messages.
268+
SanitizerMask DiagnosedAlwaysInViolations;
269+
SanitizerMask DiagnosedAlwaysOutViolations;
270+
for (const auto *Arg : Args) {
264271
if (Arg->getOption().matches(OptInID)) {
265-
Arg->claim();
266-
SanitizerMask Add = parseArgValues(D, Arg, true);
267-
Add &= ~Remove;
268-
SanitizerMask InvalidValues = Add & ~SupportedWithGroups;
269-
if (InvalidValues && DiagnoseErrors) {
270-
SanitizerSet S;
271-
S.Mask = InvalidValues;
272-
D.Diag(diag::err_drv_unsupported_option_argument)
273-
<< Arg->getSpelling() << toString(S);
272+
SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
273+
// Report error if user explicitly tries to opt-in to an always-out
274+
// sanitizer.
275+
if (SanitizerMask KindsToDiagnose =
276+
Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {
277+
if (DiagnoseErrors) {
278+
SanitizerSet SetToDiagnose;
279+
SetToDiagnose.Mask |= KindsToDiagnose;
280+
D.Diag(diag::err_drv_unsupported_option_argument)
281+
<< Arg->getSpelling() << toString(SetToDiagnose);
282+
DiagnosedAlwaysOutViolations |= KindsToDiagnose;
283+
}
274284
}
275-
Kinds |= expandSanitizerGroups(Add) & ~Remove;
285+
Output |= expandSanitizerGroups(Add);
286+
Arg->claim();
276287
} else if (Arg->getOption().matches(OptOutID)) {
288+
SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
289+
// Report error if user explicitly tries to opt-out of an always-in
290+
// sanitizer.
291+
if (SanitizerMask KindsToDiagnose =
292+
Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {
293+
if (DiagnoseErrors) {
294+
SanitizerSet SetToDiagnose;
295+
SetToDiagnose.Mask |= KindsToDiagnose;
296+
D.Diag(diag::err_drv_unsupported_option_argument)
297+
<< Arg->getSpelling() << toString(SetToDiagnose);
298+
DiagnosedAlwaysInViolations |= KindsToDiagnose;
299+
}
300+
}
301+
Output &= ~expandSanitizerGroups(Remove);
277302
Arg->claim();
278-
Remove |= expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors));
279303
}
280304
}
281305

282-
// Apply default behavior.
283-
Kinds |= Default & ~Remove;
284-
285-
return Kinds;
306+
return Output;
286307
}
287308

288309
static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
289310
const llvm::opt::ArgList &Args,
290311
bool DiagnoseErrors) {
291-
return parseSanitizeArgs(D, Args, DiagnoseErrors, TrappingSupported,
292-
TrappingDefault, options::OPT_fsanitize_trap_EQ,
312+
SanitizerMask AlwaysTrap; // Empty
313+
SanitizerMask NeverTrap = ~(setGroupBits(TrappingSupported));
314+
315+
// N.B. We do *not* enforce NeverTrap. This maintains the behavior of
316+
// '-fsanitize=undefined -fsanitize-trap=undefined'
317+
// (clang/test/Driver/fsanitize.c ), which is that vptr is not enabled at all
318+
// (not even in recover mode) in order to avoid the need for a ubsan runtime.
319+
return parseSanitizeArgs(D, Args, DiagnoseErrors, TrappingDefault, AlwaysTrap,
320+
NeverTrap, options::OPT_fsanitize_trap_EQ,
293321
options::OPT_fno_sanitize_trap_EQ);
294322
}
295323

@@ -657,44 +685,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
657685
// default in ASan?
658686

659687
// Parse -f(no-)?sanitize-recover flags.
660-
SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;
661-
SanitizerMask DiagnosedUnrecoverableKinds;
662-
SanitizerMask DiagnosedAlwaysRecoverableKinds;
663-
for (const auto *Arg : Args) {
664-
if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
665-
SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
666-
// Report error if user explicitly tries to recover from unrecoverable
667-
// sanitizer.
668-
if (SanitizerMask KindsToDiagnose =
669-
Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
670-
SanitizerSet SetToDiagnose;
671-
SetToDiagnose.Mask |= KindsToDiagnose;
672-
if (DiagnoseErrors)
673-
D.Diag(diag::err_drv_unsupported_option_argument)
674-
<< Arg->getSpelling() << toString(SetToDiagnose);
675-
DiagnosedUnrecoverableKinds |= KindsToDiagnose;
676-
}
677-
RecoverableKinds |= expandSanitizerGroups(Add);
678-
Arg->claim();
679-
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
680-
SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
681-
// Report error if user explicitly tries to disable recovery from
682-
// always recoverable sanitizer.
683-
if (SanitizerMask KindsToDiagnose =
684-
Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
685-
SanitizerSet SetToDiagnose;
686-
SetToDiagnose.Mask |= KindsToDiagnose;
687-
if (DiagnoseErrors)
688-
D.Diag(diag::err_drv_unsupported_option_argument)
689-
<< Arg->getSpelling() << toString(SetToDiagnose);
690-
DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
691-
}
692-
RecoverableKinds &= ~expandSanitizerGroups(Remove);
693-
Arg->claim();
694-
}
695-
}
696-
RecoverableKinds &= Kinds;
688+
SanitizerMask RecoverableKinds = parseSanitizeArgs(
689+
D, Args, DiagnoseErrors, RecoverableByDefault, AlwaysRecoverable,
690+
Unrecoverable, options::OPT_fsanitize_recover_EQ,
691+
options::OPT_fno_sanitize_recover_EQ);
692+
RecoverableKinds |= AlwaysRecoverable;
697693
RecoverableKinds &= ~Unrecoverable;
694+
RecoverableKinds &= Kinds;
698695

699696
TrappingKinds &= Kinds;
700697
RecoverableKinds &= ~TrappingKinds;

clang/lib/Sema/SemaExpr.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11786,6 +11786,50 @@ static bool checkForArray(const Expr *E) {
1178611786
return D->getType()->isArrayType() && !D->isWeak();
1178711787
}
1178811788

11789+
/// Detect patterns ptr + size >= ptr and ptr + size < ptr, where ptr is a
11790+
/// pointer and size is an unsigned integer. Return whether the result is
11791+
/// always true/false.
11792+
static std::optional<bool> isTautologicalBoundsCheck(const Expr *LHS,
11793+
const Expr *RHS,
11794+
BinaryOperatorKind Opc) {
11795+
if (!LHS->getType()->isPointerType())
11796+
return std::nullopt;
11797+
11798+
// Canonicalize to >= or < predicate.
11799+
switch (Opc) {
11800+
case BO_GE:
11801+
case BO_LT:
11802+
break;
11803+
case BO_GT:
11804+
std::swap(LHS, RHS);
11805+
Opc = BO_LT;
11806+
break;
11807+
case BO_LE:
11808+
std::swap(LHS, RHS);
11809+
Opc = BO_GE;
11810+
break;
11811+
default:
11812+
return std::nullopt;
11813+
}
11814+
11815+
auto *BO = dyn_cast<BinaryOperator>(LHS);
11816+
if (!BO || BO->getOpcode() != BO_Add)
11817+
return std::nullopt;
11818+
11819+
Expr *Other;
11820+
if (Expr::isSameComparisonOperand(BO->getLHS(), RHS))
11821+
Other = BO->getRHS();
11822+
else if (Expr::isSameComparisonOperand(BO->getRHS(), RHS))
11823+
Other = BO->getLHS();
11824+
else
11825+
return std::nullopt;
11826+
11827+
if (!Other->getType()->isUnsignedIntegerType())
11828+
return std::nullopt;
11829+
11830+
return Opc == BO_GE;
11831+
}
11832+
1178911833
/// Diagnose some forms of syntactically-obvious tautological comparison.
1179011834
static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
1179111835
Expr *LHS, Expr *RHS,
@@ -11895,6 +11939,12 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
1189511939
S.PDiag(diag::warn_comparison_always)
1189611940
<< 1 /*array comparison*/
1189711941
<< Result);
11942+
} else if (std::optional<bool> Res =
11943+
isTautologicalBoundsCheck(LHS, RHS, Opc)) {
11944+
S.DiagRuntimeBehavior(Loc, nullptr,
11945+
S.PDiag(diag::warn_comparison_always)
11946+
<< 2 /*pointer comparison*/
11947+
<< (*Res ? AlwaysTrue : AlwaysFalse));
1189811948
}
1189911949
}
1190011950

0 commit comments

Comments
 (0)