Skip to content

Commit e1555de

Browse files
Merge branch 'main' into private/udit/email_check
2 parents 9e0581a + a32040e commit e1555de

File tree

25 files changed

+1579
-79
lines changed

25 files changed

+1579
-79
lines changed

clang/include/clang/Analysis/Analyses/UninitializedValues.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class UninitUse {
5050
/// Is this use a const reference to this variable?
5151
bool ConstRefUse = false;
5252

53+
/// Is this use a const pointer to this variable?
54+
bool ConstPtrUse = false;
55+
5356
/// This use is always uninitialized if it occurs after any of these branches
5457
/// is taken.
5558
SmallVector<Branch, 2> UninitBranches;
@@ -65,11 +68,14 @@ class UninitUse {
6568
void setUninitAfterCall() { UninitAfterCall = true; }
6669
void setUninitAfterDecl() { UninitAfterDecl = true; }
6770
void setConstRefUse() { ConstRefUse = true; }
71+
void setConstPtrUse() { ConstPtrUse = true; }
6872

6973
/// Get the expression containing the uninitialized use.
7074
const Expr *getUser() const { return User; }
7175

7276
bool isConstRefUse() const { return ConstRefUse; }
77+
bool isConstPtrUse() const { return ConstPtrUse; }
78+
bool isConstRefOrPtrUse() const { return ConstRefUse || ConstPtrUse; }
7379

7480
/// The kind of uninitialized use.
7581
enum Kind {

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,9 +952,11 @@ def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
952952
def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
953953
def UninitializedStaticSelfInit : DiagGroup<"static-self-init">;
954954
def UninitializedConstReference : DiagGroup<"uninitialized-const-reference">;
955+
def UninitializedConstPointer : DiagGroup<"uninitialized-const-pointer">;
955956
def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
956957
UninitializedStaticSelfInit,
957-
UninitializedConstReference]>;
958+
UninitializedConstReference,
959+
UninitializedConstPointer]>;
958960
def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
959961
// #pragma optimize is often used to avoid to work around MSVC codegen bugs or
960962
// to disable inlining. It's not completely clear what alternative to suggest

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,6 +2548,10 @@ def warn_uninit_const_reference : Warning<
25482548
"variable %0 is uninitialized when passed as a const reference argument "
25492549
"here">, InGroup<UninitializedConstReference>, DefaultIgnore;
25502550

2551+
def warn_uninit_const_pointer : Warning<
2552+
"variable %0 is uninitialized when passed as a const pointer argument here">,
2553+
InGroup<UninitializedConstPointer>, DefaultIgnore;
2554+
25512555
def warn_unsequenced_mod_mod : Warning<
25522556
"multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
25532557
def warn_unsequenced_mod_use : Warning<

clang/lib/Analysis/UninitializedValues.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,7 @@ namespace {
276276
/// escaped the analysis and will be treated as an initialization.
277277
class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
278278
public:
279-
enum Class {
280-
Init,
281-
Use,
282-
SelfInit,
283-
ConstRefUse,
284-
Ignore
285-
};
279+
enum Class { Init, Use, SelfInit, ConstRefUse, ConstPtrUse, Ignore };
286280

287281
private:
288282
const DeclContext *DC;
@@ -451,8 +445,9 @@ void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
451445
const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
452446
const auto *UO = dyn_cast<UnaryOperator>(Ex);
453447
if (UO && UO->getOpcode() == UO_AddrOf)
454-
Ex = UO->getSubExpr();
455-
classify(Ex, Ignore);
448+
classify(UO->getSubExpr(), isTrivialBody ? Ignore : ConstPtrUse);
449+
else
450+
classify(Ex, Ignore);
456451
}
457452
}
458453
}
@@ -496,6 +491,7 @@ class TransferFunctions : public StmtVisitor<TransferFunctions> {
496491

497492
void reportUse(const Expr *ex, const VarDecl *vd);
498493
void reportConstRefUse(const Expr *ex, const VarDecl *vd);
494+
void reportConstPtrUse(const Expr *ex, const VarDecl *vd);
499495

500496
void VisitBinaryOperator(BinaryOperator *bo);
501497
void VisitBlockExpr(BlockExpr *be);
@@ -682,6 +678,15 @@ void TransferFunctions::reportConstRefUse(const Expr *ex, const VarDecl *vd) {
682678
}
683679
}
684680

