Skip to content

Commit 63424ba

Browse files
committed
Merge remote-tracking branch 'origin/main' into vplan-for-hoist
2 parents 89b10f2 + 467a9bd commit 63424ba

File tree

86 files changed

+1842
-992
lines changed

Some content is hidden

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

86 files changed

+1842
-992
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,8 @@ Android Support
605605
Windows Support
606606
^^^^^^^^^^^^^^^
607607

608+
- clang-cl now supports ``/std:c++23preview`` which enables C++23 features.
609+
608610
- Clang no longer allows references inside a union when emulating MSVC 1900+ even if `fms-extensions` is enabled.
609611
Starting with VS2015, MSVC 1900, this Microsoft extension is no longer allowed and always results in an error.
610612
Clang now follows the MSVC behavior in this scenario.

clang/docs/analyzer/checkers.rst

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3371,12 +3371,23 @@ Checks for overlap in two buffer arguments. Applies to: ``memcpy, mempcpy, wmem
33713371
33723372
alpha.unix.cstring.NotNullTerminated (C)
33733373
""""""""""""""""""""""""""""""""""""""""
3374-
Check for arguments which are not null-terminated strings; applies to: ``strlen, strnlen, strcpy, strncpy, strcat, strncat, wcslen, wcsnlen``.
3374+
Check for arguments which are not null-terminated strings;
3375+
applies to the ``strlen``, ``strcpy``, ``strcat``, ``strcmp`` family of functions.
3376+
3377+
Only very fundamental cases are detected where the passed memory block is
3378+
absolutely different from a null-terminated string. This checker does not
3379+
find if a memory buffer is passed where the terminating zero character
3380+
is missing.
33753381
33763382
.. code-block:: c
33773383
3378-
void test() {
3379-
int y = strlen((char *)&test); // warn
3384+
void test1() {
3385+
int l = strlen((char *)&test); // warn
3386+
}
3387+
3388+
void test2() {
3389+
label:
3390+
int l = strlen((char *)&&label); // warn
33803391
}
33813392
33823393
.. _alpha-unix-cstring-OutOfBounds:

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8531,7 +8531,7 @@ def _SLASH_execution_charset : CLCompileJoined<"execution-charset:">,
85318531
HelpText<"Set runtime encoding, supports only UTF-8">,
85328532
Alias<fexec_charset_EQ>;
85338533
def _SLASH_std : CLCompileJoined<"std:">,
8534-
HelpText<"Set language version (c++14,c++17,c++20,c++latest,c11,c17)">;
8534+
HelpText<"Set language version (c++14,c++17,c++20,c++23preview,c++latest,c11,c17)">;
85358535
def _SLASH_U : CLJoinedOrSeparate<"U">, HelpText<"Undefine macro">,
85368536
MetaVarName<"<macro>">, Alias<U>;
85378537
def _SLASH_validate_charset : CLFlag<"validate-charset">,

clang/include/clang/ExtractAPI/API.h

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/ADT/SmallVector.h"
2727
#include "llvm/Support/Allocator.h"
2828
#include "llvm/Support/Casting.h"
29+
#include "llvm/Support/Compiler.h"
2930
#include "llvm/TargetParser/Triple.h"
3031
#include <cstddef>
3132
#include <iterator>
@@ -615,7 +616,24 @@ struct TagRecord : APIRecord, RecordContext {
615616
return classofKind(Record->getKind());
616617
}
617618
static bool classofKind(RecordKind K) {
618-
return K == RK_Struct || K == RK_Union || K == RK_Enum;
619+
switch (K) {
620+
case RK_Enum:
621+
LLVM_FALLTHROUGH;
622+
case RK_Struct:
623+
LLVM_FALLTHROUGH;
624+
case RK_Union:
625+
LLVM_FALLTHROUGH;
626+
case RK_CXXClass:
627+
LLVM_FALLTHROUGH;
628+
case RK_ClassTemplate:
629+
LLVM_FALLTHROUGH;
630+
case RK_ClassTemplateSpecialization:
631+
LLVM_FALLTHROUGH;
632+
case RK_ClassTemplatePartialSpecialization:
633+
return true;
634+
default:
635+
return false;
636+
}
619637
}
620638

621639
bool IsEmbeddedInVarDeclarator;
@@ -684,7 +702,22 @@ struct RecordRecord : TagRecord {
684702
return classofKind(Record->getKind());
685703
}
686704
static bool classofKind(RecordKind K) {
687-
return K == RK_Struct || K == RK_Union;
705+
switch (K) {
706+
case RK_Struct:
707+
LLVM_FALLTHROUGH;
708+
case RK_Union:
709+
LLVM_FALLTHROUGH;
710+
case RK_CXXClass:
711+
LLVM_FALLTHROUGH;
712+
case RK_ClassTemplate:
713+
LLVM_FALLTHROUGH;
714+
case RK_ClassTemplateSpecialization:
715+
LLVM_FALLTHROUGH;
716+
case RK_ClassTemplatePartialSpecialization:
717+
return true;
718+
default:
719+
return false;
720+
}
688721
}
689722

690723
bool isAnonymousWithNoTypedef() { return Name.empty(); }

clang/lib/AST/ExprConstant.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7237,6 +7237,7 @@ class APValueToBufferConverter {
72377237

72387238
case APValue::ComplexInt:
72397239
case APValue::ComplexFloat:
7240+
return visitComplex(Val, Ty, Offset);
72407241
case APValue::FixedPoint:
72417242
// FIXME: We should support these.
72427243

@@ -7323,6 +7324,31 @@ class APValueToBufferConverter {
73237324
return true;
73247325
}
73257326

7327+
bool visitComplex(const APValue &Val, QualType Ty, CharUnits Offset) {
7328+
const ComplexType *ComplexTy = Ty->castAs<ComplexType>();
7329+
QualType EltTy = ComplexTy->getElementType();
7330+
CharUnits EltSizeChars = Info.Ctx.getTypeSizeInChars(EltTy);
7331+
bool IsInt = Val.isComplexInt();
7332+
7333+
if (IsInt) {
7334+
if (!visitInt(Val.getComplexIntReal(), EltTy,
7335+
Offset + (0 * EltSizeChars)))
7336+
return false;
7337+
if (!visitInt(Val.getComplexIntImag(), EltTy,
7338+
Offset + (1 * EltSizeChars)))
7339+
return false;
7340+
} else {
7341+
if (!visitFloat(Val.getComplexFloatReal(), EltTy,
7342+
Offset + (0 * EltSizeChars)))
7343+
return false;
7344+
if (!visitFloat(Val.getComplexFloatImag(), EltTy,
7345+
Offset + (1 * EltSizeChars)))
7346+
return false;
7347+
}
7348+
7349+
return true;
7350+
}
7351+
73267352
bool visitVector(const APValue &Val, QualType Ty, CharUnits Offset) {
73277353
const VectorType *VTy = Ty->castAs<VectorType>();
73287354
QualType EltTy = VTy->getElementType();
@@ -7595,6 +7621,23 @@ class BufferToAPValueConverter {
75957621
return ArrayValue;
75967622
}
75977623

7624+
std::optional<APValue> visit(const ComplexType *Ty, CharUnits Offset) {
7625+
QualType ElementType = Ty->getElementType();
7626+
CharUnits ElementWidth = Info.Ctx.getTypeSizeInChars(ElementType);
7627+
bool IsInt = ElementType->isIntegerType();
7628+
7629+
std::optional<APValue> Values[2];
7630+
for (unsigned I = 0; I != 2; ++I) {
7631+
Values[I] = visitType(Ty->getElementType(), Offset + I * ElementWidth);
7632+
if (!Values[I])
7633+
return std::nullopt;
7634+
}
7635+
7636+
if (IsInt)
7637+
return APValue(Values[0]->getInt(), Values[1]->getInt());
7638+
return APValue(Values[0]->getFloat(), Values[1]->getFloat());
7639+
}
7640+
75987641
std::optional<APValue> visit(const VectorType *VTy, CharUnits Offset) {
75997642
QualType EltTy = VTy->getElementType();
76007643
unsigned NElts = VTy->getNumElements();

clang/lib/Basic/Targets/OSTargets.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,11 @@ static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) {
214214
Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
215215

216216
if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
217-
if (Opts.CPlusPlus23)
217+
if (Opts.CPlusPlus26)
218218
// TODO update to the proper value.
219-
Builder.defineMacro("_MSVC_LANG", "202004L");
219+
Builder.defineMacro("_MSVC_LANG", "202400L");
220+
else if (Opts.CPlusPlus23)
221+
Builder.defineMacro("_MSVC_LANG", "202302L");
220222
else if (Opts.CPlusPlus20)
221223
Builder.defineMacro("_MSVC_LANG", "202002L");
222224
else if (Opts.CPlusPlus17)

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7225,6 +7225,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
72257225
.Case("c++17", "-std=c++17")
72267226
.Case("c++20", "-std=c++20")
72277227
// TODO add c++23 and c++26 when MSVC supports it.
7228+
.Case("c++23preview", "-std=c++23")
72287229
.Case("c++latest", "-std=c++26")
72297230
.Default("");
72307231
if (LanguageStandard.empty())

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2216,7 +2216,7 @@ ExprResult SemaOpenACC::CheckGangExpr(OpenACCGangKind GK, Expr *E) {
22162216
case OpenACCGangKind::Static:
22172217
return CheckGangStaticExpr(*this, E);
22182218
}
2219-
}
2219+
} break;
22202220
default:
22212221
llvm_unreachable("Non compute construct in active compute construct?");
22222222
}

clang/test/Analysis/string.c

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,10 @@ void strcpy_fn_const(char *x) {
361361
strcpy(x, (const char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
362362
}
363363

364+
void strcpy_fn_dst(const char *x) {
365+
strcpy((char*)&strcpy_fn, x); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
366+
}
367+
364368
extern int globalInt;
365369
void strcpy_effects(char *x, char *y) {
366370
char a = x[0];
@@ -469,8 +473,22 @@ void strcat_null_src(char *x) {
469473
strcat(x, NULL); // expected-warning{{Null pointer passed as 2nd argument to string concatenation function}}
470474
}
471475

472-
void strcat_fn(char *x) {
473-
strcat(x, (char*)&strcat_fn); // expected-warning{{Argument to string concatenation function is the address of the function 'strcat_fn', which is not a null-terminated string}}
476+
void strcat_fn_dst(const char *x) {
477+
strcat((char*)&strcat_fn_dst, x); // expected-warning{{Argument to string concatenation function is the address of the function 'strcat_fn_dst', which is not a null-terminated string}}
478+
}
479+
480+
void strcat_fn_src(char *x) {
481+
strcat(x, (char*)&strcat_fn_src); // expected-warning{{Argument to string concatenation function is the address of the function 'strcat_fn_src', which is not a null-terminated string}}
482+
}
483+
484+
void strcat_label_dst(const char *x) {
485+
label:
486+
strcat((char*)&&label, x); // expected-warning{{Argument to string concatenation function is the address of the label 'label', which is not a null-terminated string}}
487+
}
488+
489+
void strcat_label_src(char *x) {
490+
label:
491+
strcat(x, (char*)&&label); // expected-warning{{Argument to string concatenation function is the address of the label 'label', which is not a null-terminated string}}
474492
}
475493

476494
void strcat_effects(char *y) {
@@ -568,8 +586,12 @@ void strncpy_null_src(char *x) {
568586
strncpy(x, NULL, 5); // expected-warning{{Null pointer passed as 2nd argument to string copy function}}
569587
}
570588

571-
void strncpy_fn(char *x) {
572-
strncpy(x, (char*)&strcpy_fn, 5); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
589+
void strncpy_fn_src(char *x) {
590+
strncpy(x, (char*)&strncpy_fn_src, 5); // expected-warning{{Argument to string copy function is the address of the function 'strncpy_fn_src', which is not a null-terminated string}}
591+
}
592+
593+
void strncpy_fn_dst(const char *x) {
594+
strncpy((char*)&strncpy_fn_dst, x, 5); // expected-warning{{Argument to string copy function is the address of the function 'strncpy_fn_dst', which is not a null-terminated string}}
573595
}
574596

575597
void strncpy_effects(char *x, char *y) {
@@ -680,8 +702,12 @@ void strncat_null_src(char *x) {
680702
strncat(x, NULL, 4); // expected-warning{{Null pointer passed as 2nd argument to string concatenation function}}
681703
}
682704

683-
void strncat_fn(char *x) {
684-
strncat(x, (char*)&strncat_fn, 4); // expected-warning{{Argument to string concatenation function is the address of the function 'strncat_fn', which is not a null-terminated string}}
705+
void strncat_fn_src(char *x) {
706+
strncat(x, (char*)&strncat_fn_src, 4); // expected-warning{{Argument to string concatenation function is the address of the function 'strncat_fn_src', which is not a null-terminated string}}
707+
}
708+
709+
void strncat_fn_dst(const char *x) {
710+
strncat((char*)&strncat_fn_dst, x, 4); // expected-warning{{Argument to string concatenation function is the address of the function 'strncat_fn_dst', which is not a null-terminated string}}
685711
}
686712

687713
void strncat_effects(char *y) {
@@ -921,6 +947,14 @@ int strcmp_null_argument(char *a) {
921947
return strcmp(a, b); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}}
922948
}
923949

950+
void strcmp_fn_r(char *x) {
951+
strcmp(x, (char*)&strcmp_null_argument); // expected-warning{{Argument to string comparison function is the address of the function 'strcmp_null_argument', which is not a null-terminated string}}
952+
}
953+
954+
void strcmp_fn_l(char *x) {
955+
strcmp((char*)&strcmp_null_argument, x); // expected-warning{{Argument to string comparison function is the address of the function 'strcmp_null_argument', which is not a null-terminated string}}
956+
}
957+
924958
//===----------------------------------------------------------------------===
925959
// strncmp()
926960
//===----------------------------------------------------------------------===

clang/test/Analysis/string.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,alpha.unix.cstring,debug.ExprInspection -verify %s
22

33
// Test functions that are called "memcpy" but aren't the memcpy
44
// we're looking for. Unfortunately, this test cannot be put into
55
// a namespace. The out-of-class weird memcpy needs to be recognized
66
// as a normal C function for the test to make sense.
77
typedef __typeof(sizeof(int)) size_t;
88
void *memcpy(void *, const void *, size_t);
9+
size_t strlen(const char *s);
910

1011
int sprintf(char *str, const char *format, ...);
1112
int snprintf(char *str, size_t size, const char *format, ...);
@@ -45,3 +46,10 @@ void log(const char* fmt, const Args&... args) {
4546
void test_gh_74269_no_crash() {
4647
log("%d", 1);
4748
}
49+
50+
struct TestNotNullTerm {
51+
void test1() {
52+
TestNotNullTerm * const &x = this;
53+
strlen((char *)&x); // expected-warning{{Argument to string length function is not a null-terminated string}}
54+
}
55+
};

0 commit comments

Comments
 (0)