681+
void TransferFunctions::reportConstPtrUse(const Expr *ex, const VarDecl *vd) {
682+
Value v = vals[vd];
683+
if (isAlwaysUninit(v)) {
684+
auto use = getUninitUse(ex, vd, v);
685+
use.setConstPtrUse();
686+
handler.handleUseOfUninitVariable(vd, use);
687+
}
688+
}
689+
685690
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
686691
// This represents an initialization of the 'element' value.
687692
if (const auto *DS = dyn_cast<DeclStmt>(FS->getElement())) {
@@ -754,6 +759,9 @@ void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
754759
case ClassifyRefs::ConstRefUse:
755760
reportConstRefUse(dr, cast<VarDecl>(dr->getDecl()));
756761
break;
762+
case ClassifyRefs::ConstPtrUse:
763+
reportConstPtrUse(dr, cast<VarDecl>(dr->getDecl()));
764+
break;
757765
}
758766
}
759767

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,14 @@ static bool DiagnoseUninitializedConstRefUse(Sema &S, const VarDecl *VD,
994994
return !S.getDiagnostics().isLastDiagnosticIgnored();
995995
}
996996

997+
/// Diagnose uninitialized const pointer usages.
998+
static bool DiagnoseUninitializedConstPtrUse(Sema &S, const VarDecl *VD,
999+
const UninitUse &Use) {
1000+
S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_pointer)
1001+
<< VD->getDeclName() << Use.getUser()->getSourceRange();
1002+
return !S.getDiagnostics().isLastDiagnosticIgnored();
1003+
}
1004+
9971005
/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
9981006
/// uninitialized variable. This manages the different forms of diagnostic
9991007
/// emitted for particular types of uses. Returns true if the use was diagnosed
@@ -1599,9 +1607,9 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
15991607
// a stable ordering.
16001608
llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
16011609
// Prefer the direct use of an uninitialized variable over its use via
1602-
// constant reference.
1603-
if (a.isConstRefUse() != b.isConstRefUse())
1604-
return b.isConstRefUse();
1610+
// constant reference or pointer.
1611+
if (a.isConstRefOrPtrUse() != b.isConstRefOrPtrUse())
1612+
return b.isConstRefOrPtrUse();
16051613
// Prefer a more confident report over a less confident one.
16061614
if (a.getKind() != b.getKind())
16071615
return a.getKind() > b.getKind();
@@ -1612,6 +1620,9 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
16121620
if (U.isConstRefUse()) {
16131621
if (DiagnoseUninitializedConstRefUse(S, vd, U))
16141622
return;
1623+
} else if (U.isConstPtrUse()) {
1624+
if (DiagnoseUninitializedConstPtrUse(S, vd, U))
1625+
return;
16151626
} else {
16161627
// If we have self-init, downgrade all uses to 'may be uninitialized'.
16171628
UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
@@ -2828,7 +2839,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
28282839
if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
28292840
!Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
28302841
!Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||
2831-
!Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc())) {
2842+
!Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc()) ||
2843+
!Diags.isIgnored(diag::warn_uninit_const_pointer, D->getBeginLoc())) {
28322844
if (CFG *cfg = AC.getCFG()) {
28332845
UninitValsDiagReporter reporter(S);
28342846
UninitVariablesAnalysisStats stats;

clang/test/Misc/warning-wall.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ CHECK-NEXT: -Wuninitialized
6666
CHECK-NEXT: -Wsometimes-uninitialized
6767
CHECK-NEXT: -Wstatic-self-init
6868
CHECK-NEXT: -Wuninitialized-const-reference
69+
CHECK-NEXT: -Wuninitialized-const-pointer
6970
CHECK-NEXT: -Wunknown-pragmas
7071
CHECK-NEXT: -Wunused
7172
CHECK-NEXT: -Wunused-argument
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -Wuninitialized-const-pointer -verify %s
2+
3+
template <class T>
4+
void ignore_template(const T *) {}
5+
void ignore(const int *) {}
6+
void dont_ignore_non_empty(const int *) { ; }
7+
void dont_ignore_block(const int *) { {} }
8+
void dont_ignore_try_block(const int *) try {
9+
} catch (...) {
10+
}
11+
int const_ptr_use(const int *);
12+
13+
void f(int a) {
14+
int i;
15+
const_ptr_use(&i); // expected-warning {{variable 'i' is uninitialized when passed as a const pointer argument here}}
16+
int j = j + const_ptr_use(&j); // expected-warning {{variable 'j' is uninitialized when used within its own initialization}}
17+
int k = k; // expected-warning {{variable 'k' is uninitialized when used within its own initialization}}
18+
const_ptr_use(&k);
19+
20+
// Only report if a variable is always uninitialized at the point of use
21+
int l;
22+
if (a < 42)
23+
l = 1;
24+
const_ptr_use(&l);
25+
26+
// Don't report if the called function is known to be empty.
27+
int m;
28+
ignore_template(&m);
29+
ignore(&m);
30+
dont_ignore_non_empty(&m); // expected-warning {{variable 'm' is uninitialized when passed as a const pointer argument here}}
31+
int n;
32+
dont_ignore_block(&n); // expected-warning {{variable 'n' is uninitialized when passed as a const pointer argument here}}
33+
int o;
34+
dont_ignore_try_block(&o); // expected-warning {{variable 'o' is uninitialized when passed as a const pointer argument here}}
35+
}

libc/src/__support/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ add_subdirectory(time)
406406

407407
# Requires access to uchar header which is not on macos
408408
# Therefore, cannot currently build this on macos in overlay mode
409-
if(NOT(LIBC_TARGET_OS_IS_DARWIN))
409+
if(NOT (LIBC_TARGET_OS_IS_DARWIN))
410410
add_subdirectory(wchar)
411411
endif()
412412

libc/src/__support/wchar/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ add_header_library(
66
libc.hdr.types.char32_t
77
)
88

9+
add_header_library(
10+
string_converter
11+
HDRS
12+
string_converter.h
13+
DEPENDS
14+
libc.hdr.types.char8_t
15+
libc.hdr.types.char32_t
16+
libc.hdr.types.size_t
17+
libc.src.__support.error_or
18+
.mbstate
19+
.character_converter
20+
)
21+
922
add_object_library(
1023
character_converter
1124
HDRS
@@ -16,6 +29,7 @@ add_object_library(
1629
libc.hdr.errno_macros
1730
libc.hdr.types.char8_t
1831
libc.hdr.types.char32_t
32+
libc.hdr.types.size_t
1933
libc.src.__support.error_or
2034
libc.src.__support.math_extras
2135
.mbstate

libc/src/__support/wchar/character_converter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "hdr/errno_macros.h"
1010
#include "hdr/types/char32_t.h"
1111
#include "hdr/types/char8_t.h"
12+
#include "hdr/types/size_t.h"
1213
#include "src/__support/CPP/bit.h"
1314
#include "src/__support/common.h"
1415
#include "src/__support/error_or.h"
@@ -92,6 +93,7 @@ int CharacterConverter::push(char8_t utf8_byte) {
9293
state->bytes_stored++;
9394
return 0;
9495
}
96+
9597
// Invalid byte -> reset the state
9698
clear();
9799
return EILSEQ;
@@ -130,6 +132,12 @@ ErrorOr<char32_t> CharacterConverter::pop_utf32() {
130132
return utf32;
131133
}
132134

135+
size_t CharacterConverter::sizeAsUTF32() {
136+
return 1; // a single utf-32 value can fit an entire character
137+
}
138+
139+
size_t CharacterConverter::sizeAsUTF8() { return state->total_bytes; }
140+
133141
ErrorOr<char8_t> CharacterConverter::pop_utf8() {
134142
if (isEmpty())
135143
return Error(-1);
@@ -156,6 +164,9 @@ ErrorOr<char8_t> CharacterConverter::pop_utf8() {
156164
}
157165

158166
state->bytes_stored--;
167+
if (state->bytes_stored == 0)
168+
clear();
169+
159170
return static_cast<char8_t>(output);
160171
}
161172

0 commit comments

Comments
 (0)