79 changes: 68 additions & 11 deletions clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2023,13 +2023,6 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
{{EOFv, EOFv}, {0, UCharRangeMax}},
"an unsigned char value or EOF")));

// The getc() family of functions that returns either a char or an EOF.
addToFunctionSummaryMap(
{"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
Summary(NoEvalCall)
.Case({ReturnValueCondition(WithinRange,
{{EOFv, EOFv}, {0, UCharRangeMax}})},
ErrnoIrrelevant));
addToFunctionSummaryMap(
"getchar", Signature(ArgTypes{}, RetType{IntTy}),
Summary(NoEvalCall)
Expand Down Expand Up @@ -2139,7 +2132,17 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
std::move(GetenvSummary));
}

if (ModelPOSIX) {
if (!ModelPOSIX) {
// Without POSIX use of 'errno' is not specified (in these cases).
// Add these functions without 'errno' checks.
addToFunctionSummaryMap(
{"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
Summary(NoEvalCall)
.Case({ReturnValueCondition(WithinRange,
{{EOFv, EOFv}, {0, UCharRangeMax}})},
ErrnoIrrelevant)
.ArgConstraint(NotNull(ArgNo(0))));
} else {
const auto ReturnsZeroOrMinusOne =
ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))};
const auto ReturnsZero =
Expand Down Expand Up @@ -2231,6 +2234,63 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
.Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
.ArgConstraint(NotNull(ArgNo(0))));

std::optional<QualType> Off_tTy = lookupTy("off_t");
std::optional<RangeInt> Off_tMax = getMaxValue(Off_tTy);

// int fgetc(FILE *stream);
// 'getc' is the same as 'fgetc' but may be a macro
addToFunctionSummaryMap(
{"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
Summary(NoEvalCall)
.Case({ReturnValueCondition(WithinRange, {{0, UCharRangeMax}})},
ErrnoMustNotBeChecked, GenericSuccessMsg)
.Case({ReturnValueCondition(WithinRange, SingleValue(EOFv))},
ErrnoIrrelevant, GenericFailureMsg)
.ArgConstraint(NotNull(ArgNo(0))));

// int fputc(int c, FILE *stream);
// 'putc' is the same as 'fputc' but may be a macro
addToFunctionSummaryMap(
{"putc", "fputc"},
Signature(ArgTypes{IntTy, FilePtrTy}, RetType{IntTy}),
Summary(NoEvalCall)
.Case({ArgumentCondition(0, WithinRange, Range(0, UCharRangeMax)),
ReturnValueCondition(BO_EQ, ArgNo(0))},
ErrnoMustNotBeChecked, GenericSuccessMsg)
.Case({ArgumentCondition(0, OutOfRange, Range(0, UCharRangeMax)),
ReturnValueCondition(WithinRange, Range(0, UCharRangeMax))},
ErrnoMustNotBeChecked, GenericSuccessMsg)
.Case({ReturnValueCondition(WithinRange, SingleValue(EOFv))},
ErrnoNEZeroIrrelevant, GenericFailureMsg)
.ArgConstraint(NotNull(ArgNo(1))));

// char *fgets(char *restrict s, int n, FILE *restrict stream);
addToFunctionSummaryMap(
"fgets",
Signature(ArgTypes{CharPtrRestrictTy, IntTy, FilePtrRestrictTy},
RetType{CharPtrTy}),
Summary(NoEvalCall)
.Case({ReturnValueCondition(BO_EQ, ArgNo(0))},
ErrnoMustNotBeChecked, GenericSuccessMsg)
.Case({IsNull(Ret)}, ErrnoIrrelevant, GenericFailureMsg)
.ArgConstraint(NotNull(ArgNo(0)))
.ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax)))
.ArgConstraint(
BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))
.ArgConstraint(NotNull(ArgNo(2))));

// int fputs(const char *restrict s, FILE *restrict stream);
addToFunctionSummaryMap(
"fputs",
Signature(ArgTypes{ConstCharPtrRestrictTy, FilePtrRestrictTy},
RetType{IntTy}),
Summary(NoEvalCall)
.Case(ReturnsNonnegative, ErrnoMustNotBeChecked, GenericSuccessMsg)
.Case({ReturnValueCondition(WithinRange, SingleValue(EOFv))},
ErrnoNEZeroIrrelevant, GenericFailureMsg)
.ArgConstraint(NotNull(ArgNo(0)))
.ArgConstraint(NotNull(ArgNo(1))));

// int ungetc(int c, FILE *stream);
addToFunctionSummaryMap(
"ungetc", Signature(ArgTypes{IntTy, FilePtrTy}, RetType{IntTy}),
Expand All @@ -2250,9 +2310,6 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
0, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))
.ArgConstraint(NotNull(ArgNo(1))));

std::optional<QualType> Off_tTy = lookupTy("off_t");
std::optional<RangeInt> Off_tMax = getMaxValue(Off_tTy);

// int fseek(FILE *stream, long offset, int whence);
// FIXME: It can be possible to get the 'SEEK_' values (like EOFv) and use
// these for condition of arg 2.
Expand Down
108 changes: 48 additions & 60 deletions clang/test/AST/Interp/builtin-functions.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify
// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify
// RUN: %clang_cc1 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated
// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify
// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify
// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated
// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify
// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated
// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify=expected,both
// RUN: %clang_cc1 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify=expected,both
// RUN: %clang_cc1 -Wno-string-plus-int -verify=ref,both %s -Wno-constant-evaluated
// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify=expected,both
// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify=expected,both
// RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -verify=ref,both %s -Wno-constant-evaluated
// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter %s -verify=expected,both
// RUN: %clang_cc1 -triple avr -std=c++20 -Wno-string-plus-int -verify=ref,both %s -Wno-constant-evaluated


namespace strcmp {
Expand All @@ -23,23 +23,17 @@ namespace strcmp {
static_assert(__builtin_strcmp("abab\0banana", "abab") == 0, "");
static_assert(__builtin_strcmp("abab", "abab\0banana") == 0, "");
static_assert(__builtin_strcmp("abab\0banana", "abab\0canada") == 0, "");
static_assert(__builtin_strcmp(0, "abab") == 0, ""); // expected-error {{not an integral constant}} \
// expected-note {{dereferenced null}} \
// expected-note {{in call to}} \
// ref-error {{not an integral constant}} \
// ref-note {{dereferenced null}}
static_assert(__builtin_strcmp("abab", 0) == 0, ""); // expected-error {{not an integral constant}} \
// expected-note {{dereferenced null}} \
// expected-note {{in call to}} \
// ref-error {{not an integral constant}} \
// ref-note {{dereferenced null}}
static_assert(__builtin_strcmp(0, "abab") == 0, ""); // both-error {{not an integral constant}} \
// both-note {{dereferenced null}} \
// expected-note {{in call to}}
static_assert(__builtin_strcmp("abab", 0) == 0, ""); // both-error {{not an integral constant}} \
// both-note {{dereferenced null}} \
// expected-note {{in call to}}

static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar) == -1, "");
static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0, ""); // expected-error {{not an integral constant}} \
// expected-note {{dereferenced one-past-the-end}} \
// expected-note {{in call to}} \
// ref-error {{not an integral constant}} \
// ref-note {{dereferenced one-past-the-end}}
static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0, ""); // both-error {{not an integral constant}} \
// both-note {{dereferenced one-past-the-end}} \
// expected-note {{in call to}}
}

/// Copied from constant-expression-cxx11.cpp
Expand Down Expand Up @@ -69,41 +63,27 @@ constexpr const char *a = "foo\0quux";
static_assert(check(b), "");
static_assert(check(c), "");

constexpr int over1 = __builtin_strlen(a + 9); // expected-error {{constant expression}} \
// expected-note {{one-past-the-end}} \
// expected-note {{in call to}} \
// ref-error {{constant expression}} \
// ref-note {{one-past-the-end}}
constexpr int over2 = __builtin_strlen(b + 9); // expected-error {{constant expression}} \
// expected-note {{one-past-the-end}} \
// expected-note {{in call to}} \
// ref-error {{constant expression}} \
// ref-note {{one-past-the-end}}
constexpr int over3 = __builtin_strlen(c + 9); // expected-error {{constant expression}} \
// expected-note {{one-past-the-end}} \
// expected-note {{in call to}} \
// ref-error {{constant expression}} \
// ref-note {{one-past-the-end}}

constexpr int under1 = __builtin_strlen(a - 1); // expected-error {{constant expression}} \
// expected-note {{cannot refer to element -1}} \
// ref-error {{constant expression}} \
// ref-note {{cannot refer to element -1}}
constexpr int under2 = __builtin_strlen(b - 1); // expected-error {{constant expression}} \
// expected-note {{cannot refer to element -1}} \
// ref-error {{constant expression}} \
// ref-note {{cannot refer to element -1}}
constexpr int under3 = __builtin_strlen(c - 1); // expected-error {{constant expression}} \
// expected-note {{cannot refer to element -1}} \
// ref-error {{constant expression}} \
// ref-note {{cannot refer to element -1}}
constexpr int over1 = __builtin_strlen(a + 9); // both-error {{constant expression}} \
// both-note {{one-past-the-end}} \
// expected-note {{in call to}}
constexpr int over2 = __builtin_strlen(b + 9); // both-error {{constant expression}} \
// both-note {{one-past-the-end}} \
// expected-note {{in call to}}
constexpr int over3 = __builtin_strlen(c + 9); // both-error {{constant expression}} \
// both-note {{one-past-the-end}} \
// expected-note {{in call to}}

constexpr int under1 = __builtin_strlen(a - 1); // both-error {{constant expression}} \
// both-note {{cannot refer to element -1}}
constexpr int under2 = __builtin_strlen(b - 1); // both-error {{constant expression}} \
// both-note {{cannot refer to element -1}}
constexpr int under3 = __builtin_strlen(c - 1); // both-error {{constant expression}} \
// both-note {{cannot refer to element -1}}

constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator.
constexpr int bad = __builtin_strlen(d); // expected-error {{constant expression}} \
// expected-note {{one-past-the-end}} \
// expected-note {{in call to}} \
// ref-error {{constant expression}} \
// ref-note {{one-past-the-end}}
constexpr int bad = __builtin_strlen(d); // both-error {{constant expression}} \
// both-note {{one-past-the-end}} \
// expected-note {{in call to}}
}

namespace nan {
Expand All @@ -115,8 +95,7 @@ namespace nan {
// expected-error@-2 {{must be initialized by a constant expression}}
#endif

constexpr double NaN3 = __builtin_nan("foo"); // expected-error {{must be initialized by a constant expression}} \
// ref-error {{must be initialized by a constant expression}}
constexpr double NaN3 = __builtin_nan("foo"); // both-error {{must be initialized by a constant expression}}
constexpr float NaN4 = __builtin_nanf("");
//constexpr long double NaN5 = __builtin_nanf128("");

Expand All @@ -126,8 +105,7 @@ namespace nan {

/// FIXME: Current interpreter misses diagnostics.
constexpr char f2[] = {'0', 'x', 'A', 'E'}; /// No trailing 0 byte.
constexpr double NaN7 = __builtin_nan(f2); // ref-error {{must be initialized by a constant expression}} \
// expected-error {{must be initialized by a constant expression}} \
constexpr double NaN7 = __builtin_nan(f2); // both-error {{must be initialized by a constant expression}} \
// expected-note {{read of dereferenced one-past-the-end pointer}} \
// expected-note {{in call to}}
static_assert(!__builtin_issignaling(__builtin_nan("")), "");
Expand Down Expand Up @@ -363,3 +341,13 @@ namespace ffs {
char ffs6[__builtin_ffsl(0x10L) == 5 ? 1 : -1];
char ffs7[__builtin_ffsll(0x100LL) == 9 ? 1 : -1];
}

namespace EhReturnDataRegno {
void test11(int X) {
switch (X) {
case __builtin_eh_return_data_regno(0): // constant foldable.
break;
}
__builtin_eh_return_data_regno(X); // both-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}}
}
}
2 changes: 2 additions & 0 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ namespace PointerComparison {
}

namespace SizeOf {
static_assert(alignof(char&) == 1, "");

constexpr int soint = sizeof(int);
constexpr int souint = sizeof(unsigned int);
static_assert(soint == souint, "");
Expand Down
4 changes: 4 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
// RUN: %clang_cc1 -verify=ref -std=c++20 %s
// RUN: %clang_cc1 -verify=ref -triple i686 %s

/// Used to crash.
struct Empty {};
constexpr Empty e = {Empty()};

struct BoolPair {
bool first;
bool second;
Expand Down
22 changes: 8 additions & 14 deletions clang/test/AST/Interp/switch.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -std=c++17 -fexperimental-new-constant-interpreter -verify %s
// RUN: %clang_cc1 -std=c++17 -verify=ref %s
// RUN: %clang_cc1 -std=c++17 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -std=c++17 -verify=ref,both %s

constexpr bool isEven(int a) {
bool v = false;
Expand Down Expand Up @@ -75,20 +75,14 @@ constexpr int test(int val) {
}
static_assert(test(1) == 100, "");

constexpr int bad(int val) { return val / 0; } // expected-warning {{division by zero}} \
// ref-warning {{division by zero}}
constexpr int another_test(int val) { // expected-note {{declared here}} \
// ref-note {{declared here}}
constexpr int bad(int val) { return val / 0; } // both-warning {{division by zero}}
constexpr int another_test(int val) { // both-note {{declared here}}
switch (val) {
case bad(val): return 100; // expected-error {{case value is not a constant expression}} \
// expected-note {{cannot be used in a constant expression}} \
// ref-error {{case value is not a constant expression}} \
// ref-note {{cannot be used in a constant expression}}
case bad(val): return 100; // both-error {{case value is not a constant expression}} \
// both-note {{cannot be used in a constant expression}}
default: return -1;
}
return 0;
}
static_assert(another_test(1) == 100, ""); // expected-error {{static assertion failed}} \
// expected-note {{evaluates to}} \
// ref-error {{static assertion failed}} \
// ref-note {{evaluates to}}
static_assert(another_test(1) == 100, ""); // both-error {{static assertion failed}} \
// both-note {{evaluates to}}
15 changes: 14 additions & 1 deletion clang/test/Analysis/Inputs/std-c-library-functions-POSIX.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ typedef unsigned long int pthread_t;
typedef unsigned long time_t;
typedef unsigned long clockid_t;
typedef __INT64_TYPE__ off64_t;
typedef __INT64_TYPE__ fpos_t;

typedef struct {
int a;
Expand Down Expand Up @@ -42,9 +43,22 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode);
FILE *tmpfile(void);
FILE *freopen(const char *restrict pathname, const char *restrict mode,
FILE *restrict stream);
FILE *fdopen(int fd, const char *mode);
int fclose(FILE *stream);
int putc(int c, FILE *stream);
int fputc(int c, FILE *stream);
char *fgets(char *restrict s, int n, FILE *restrict stream);
int fputs(const char *restrict s, FILE *restrict stream);
int fseek(FILE *stream, long offset, int whence);
int fgetpos(FILE *restrict stream, fpos_t *restrict pos);
int fsetpos(FILE *stream, const fpos_t *pos);
int fflush(FILE *stream);
long ftell(FILE *stream);
int fileno(FILE *stream);
void rewind(FILE *stream);
void clearerr(FILE *stream);
int feof(FILE *stream);
int ferror(FILE *stream);
long a64l(const char *str64);
char *l64a(long value);
int open(const char *path, int oflag, ...);
Expand Down Expand Up @@ -100,7 +114,6 @@ int pclose(FILE *stream);
int close(int fildes);
long fpathconf(int fildes, int name);
long pathconf(const char *path, int name);
FILE *fdopen(int fd, const char *mode);
void rewinddir(DIR *dir);
void seekdir(DIR *dirp, long loc);
int rand_r(unsigned int *seedp);
Expand Down
16 changes: 14 additions & 2 deletions clang/test/Analysis/std-c-library-functions-POSIX.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,22 @@
// CHECK: Loaded summary for: FILE *popen(const char *command, const char *type)
// CHECK: Loaded summary for: int fclose(FILE *stream)
// CHECK: Loaded summary for: int pclose(FILE *stream)
// CHECK: Loaded summary for: int getc(FILE *)
// CHECK: Loaded summary for: int fgetc(FILE *)
// CHECK: Loaded summary for: int putc(int c, FILE *stream)
// CHECK: Loaded summary for: int fputc(int c, FILE *stream)
// CHECK: Loaded summary for: char *fgets(char *restrict s, int n, FILE *restrict stream)
// CHECK: Loaded summary for: int fputs(const char *restrict s, FILE *restrict stream)
// CHECK: Loaded summary for: int fseek(FILE *stream, long offset, int whence)
// CHECK: Loaded summary for: int fseeko(FILE *stream, off_t offset, int whence)
// CHECK: Loaded summary for: off_t ftello(FILE *stream)
// CHECK: Loaded summary for: int fgetpos(FILE *restrict stream, fpos_t *restrict pos)
// CHECK: Loaded summary for: int fsetpos(FILE *stream, const fpos_t *pos)
// CHECK: Loaded summary for: int fflush(FILE *stream)
// CHECK: Loaded summary for: long ftell(FILE *stream)
// CHECK: Loaded summary for: int fileno(FILE *stream)
// CHECK: Loaded summary for: void rewind(FILE *stream)
// CHECK: Loaded summary for: void clearerr(FILE *stream)
// CHECK: Loaded summary for: int feof(FILE *stream)
// CHECK: Loaded summary for: int ferror(FILE *stream)
// CHECK: Loaded summary for: long a64l(const char *str64)
// CHECK: Loaded summary for: char *l64a(long value)
// CHECK: Loaded summary for: int open(const char *path, int oflag, ...)
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Analysis/std-c-library-functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@
// CHECK-NEXT: Loaded summary for: int toupper(int)
// CHECK-NEXT: Loaded summary for: int tolower(int)
// CHECK-NEXT: Loaded summary for: int toascii(int)
// CHECK-NEXT: Loaded summary for: int getc(FILE *)
// CHECK-NEXT: Loaded summary for: int fgetc(FILE *)
// CHECK-NEXT: Loaded summary for: int getchar(void)
// CHECK-NEXT: Loaded summary for: unsigned int fread(void *restrict, size_t, size_t, FILE *restrict)
// CHECK-NEXT: Loaded summary for: unsigned int fwrite(const void *restrict, size_t, size_t, FILE *restrict)
Expand All @@ -63,6 +61,8 @@
// CHECK-NEXT: Loaded summary for: ssize_t getline(char **restrict, size_t *restrict, FILE *restrict)
// CHECK-NEXT: Loaded summary for: ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict)
// CHECK-NEXT: Loaded summary for: char *getenv(const char *)
// CHECK-NEXT: Loaded summary for: int getc(FILE *)
// CHECK-NEXT: Loaded summary for: int fgetc(FILE *)

#include "Inputs/std-c-library-functions.h"

Expand Down
26 changes: 0 additions & 26 deletions clang/test/Analysis/stream-error.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,32 +491,6 @@ void error_ftello(void) {
fclose(F);
}

void error_fflush_after_fclose(void) {
FILE *F = tmpfile();
int Ret;
fflush(NULL); // no-warning
if (!F)
return;
if ((Ret = fflush(F)) != 0)
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
fclose(F);
fflush(F); // expected-warning {{Stream might be already closed}}
}

void error_fflush_on_open_failed_stream(void) {
FILE *F = tmpfile();
if (!F) {
fflush(F); // no-warning
return;
}
fclose(F);
}

void error_fflush_on_unknown_stream(FILE *F) {
fflush(F); // no-warning
fclose(F); // no-warning
}

void error_fflush_on_non_null_stream_clear_error_states(void) {
FILE *F0 = tmpfile(), *F1 = tmpfile();
// `fflush` clears a non-EOF stream's error state.
Expand Down
120 changes: 99 additions & 21 deletions clang/test/Analysis/stream-noopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,95 @@ void test_fwrite(FILE *F) {
clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}}
}

void test_fgetc(FILE *F) {
int Ret = fgetc(F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
if (Ret != EOF) {
if (errno) {} // expected-warning {{undefined}}
} else {
clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}}
// expected-warning@-1 {{FALSE}}
}
clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}}
}

void test_fputc(FILE *F) {
int Ret = fputc('a', F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
if (Ret != EOF) {
clang_analyzer_eval(Ret == 'a'); // expected-warning {{TRUE}}
if (errno) {} // expected-warning {{undefined}}
} else {
clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}}
}
clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}}
}

void test_fgets(char *Buf, int N, FILE *F) {
char *Ret = fgets(Buf, N, F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
clang_analyzer_eval(Buf != NULL); // expected-warning {{TRUE}}
clang_analyzer_eval(N >= 0); // expected-warning {{TRUE}}
if (Ret == Buf) {
if (errno) {} // expected-warning {{undefined}}
} else {
clang_analyzer_eval(Ret == 0); // expected-warning {{TRUE}}
clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}}
// expected-warning@-1 {{FALSE}}
}
clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}}

char Buf1[10];
Ret = fgets(Buf1, 11, F); // expected-warning {{The 1st argument to 'fgets' is a buffer with size 10}}
}

void test_fgets_bufsize(FILE *F) {
char Buf[10];
fgets(Buf, 11, F); // expected-warning {{The 1st argument to 'fgets' is a buffer with size 10}}
}

void test_fputs(char *Buf, FILE *F) {
int Ret = fputs(Buf, F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
clang_analyzer_eval(Buf != NULL); // expected-warning {{TRUE}}
if (Ret >= 0) {
if (errno) {} // expected-warning {{undefined}}
} else {
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}}
}
clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}}
}

void test_ungetc(FILE *F) {
int Ret = ungetc('X', F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
if (Ret == 'X') {
if (errno) {} // expected-warning {{undefined}}
} else {
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}}
}
clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}}
}

void test_ungetc_EOF(FILE *F, int C) {
int Ret = ungetc(EOF, F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}}
Ret = ungetc(C, F);
if (Ret == EOF) {
clang_analyzer_eval(C == EOF); // expected-warning {{TRUE}}
// expected-warning@-1{{FALSE}}
}
}

void test_fclose(FILE *F) {
int Ret = fclose(F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
Expand Down Expand Up @@ -138,28 +227,17 @@ void test_rewind(FILE *F) {
rewind(F);
}

void test_ungetc(FILE *F) {
int Ret = ungetc('X', F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
if (Ret == 'X') {
if (errno) {} // expected-warning {{undefined}}
} else {
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}}
}
clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}}
clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}}
}

void test_ungetc_EOF(FILE *F, int C) {
int Ret = ungetc(EOF, F);
clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}}
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}}
Ret = ungetc(C, F);
void test_fflush(FILE *F) {
errno = 0;
int Ret = fflush(F);
clang_analyzer_eval(F != NULL); // expected-warning{{TRUE}}
// expected-warning@-1{{FALSE}}
if (Ret == EOF) {
clang_analyzer_eval(C == EOF); // expected-warning {{TRUE}}
// expected-warning@-1{{FALSE}}
clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
} else {
clang_analyzer_eval(Ret == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(errno == 0); // expected-warning{{TRUE}}
// expected-warning@-1{{FALSE}}
}
}

Expand Down
25 changes: 24 additions & 1 deletion clang/test/Analysis/stream.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.unix.Stream -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s

#include "Inputs/system-header-simulator.h"

void clang_analyzer_eval(int);

void check_fread(void) {
FILE *fp = tmpfile();
fread(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}
Expand Down Expand Up @@ -316,3 +318,24 @@ void check_leak_noreturn_2(void) {
} // expected-warning {{Opened stream never closed. Potential resource leak}}
// FIXME: This warning should be placed at the `return` above.
// See https://reviews.llvm.org/D83120 about details.

void fflush_after_fclose(void) {
FILE *F = tmpfile();
int Ret;
fflush(NULL); // no-warning
if (!F)
return;
if ((Ret = fflush(F)) != 0)
clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
fclose(F);
fflush(F); // expected-warning {{Stream might be already closed}}
}

void fflush_on_open_failed_stream(void) {
FILE *F = tmpfile();
if (!F) {
fflush(F); // no-warning
return;
}
fclose(F);
}
4 changes: 4 additions & 0 deletions clang/test/Driver/fbasic-block-sections.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
// RUN: %clang -### --target=x86_64 -fbasic-block-sections=all %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-ALL %s
// RUN: %clang -### --target=x86_64 -fbasic-block-sections=list=%s %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-LIST %s
// RUN: %clang -### --target=x86_64 -fbasic-block-sections=labels %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-LABELS %s
// RUN: %clang -### --target=aarch64 -fbasic-block-sections=none %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-NONE %s
// RUN: %clang -### --target=aarch64 -fbasic-block-sections=list=%s %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-LIST %s
// RUN: %clang -### --target=aarch64 -fbasic-block-sections=labels %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-LABELS %s
// RUN: not %clang -### --target=aarch64 -fbasic-block-sections=all %s -S 2>&1 | FileCheck -check-prefix=CHECK-INVALID-VALUE %s
// RUN: not %clang -c --target=arm-unknown-linux -fbasic-block-sections=all %s -S 2>&1 | FileCheck -check-prefix=CHECK-TRIPLE %s
// RUN: %clang -### --target=arm-unknown-linux -fbasic-block-sections=all -fbasic-block-sections=none %s -S 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-NOOPT %s
Expand Down
8 changes: 8 additions & 0 deletions clang/test/Driver/linker-wrapper-image.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
// RUN: -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP,OPENMP-ELF
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run -r --host-triple=x86_64-unknown-linux-gnu \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP-ELF,OPENMP-REL
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP,OPENMP-COFF

Expand All @@ -19,6 +21,8 @@
// OPENMP-COFF: @__start_omp_offloading_entries = weak_odr hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "omp_offloading_entries$OA"
// OPENMP-COFF-NEXT: @__stop_omp_offloading_entries = weak_odr hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "omp_offloading_entries$OZ"

// OPENMP-REL: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading.relocatable", align 8

// OPENMP: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading", align 8
// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr getelementptr inbounds ([[[BEGIN:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr getelementptr inbounds ([[[END:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }]
// OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }
Expand All @@ -42,6 +46,8 @@
// RUN: -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-ELF
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run -r --host-triple=x86_64-unknown-linux-gnu \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-ELF
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-COFF

Expand Down Expand Up @@ -140,6 +146,8 @@
// RUN: -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-ELF
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu -r \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-ELF
// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-COFF

Expand Down
32 changes: 29 additions & 3 deletions clang/test/Driver/linker-wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,36 @@ __attribute__((visibility("protected"), used)) int x;
// RUN: --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
// RUN: --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
// RUN: llvm-ar rcs %t.a %t.o
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld.lld -- -r --whole-archive %t.a --no-whole-archive \
// RUN: --linker-path=/usr/bin/ld.lld -- -r %t.o \
// RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK

// RELOCATABLE-LINK-NOT: clang{{.*}} -o {{.*}}.img --target=x86_64-unknown-linux-gnu
// RELOCATABLE-LINK: clang{{.*}} -o {{.*}}.img --target=x86_64-unknown-linux-gnu
// RELOCATABLE-LINK: /usr/bin/ld.lld{{.*}}-r
// RELOCATABLE-LINK: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading

// RUN: clang-offload-packager -o %t.out \
// RUN: --image=file=%t.elf.o,kind=hip,triple=amdgcn-amd-amdhsa,arch=gfx90a \
// RUN: --image=file=%t.elf.o,kind=hip,triple=amdgcn-amd-amdhsa,arch=gfx90a
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld.lld -- -r %t.o \
// RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK-HIP

// RELOCATABLE-LINK-HIP: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa
// RELOCATABLE-LINK-HIP: clang-offload-bundler{{.*}} -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx90a -input=/dev/null -input={{.*}} -output={{.*}}
// RELOCATABLE-LINK-HIP: /usr/bin/ld.lld{{.*}}-r
// RELOCATABLE-LINK-HIP: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading

// RUN: clang-offload-packager -o %t.out \
// RUN: --image=file=%t.elf.o,kind=cuda,triple=nvptx64-nvidia-cuda,arch=sm_89 \
// RUN: --image=file=%t.elf.o,kind=cuda,triple=nvptx64-nvidia-cuda,arch=sm_89
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld.lld -- -r %t.o \
// RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK-CUDA

// RELOCATABLE-LINK-CUDA: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda
// RELOCATABLE-LINK-CUDA: fatbinary{{.*}} -64 --create {{.*}}.fatbin --image=profile=sm_89,file={{.*}}.img
// RELOCATABLE-LINK-CUDA: /usr/bin/ld.lld{{.*}}-r
// RELOCATABLE-LINK-CUDA: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading
3 changes: 3 additions & 0 deletions clang/test/Format/dump-config-objc-stdin.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// RUN: clang-format -assume-filename=foo.m -dump-config | FileCheck %s

// RUN: clang-format -dump-config - < %s | FileCheck %s

// CHECK: Language: ObjC

@interface Foo
@end
10 changes: 2 additions & 8 deletions clang/test/Format/verbose.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
// RUN: clang-format %s 2> %t.stderr
// RUN: clang-format -verbose 2> %t.stderr
// RUN: not grep "Formatting" %t.stderr
// RUN: clang-format %s -verbose 2> %t.stderr
// RUN: grep -E "Formatting (.*)verbose.cpp(.*)" %t.stderr
// RUN: clang-format %s -verbose=false 2> %t.stderr
// RUN: not grep "Formatting" %t.stderr

int a;
// RUN: clang-format %s 2> %t.stderr
// RUN: clang-format %s 2> %t.stderr
// RUN: not grep "Formatting" %t.stderr
// RUN: clang-format %s -verbose 2> %t.stderr
// RUN: grep -E "Formatting (.*)verbose.cpp(.*)" %t.stderr
Expand Down
29 changes: 29 additions & 0 deletions clang/test/Frontend/verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,32 @@ unexpected b; // expected-error@33 1-1 {{unknown type}}
#endif

#endif

#ifdef TEST10
// RUN: not %clang_cc1 -DTEST10 -verify=foo %s 2>&1 | FileCheck -check-prefix=CHECK10 %s

// CHECK10: error: no expected directives found: consider use of 'foo-no-diagnostics'
#endif

#ifdef TEST11
// RUN: not %clang_cc1 -DTEST11 -verify=foo %s 2>&1 | FileCheck -check-prefix=CHECK11 %s

// foo-no-diagnostics
// foo-note {{}}

// CHECK11: error: 'foo-error' diagnostics seen but not expected:
// CHECK11-NEXT: Line 201: expected directive cannot follow 'foo-no-diagnostics' directive
// CHECK11-NEXT: 1 error generated.
#endif

#ifdef TEST12
// RUN: not %clang_cc1 -DTEST12 -verify=foo %s 2>&1 | FileCheck -check-prefix=CHECK12 %s

#warning X
// foo-warning@-1 {{X}}
// foo-no-diagnostics

// CHECK12: error: 'foo-error' diagnostics seen but not expected:
// CHECK12-NEXT: Line 213: 'foo-no-diagnostics' directive cannot follow other expected directives
// CHECK12-NEXT: 1 error generated.
#endif
16 changes: 8 additions & 8 deletions clang/test/Headers/__clang_hip_cmath.hip
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,27 @@ extern "C" __device__ float test_fabs_f32(float x) {

// DEFAULT-LABEL: @test_sin_f32(
// DEFAULT-NEXT: entry:
// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR8:[0-9]+]]
// DEFAULT-NEXT: ret float [[CALL_I_I]]
// DEFAULT-NEXT: [[CALL_I1:%.*]] = tail call contract noundef float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR8:[0-9]+]]
// DEFAULT-NEXT: ret float [[CALL_I1]]
//
// FINITEONLY-LABEL: @test_sin_f32(
// FINITEONLY-NEXT: entry:
// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8:[0-9]+]]
// FINITEONLY-NEXT: ret float [[CALL_I_I]]
// FINITEONLY-NEXT: [[CALL_I1:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8:[0-9]+]]
// FINITEONLY-NEXT: ret float [[CALL_I1]]
//
extern "C" __device__ float test_sin_f32(float x) {
return sin(x);
}

// DEFAULT-LABEL: @test_cos_f32(
// DEFAULT-NEXT: entry:
// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR8]]
// DEFAULT-NEXT: ret float [[CALL_I_I]]
// DEFAULT-NEXT: [[CALL_I1:%.*]] = tail call contract noundef float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR8]]
// DEFAULT-NEXT: ret float [[CALL_I1]]
//
// FINITEONLY-LABEL: @test_cos_f32(
// FINITEONLY-NEXT: entry:
// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8]]
// FINITEONLY-NEXT: ret float [[CALL_I_I]]
// FINITEONLY-NEXT: [[CALL_I1:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8]]
// FINITEONLY-NEXT: ret float [[CALL_I1]]
//
extern "C" __device__ float test_cos_f32(float x) {
return cos(x);
Expand Down
896 changes: 448 additions & 448 deletions clang/test/Headers/__clang_hip_math.hip

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions clang/test/OpenMP/bug69085.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -verify -O0 -fopenmp-simd %s

int k[-1]; // expected-error {{'k' declared as an array with a negative size}}

void foo() {
#pragma omp task depend(inout: k [:])
{
k[0] = 1;
}
}
1 change: 1 addition & 0 deletions clang/test/SemaCXX/cxx1z-copy-omission.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++1z -verify -Wno-unused %s
// RUN: %clang_cc1 -std=c++1z -verify -Wno-unused %s -fexperimental-new-constant-interpreter

struct Noncopyable {
Noncopyable();
Expand Down
3 changes: 2 additions & 1 deletion clang/test/SemaCXX/cxx20-using-enum.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s -fexperimental-new-constant-interpreter

// p1099 'using enum ELABORATED-ENUM-SPECIFIER ;'

Expand Down
10 changes: 10 additions & 0 deletions clang/test/SemaCXX/cxx2b-deducing-this.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,3 +636,13 @@ struct D {
}
};
}

namespace GH80971 {
struct S {
auto f(this auto self...) { }
};

int bug() {
S{}.f(0);
}
}
49 changes: 25 additions & 24 deletions clang/tools/clang-format/ClangFormat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ class ClangFormatDiagConsumer : public DiagnosticConsumer {
};

// Returns true on error.
static bool format(StringRef FileName, bool IsSTDIN) {
static bool format(StringRef FileName) {
const bool IsSTDIN = FileName == "-";
if (!OutputXML && Inplace && IsSTDIN) {
errs() << "error: cannot use -i when reading from stdin.\n";
return false;
Expand Down Expand Up @@ -545,24 +546,25 @@ static void PrintVersion(raw_ostream &OS) {
}

// Dump the configuration.
static int dumpConfig(bool IsSTDIN) {
static int dumpConfig() {
std::unique_ptr<llvm::MemoryBuffer> Code;

// `FileNames` must have at least "-" in it even if no file was specified.
assert(!FileNames.empty());

// Read in the code in case the filename alone isn't enough to detect the
// language.
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
MemoryBuffer::getFileOrSTDIN(FileNames[0]);
if (std::error_code EC = CodeOrErr.getError()) {
llvm::errs() << EC.message() << "\n";
return 1;
// We can't read the code to detect the language if there's no file name.
if (!FileNames.empty()) {
// Read in the code in case the filename alone isn't enough to detect the
// language.
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
MemoryBuffer::getFileOrSTDIN(FileNames[0]);
if (std::error_code EC = CodeOrErr.getError()) {
llvm::errs() << EC.message() << "\n";
return 1;
}
Code = std::move(CodeOrErr.get());
}
Code = std::move(CodeOrErr.get());

llvm::Expected<clang::format::FormatStyle> FormatStyle =
clang::format::getStyle(Style, IsSTDIN ? AssumeFileName : FileNames[0],
clang::format::getStyle(Style,
FileNames.empty() || FileNames[0] == "-"
? AssumeFileName
: FileNames[0],
FallbackStyle, Code ? Code->getBuffer() : "");
if (!FormatStyle) {
llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n";
Expand Down Expand Up @@ -682,11 +684,8 @@ int main(int argc, const char **argv) {
return 0;
}

if (FileNames.empty())
FileNames.push_back("-");

if (DumpConfig)
return dumpConfig(FileNames[0] == "-");
return dumpConfig();

if (!Files.empty()) {
std::ifstream ExternalFileOfFiles{std::string(Files)};
Expand All @@ -699,7 +698,10 @@ int main(int argc, const char **argv) {
errs() << "Clang-formating " << LineNo << " files\n";
}

if (FileNames.size() != 1 &&
if (FileNames.empty())
return clang::format::format("-");

if (FileNames.size() > 1 &&
(!Offsets.empty() || !Lengths.empty() || !LineRanges.empty())) {
errs() << "error: -offset, -length and -lines can only be used for "
"single file.\n";
Expand All @@ -709,14 +711,13 @@ int main(int argc, const char **argv) {
unsigned FileNo = 1;
bool Error = false;
for (const auto &FileName : FileNames) {
const bool IsSTDIN = FileName == "-";
if (!IsSTDIN && isIgnored(FileName))
if (isIgnored(FileName))
continue;
if (Verbose) {
errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] "
<< FileName << "\n";
}
Error |= clang::format::format(FileName, IsSTDIN);
Error |= clang::format::format(FileName);
}
return Error ? 1 : 0;
}
77 changes: 70 additions & 7 deletions clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,70 @@ Expected<std::string> findProgram(StringRef Name, ArrayRef<StringRef> Paths) {
return *Path;
}

/// Returns the hashed value for a constant string.
std::string getHash(StringRef Str) {
llvm::MD5 Hasher;
llvm::MD5::MD5Result Hash;
Hasher.update(Str);
Hasher.final(Hash);
return llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
}

/// Renames offloading entry sections in a relocatable link so they do not
/// conflict with a later link job.
Error relocateOffloadSection(const ArgList &Args, StringRef Output) {
llvm::Triple Triple(
Args.getLastArgValue(OPT_host_triple_EQ, sys::getDefaultTargetTriple()));
if (Triple.isOSWindows())
return createStringError(
inconvertibleErrorCode(),
"Relocatable linking is not supported on COFF targets");

Expected<std::string> ObjcopyPath =
findProgram("llvm-objcopy", {getMainExecutable("llvm-objcopy")});
if (!ObjcopyPath)
return ObjcopyPath.takeError();

// Use the linker output file to get a unique hash. This creates a unique
// identifier to rename the sections to that is deterministic to the contents.
auto BufferOrErr = DryRun ? MemoryBuffer::getMemBuffer("")
: MemoryBuffer::getFileOrSTDIN(Output);
if (!BufferOrErr)
return createStringError(inconvertibleErrorCode(), "Failed to open %s",
Output.str().c_str());
std::string Suffix = "_" + getHash((*BufferOrErr)->getBuffer());

SmallVector<StringRef> ObjcopyArgs = {
*ObjcopyPath,
Output,
};

// Remove the old .llvm.offloading section to prevent further linking.
ObjcopyArgs.emplace_back("--remove-section");
ObjcopyArgs.emplace_back(".llvm.offloading");
for (StringRef Prefix : {"omp", "cuda", "hip"}) {
auto Section = (Prefix + "_offloading_entries").str();
// Rename the offloading entires to make them private to this link unit.
ObjcopyArgs.emplace_back("--rename-section");
ObjcopyArgs.emplace_back(
Args.MakeArgString(Section + "=" + Section + Suffix));

// Rename the __start_ / __stop_ symbols appropriately to iterate over the
// newly renamed section containing the offloading entries.
ObjcopyArgs.emplace_back("--redefine-sym");
ObjcopyArgs.emplace_back(Args.MakeArgString("__start_" + Section + "=" +
"__start_" + Section + Suffix));
ObjcopyArgs.emplace_back("--redefine-sym");
ObjcopyArgs.emplace_back(Args.MakeArgString("__stop_" + Section + "=" +
"__stop_" + Section + Suffix));
}

if (Error Err = executeCommands(*ObjcopyPath, ObjcopyArgs))
return Err;

return Error::success();
}

/// Runs the wrapped linker job with the newly created input.
Error runLinker(ArrayRef<StringRef> Files, const ArgList &Args) {
llvm::TimeTraceScope TimeScope("Execute host linker");
Expand All @@ -265,6 +329,10 @@ Error runLinker(ArrayRef<StringRef> Files, const ArgList &Args) {
LinkerArgs.push_back(Arg);
if (Error Err = executeCommands(LinkerPath, LinkerArgs))
return Err;

if (Args.hasArg(OPT_relocatable))
return relocateOffloadSection(Args, ExecutableName);

return Error::success();
}

Expand Down Expand Up @@ -910,7 +978,8 @@ wrapDeviceImages(ArrayRef<std::unique_ptr<MemoryBuffer>> Buffers,
case OFK_OpenMP:
if (Error Err = offloading::wrapOpenMPBinaries(
M, BuffersToWrap,
offloading::getOffloadEntryArray(M, "omp_offloading_entries")))
offloading::getOffloadEntryArray(M, "omp_offloading_entries"),
/*Suffix=*/"", /*Relocatable=*/Args.hasArg(OPT_relocatable)))
return std::move(Err);
break;
case OFK_Cuda:
Expand Down Expand Up @@ -1356,12 +1425,6 @@ Expected<SmallVector<SmallVector<OffloadFile>>>
getDeviceInput(const ArgList &Args) {
llvm::TimeTraceScope TimeScope("ExtractDeviceCode");

// If the user is requesting a reloctable link we ignore the device code. The
// actual linker will merge the embedded device code sections so they can be
// linked when the executable is finally created.
if (Args.hasArg(OPT_relocatable))
return SmallVector<SmallVector<OffloadFile>>{};

StringRef Root = Args.getLastArgValue(OPT_sysroot_EQ);
SmallVector<StringRef> LibraryPaths;
for (const opt::Arg *Arg : Args.filtered(OPT_library_path, OPT_libpath))
Expand Down
5 changes: 3 additions & 2 deletions clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,9 @@ def version : Flag<["--", "-"], "version">, Flags<[HelpHidden]>, Alias<v>;
def whole_archive : Flag<["--", "-"], "whole-archive">, Flags<[HelpHidden]>;
def no_whole_archive : Flag<["--", "-"], "no-whole-archive">, Flags<[HelpHidden]>;

def relocatable : Flag<["--", "-"], "relocatable">, Flags<[HelpHidden]>;
def r : Flag<["-"], "r">, Alias<relocatable>, Flags<[HelpHidden]>;
def relocatable : Flag<["--", "-"], "relocatable">,
HelpText<"Link device code to create a relocatable offloading application">;
def r : Flag<["-"], "r">, Alias<relocatable>;

// link.exe-style linker options.
def out : Joined<["/", "-", "/?", "-?"], "out:">, Flags<[HelpHidden]>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -770,12 +770,17 @@ constexpr bool operator!=(const optional<T> &lhs, const optional<U> &rhs);
template <typename T>
constexpr bool operator==(const optional<T> &opt, nullopt_t);
// C++20 and later do not define the following overloads because they are
// provided by rewritten candidates instead.
#if __cplusplus < 202002L
template <typename T>
constexpr bool operator==(nullopt_t, const optional<T> &opt);
template <typename T>
constexpr bool operator!=(const optional<T> &opt, nullopt_t);
template <typename T>
constexpr bool operator!=(nullopt_t, const optional<T> &opt);
#endif // __cplusplus < 202002L
template <typename T, typename U>
constexpr bool operator==(const optional<T> &opt, const U &value);
Expand Down Expand Up @@ -1289,6 +1294,15 @@ class UncheckedOptionalAccessTest
template <typename FuncDeclMatcher>
void ExpectDiagnosticsFor(std::string SourceCode,
FuncDeclMatcher FuncMatcher) {
// Run in C++17 and C++20 mode to cover differences in the AST between modes
// (e.g. C++20 can contain `CXXRewrittenBinaryOperator`).
for (const char *CxxMode : {"-std=c++17", "-std=c++20"})
ExpectDiagnosticsFor(SourceCode, FuncMatcher, CxxMode);
}

template <typename FuncDeclMatcher>
void ExpectDiagnosticsFor(std::string SourceCode, FuncDeclMatcher FuncMatcher,
const char *CxxMode) {
ReplaceAllOccurrences(SourceCode, "$ns", GetParam().NamespaceName);
ReplaceAllOccurrences(SourceCode, "$optional", GetParam().TypeName);

Expand Down Expand Up @@ -1332,7 +1346,7 @@ class UncheckedOptionalAccessTest
llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
})
.withASTBuildArgs(
{"-fsyntax-only", "-std=c++17", "-Wno-undefined-inline"})
{"-fsyntax-only", CxxMode, "-Wno-undefined-inline"})
.withASTBuildVirtualMappedFiles(
tooling::FileContentMappings(Headers.begin(), Headers.end())),
/*VerifyResults=*/[&Diagnostics](
Expand Down
2 changes: 2 additions & 0 deletions clang/unittests/Format/ConfigParseTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,8 @@ TEST(ConfigParseTest, ParsesConfiguration) {
FormatStyle::RTBS_TopLevelDefinitions);

Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
CHECK_PARSE("AlwaysBreakTemplateDeclarations: Leave",
AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_Leave);
CHECK_PARSE("AlwaysBreakTemplateDeclarations: No",
AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_No);
CHECK_PARSE("AlwaysBreakTemplateDeclarations: MultiLine",
Expand Down
68 changes: 68 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10697,6 +10697,74 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) {
verifyFormat("template <typename T> void\nfoo(aaaaaaaaaaaaaaaaaaaaaaaaaa "
"bbbbbbbbbbbbbbbbbbbb) {}",
NeverBreak);

auto Style = getLLVMStyle();
Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Leave;

verifyNoChange("template <typename T>\n"
"class C {};",
Style);
verifyFormat("template <typename T> class C {};", Style);

verifyNoChange("template <typename T>\n"
"void f();",
Style);
verifyFormat("template <typename T> void f();", Style);

verifyNoChange("template <typename T>\n"
"void f() {}",
Style);
verifyFormat("template <typename T> void f() {}", Style);

verifyNoChange("template <typename T>\n"
"// T can be A, B or C.\n"
"struct C {};",
Style);
verifyFormat("template <typename T> // T can be A, B or C.\n"
"struct C {};",
Style);

verifyNoChange("template <typename T>\n"
"C(T) noexcept;",
Style);
verifyFormat("template <typename T> C(T) noexcept;", Style);

verifyNoChange("template <enum E>\n"
"class A {\n"
"public:\n"
" E *f();\n"
"};",
Style);
verifyFormat("template <enum E> class A {\n"
"public:\n"
" E *f();\n"
"};",
Style);

verifyNoChange("template <auto x>\n"
"constexpr int simple(int) {\n"
" char c;\n"
" return 1;\n"
"}",
Style);
verifyFormat("template <auto x> constexpr int simple(int) {\n"
" char c;\n"
" return 1;\n"
"}",
Style);

Style.RequiresClausePosition = FormatStyle::RCPS_WithPreceding;
verifyNoChange("template <auto x>\n"
"requires(x > 1)\n"
"constexpr int with_req(int) {\n"
" return 1;\n"
"}",
Style);
verifyFormat("template <auto x> requires(x > 1)\n"
"constexpr int with_req(int) {\n"
" return 1;\n"
"}",
Style);
}

TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) {
Expand Down
3 changes: 3 additions & 0 deletions flang/include/flang/Optimizer/Dialect/FIRDialect.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ bool canLegallyInline(mlir::Operation *op, mlir::Region *reg, bool,
mlir::IRMapping &map);
bool canLegallyInline(mlir::Operation *, mlir::Operation *, bool);

// Register the FIRInlinerInterface to FIROpsDialect
void addFIRInlinerExtension(mlir::DialectRegistry &registry);

} // namespace fir

#endif // FORTRAN_OPTIMIZER_DIALECT_FIRDIALECT_H
7 changes: 7 additions & 0 deletions flang/include/flang/Optimizer/Support/InitFIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ inline void registerDialects(mlir::DialectRegistry &registry) {
registry.insert<FLANG_CODEGEN_DIALECT_LIST>();
}

// Register FIR Extensions
inline void addFIRExtensions(mlir::DialectRegistry &registry,
bool addFIRInlinerInterface = true) {
if (addFIRInlinerInterface)
addFIRInlinerExtension(registry);
}

inline void loadNonCodegenDialects(mlir::MLIRContext &context) {
mlir::DialectRegistry registry;
registerNonCodegenDialects(registry);
Expand Down
4 changes: 4 additions & 0 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,10 @@ void CodeGenAction::generateLLVMIR() {
llvm::OptimizationLevel level = mapToLevel(opts);

fir::support::loadDialects(*mlirCtx);
mlir::DialectRegistry registry;
fir::support::registerNonCodegenDialects(registry);
fir::support::addFIRExtensions(registry);
mlirCtx->appendDialectRegistry(registry);
fir::support::registerLLVMTranslation(*mlirCtx);

// Set-up the MLIR pass manager
Expand Down
9 changes: 8 additions & 1 deletion flang/lib/Optimizer/Dialect/FIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,14 @@ fir::FIROpsDialect::FIROpsDialect(mlir::MLIRContext *ctx)
#include "flang/Optimizer/Dialect/FIROps.cpp.inc"
>();
registerOpExternalInterfaces();
addInterfaces<FIRInlinerInterface>();
}

// Register the FIRInlinerInterface to FIROpsDialect
void fir::addFIRInlinerExtension(mlir::DialectRegistry &registry) {
registry.addExtension(
+[](mlir::MLIRContext *ctx, fir::FIROpsDialect *dialect) {
dialect->addInterface<FIRInlinerInterface>();
});
}

// anchor the class vtable to this compilation unit
Expand Down
4 changes: 3 additions & 1 deletion flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5648,7 +5648,9 @@ void DeclarationVisitor::Post(const parser::ProcDecl &x) {
const auto &name{std::get<parser::Name>(x.t)};
const Symbol *procInterface{nullptr};
if (interfaceName_) {
procInterface = interfaceName_->symbol;
procInterface = interfaceName_->symbol->has<GenericDetails>()
? interfaceName_->symbol->get<GenericDetails>().specific()
: interfaceName_->symbol;
}
auto attrs{HandleSaveName(name.source, GetAttrs())};
DerivedTypeDetails *dtDetails{nullptr};
Expand Down
1 change: 1 addition & 0 deletions flang/tools/bbc/bbc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
// translate to FIR dialect of MLIR
mlir::DialectRegistry registry;
fir::support::registerNonCodegenDialects(registry);
fir::support::addFIRExtensions(registry);
mlir::MLIRContext ctx(registry);
fir::support::loadNonCodegenDialects(ctx);
auto &defKinds = semanticsContext.defaultKinds();
Expand Down
1 change: 1 addition & 0 deletions flang/tools/fir-opt/fir-opt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ int main(int argc, char **argv) {
#endif
DialectRegistry registry;
fir::support::registerDialects(registry);
fir::support::addFIRExtensions(registry);
return failed(MlirOptMain(argc, argv, "FIR modular optimizer driver\n",
registry));
}
1 change: 1 addition & 0 deletions flang/tools/tco/tco.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ compileFIR(const mlir::PassPipelineCLParser &passPipeline) {
sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), SMLoc());
mlir::DialectRegistry registry;
fir::support::registerDialects(registry);
fir::support::addFIRExtensions(registry);
mlir::MLIRContext context(registry);
fir::support::loadDialects(context);
fir::support::registerLLVMTranslation(context);
Expand Down
8 changes: 8 additions & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,15 @@ set(TARGET_LIBM_ENTRYPOINTS
if(LIBC_COMPILER_HAS_FLOAT128)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# math.h C23 _Float128 entrypoints
libc.src.math.ceilf128
libc.src.math.copysignf128
libc.src.math.fabsf128
libc.src.math.floorf128
libc.src.math.fmaxf128
libc.src.math.fminf128
libc.src.math.roundf128
libc.src.math.sqrtf128
libc.src.math.truncf128
)
endif()

Expand Down
15 changes: 15 additions & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,21 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.truncl
)

if(LIBC_COMPILER_HAS_FLOAT128)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# math.h C23 _Float128 entrypoints
libc.src.math.ceilf128
libc.src.math.copysignf128
libc.src.math.fabsf128
libc.src.math.floorf128
libc.src.math.fmaxf128
libc.src.math.fminf128
libc.src.math.roundf128
libc.src.math.sqrtf128
libc.src.math.truncf128
)
endif()

if(LLVM_LIBC_FULL_BUILD)
list(APPEND TARGET_LIBC_ENTRYPOINTS
# compiler entrypoints (no corresponding header)
Expand Down
16 changes: 8 additions & 8 deletions libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,23 +114,23 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| ceill | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| ceilf128 | |check| | | | | | | | | | | | |
| ceilf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| copysign | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| copysignf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| copysignl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| copysignf128 | |check| | |check| | | | | | | | | | | |
| copysignf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fabs | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fabsf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fabsl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fabsf128 | |check| | |check| | | | | | | | | | | |
| fabsf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fdim | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
Expand All @@ -144,21 +144,21 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| floorl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| floorf128 | |check| | | | | | | | | | | | |
| floorf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fmax | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fmaxf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fmaxf128 | |check| | | | | | | | | | | | |
| fmaxf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fmaxl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fmin | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fminf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fminf128 | |check| | | | | | | | | | | | |
| fminf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| fminl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
Expand Down Expand Up @@ -270,7 +270,7 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| roundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| roundf128 | |check| | | | | | | | | | | | |
| roundf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| scalbn | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
Expand All @@ -284,7 +284,7 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| truncl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| truncf128 | |check| | | | | | | | | | | | |
| truncf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+


Expand Down
10 changes: 0 additions & 10 deletions libc/src/__support/FPUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,6 @@ add_header_library(
libc.src.__support.uint128
)

add_header_library(
xfloat
HDRS
XFloat.h
DEPENDS
.fp_bits
.normal_float
libc.src.__support.uint
)

add_header_library(
sqrt
HDRS
Expand Down
180 changes: 0 additions & 180 deletions libc/src/__support/FPUtil/XFloat.h

This file was deleted.

2 changes: 2 additions & 0 deletions libc/src/stdio/printf_core/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ int convert(Writer *writer, const FormatSection &to_conv) {
case 'o':
case 'x':
case 'X':
case 'b':
case 'B':
return convert_int(writer, to_conv);
#ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT
case 'f':
Expand Down
22 changes: 16 additions & 6 deletions libc/src/stdio/printf_core/int_converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,17 @@ using HexFmt = IntegerToString<uintmax_t, radix::Hex>;
using HexFmtUppercase = IntegerToString<uintmax_t, radix::Hex::Uppercase>;
using OctFmt = IntegerToString<uintmax_t, radix::Oct>;
using DecFmt = IntegerToString<uintmax_t>;
using BinFmt = IntegerToString<uintmax_t, radix::Bin>;

LIBC_INLINE constexpr size_t num_buf_size() {
constexpr auto max = [](size_t a, size_t b) -> size_t {
return (a < b) ? b : a;
};
return max(HexFmt::buffer_size(),
max(HexFmtUppercase::buffer_size(),
max(OctFmt::buffer_size(), DecFmt::buffer_size())));
cpp::array<size_t, 5> sizes{
HexFmt::buffer_size(), HexFmtUppercase::buffer_size(),
OctFmt::buffer_size(), DecFmt::buffer_size(), BinFmt::buffer_size()};

auto result = sizes[0];
for (size_t i = 1; i < sizes.size(); i++)
result = cpp::max(result, sizes[i]);
return result;
}

LIBC_INLINE cpp::optional<cpp::string_view>
Expand All @@ -52,6 +55,8 @@ num_to_strview(uintmax_t num, cpp::span<char> bufref, char conv_name) {
return HexFmtUppercase::format_to(bufref, num);
} else if (conv_name == 'o') {
return OctFmt::format_to(bufref, num);
} else if (to_lower(conv_name) == 'b') {
return BinFmt::format_to(bufref, num);
} else {
return DecFmt::format_to(bufref, num);
}
Expand Down Expand Up @@ -116,6 +121,11 @@ LIBC_INLINE int convert_int(Writer *writer, const FormatSection &to_conv) {
prefix_len = 2;
prefix[0] = '0';
prefix[1] = a + ('x' - 'a');
} else if ((to_lower(to_conv.conv_name) == 'b') &&
((flags & FormatFlags::ALTERNATE_FORM) != 0) && num != 0) {
prefix_len = 2;
prefix[0] = '0';
prefix[1] = a + ('b' - 'a');
} else {
prefix_len = (sign_char == 0 ? 0 : 1);
prefix[0] = sign_char;
Expand Down
4 changes: 4 additions & 0 deletions libc/src/stdio/printf_core/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ template <typename ArgProvider> class Parser {
case ('x'):
case ('X'):
case ('u'):
case ('b'):
case ('B'):
switch (lm) {
case (LengthModifier::hh):
case (LengthModifier::h):
Expand Down Expand Up @@ -484,6 +486,8 @@ template <typename ArgProvider> class Parser {
case ('x'):
case ('X'):
case ('u'):
case ('b'):
case ('B'):
switch (lm) {
case (LengthModifier::hh):
case (LengthModifier::h):
Expand Down
14 changes: 14 additions & 0 deletions libc/test/src/stdio/printf_core/converter_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,20 @@ TEST_F(LlvmLibcPrintfConverterTest, HexConversion) {
ASSERT_EQ(writer.get_chars_written(), 18);
}

TEST_F(LlvmLibcPrintfConverterTest, BinaryConversion) {
LIBC_NAMESPACE::printf_core::FormatSection section;
section.has_conv = true;
section.raw_string = "%b";
section.conv_name = 'b';
section.conv_val_raw = 42;
LIBC_NAMESPACE::printf_core::convert(&writer, section);

wb.buff[wb.buff_cur] = '\0';

ASSERT_STREQ(str, "101010");
ASSERT_EQ(writer.get_chars_written(), 6);
}

TEST_F(LlvmLibcPrintfConverterTest, PointerConversion) {

LIBC_NAMESPACE::printf_core::FormatSection section;
Expand Down
113 changes: 113 additions & 0 deletions libc/test/src/stdio/sprintf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,119 @@ TEST(LlvmLibcSPrintfTest, HexConv) {
ASSERT_STREQ(buff, "007F 0x1000000000 002 ");
}

TEST(LlvmLibcSPrintfTest, BinConv) {
char buff[64];
int written;

// Basic Tests.

written = LIBC_NAMESPACE::sprintf(buff, "%b", 42);
EXPECT_EQ(written, 6);
ASSERT_STREQ(buff, "101010");

written = LIBC_NAMESPACE::sprintf(buff, "%B", 12081991);
EXPECT_EQ(written, 24);
ASSERT_STREQ(buff, "101110000101101101000111");

// Min Width Tests.

written = LIBC_NAMESPACE::sprintf(buff, "%10b", 0b101010);
EXPECT_EQ(written, 10);
ASSERT_STREQ(buff, " 101010");

written = LIBC_NAMESPACE::sprintf(buff, "%2B", 0b101010);
EXPECT_EQ(written, 6);
ASSERT_STREQ(buff, "101010");

// Precision Tests.

written = LIBC_NAMESPACE::sprintf(buff, "%b", 0);
EXPECT_EQ(written, 1);
ASSERT_STREQ(buff, "0");

written = LIBC_NAMESPACE::sprintf(buff, "%.0b", 0);
EXPECT_EQ(written, 0);
ASSERT_STREQ(buff, "");

written = LIBC_NAMESPACE::sprintf(buff, "%.5b", 0b111);
EXPECT_EQ(written, 5);
ASSERT_STREQ(buff, "00111");

written = LIBC_NAMESPACE::sprintf(buff, "%.2b", 0b111);
EXPECT_EQ(written, 3);
ASSERT_STREQ(buff, "111");

written = LIBC_NAMESPACE::sprintf(buff, "%3b", 0b111);
EXPECT_EQ(written, 3);
ASSERT_STREQ(buff, "111");

// Flag Tests.

written = LIBC_NAMESPACE::sprintf(buff, "%-5b", 0b111);
EXPECT_EQ(written, 5);
ASSERT_STREQ(buff, "111 ");

written = LIBC_NAMESPACE::sprintf(buff, "%#b", 0b111);
EXPECT_EQ(written, 5);
ASSERT_STREQ(buff, "0b111");

written = LIBC_NAMESPACE::sprintf(buff, "%#b", 0);
EXPECT_EQ(written, 1);
ASSERT_STREQ(buff, "0");

written = LIBC_NAMESPACE::sprintf(buff, "%#B", 0b111);
EXPECT_EQ(written, 5);
ASSERT_STREQ(buff, "0B111");

written = LIBC_NAMESPACE::sprintf(buff, "%05b", 0b111);
EXPECT_EQ(written, 5);
ASSERT_STREQ(buff, "00111");

written = LIBC_NAMESPACE::sprintf(buff, "%0#6b", 0b111);
EXPECT_EQ(written, 6);
ASSERT_STREQ(buff, "0b0111");

written = LIBC_NAMESPACE::sprintf(buff, "%-#6b", 0b111);
EXPECT_EQ(written, 6);
ASSERT_STREQ(buff, "0b111 ");

// Combined Tests.

written = LIBC_NAMESPACE::sprintf(buff, "%#-07b", 0b111);
EXPECT_EQ(written, 7);
ASSERT_STREQ(buff, "0b111 ");

written = LIBC_NAMESPACE::sprintf(buff, "%7.5b", 0b111);
EXPECT_EQ(written, 7);
ASSERT_STREQ(buff, " 00111");

written = LIBC_NAMESPACE::sprintf(buff, "%#9.5B", 0b111);
EXPECT_EQ(written, 9);
ASSERT_STREQ(buff, " 0B00111");

written = LIBC_NAMESPACE::sprintf(buff, "%#.b", 0);
EXPECT_EQ(written, 0);
ASSERT_STREQ(buff, "");

written = LIBC_NAMESPACE::sprintf(buff, "%-7.5b", 0b111);
EXPECT_EQ(written, 7);
ASSERT_STREQ(buff, "00111 ");

written = LIBC_NAMESPACE::sprintf(buff, "%5.4b", 0b1111);
EXPECT_EQ(written, 5);
ASSERT_STREQ(buff, " 1111");

// Multiple Conversion Tests.

written = LIBC_NAMESPACE::sprintf(buff, "%10B %-#10b", 0b101, 0b110);
EXPECT_EQ(written, 21);
ASSERT_STREQ(buff, " 101 0b110 ");

written = LIBC_NAMESPACE::sprintf(buff, "%-5.4b%#.4b", 0b101, 0b110);
EXPECT_EQ(written, 11);
ASSERT_STREQ(buff, "0101 0b0110");
}

TEST(LlvmLibcSPrintfTest, PointerConv) {
char buff[64];
int written;
Expand Down
19 changes: 19 additions & 0 deletions libunwind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ set(LIBUNWIND_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
"Specify path to libc++ source.")

include(GNUInstallDirs)
include(CheckSymbolExists)

#===============================================================================
# Setup CMake Options
Expand Down Expand Up @@ -96,6 +97,20 @@ endif()
option(LIBUNWIND_HIDE_SYMBOLS
"Do not export any symbols from the static library." ${LIBUNWIND_DEFAULT_HIDE_SYMBOLS})

# If toolchain is FPXX, we switch to FP64 to save the full FPRs. See:
# https://web.archive.org/web/20180828210612/https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
check_symbol_exists(__mips_hard_float "" __MIPSHF)
check_symbol_exists(_ABIO32 "" __MIPS_O32)
if (__MIPSHF AND __MIPS_O32)
file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/mips_is_fpxx.c
"#if __mips_fpr != 0\n"
"# error\n"
"#endif\n")
try_compile(MIPS_FPABI_FPXX ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/mips_is_fpxx.c
CMAKE_FLAGS -DCMAKE_C_LINK_EXECUTABLE='echo')
endif()

#===============================================================================
# Configure System
#===============================================================================
Expand Down Expand Up @@ -179,6 +194,10 @@ if (WIN32)
add_compile_flags_if_supported(-Wno-dll-attribute-on-redeclaration)
endif()

if (MIPS_FPABI_FPXX)
add_compile_flags(-mfp64)
endif()

# Get feature flags.
# Exceptions
# Catches C++ exceptions only and tells the compiler to assume that extern C
Expand Down
4 changes: 2 additions & 2 deletions lld/ELF/Arch/LoongArch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,8 +679,8 @@ static bool relax(InputSection &sec) {
case R_LARCH_ALIGN: {
const uint64_t addend =
r.sym->isUndefined() ? Log2_64(r.addend) + 1 : r.addend;
const uint64_t allBytes = (1 << (addend & 0xff)) - 4;
const uint64_t align = 1 << (addend & 0xff);
const uint64_t allBytes = (1ULL << (addend & 0xff)) - 4;
const uint64_t align = 1ULL << (addend & 0xff);
const uint64_t maxBytes = addend >> 8;
const uint64_t off = loc & (align - 1);
const uint64_t curBytes = off == 0 ? 0 : align - off;
Expand Down
12 changes: 6 additions & 6 deletions lld/test/wasm/build-id.test
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ foo:


# DEFAULT: Contents of section build_id:
# DEFAULT-NEXT: 0000 10299168 1e3c845a 3c8f80ae 2f16cc22 .).h.<.Z<.../.."
# DEFAULT-NEXT: 0010 2d
# DEFAULT-NEXT: 0079 10299168 1e3c845a 3c8f80ae 2f16cc22 .).h.<.Z<.../.."
# DEFAULT-NEXT: 0089 2d

# SHA1: Contents of section build_id:
# SHA1-NEXT: 0000 145abdda 387a9bc4 e3aed3c3 3319cd37 .Z..8z......3..7
# SHA1-NEXT: 0010 0212237c e4 ..#|.
# SHA1-NEXT: 0079 145abdda 387a9bc4 e3aed3c3 3319cd37 .Z..8z......3..7
# SHA1-NEXT: 0089 0212237c e4 ..#|.

# UUID: Contents of section build_id:
# UUID-NEXT: 0000 10
# UUID-NEXT: 0079 10

# HEX: Contents of section build_id:
# HEX-NEXT: 0000 04123456 78 ..4Vx
# HEX-NEXT: 0079 04123456 78 ..4Vx


# NONE-NOT: Contents of section build_id:
14 changes: 7 additions & 7 deletions lld/test/wasm/merge-string-debug.s
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@

# CHECK: Hex dump of section '.debug_str':

# CHECK-O0: 0x00000000 636c616e 67207665 7273696f 6e203133 clang version 13
# CHECK-O0: 0x00000010 2e302e30 00666f6f 62617200 636c616e .0.0.foobar.clan
# CHECK-O0: 0x00000020 67207665 7273696f 6e203133 2e302e30 g version 13.0.0
# CHECK-O0: 0x00000030 00626172 00666f6f 00 .bar.foo.
# CHECK-O0: 0x00000025 636c616e 67207665 7273696f 6e203133 clang version 13
# CHECK-O0: 0x00000035 2e302e30 00666f6f 62617200 636c616e .0.0.foobar.clan
# CHECK-O0: 0x00000045 67207665 7273696f 6e203133 2e302e30 g version 13.0.0
# CHECK-O0: 0x00000055 00626172 00666f6f 00 .bar.foo.

# CHECK-O1: 0x00000000 666f6f62 61720066 6f6f0063 6c616e67 foobar.foo.clang
# CHECK-O1: 0x00000010 20766572 73696f6e 2031332e 302e3000 version 13.0.0.
# CHECK-O1: 0x00000025 666f6f62 61720066 6f6f0063 6c616e67 foobar.foo.clang
# CHECK-O1: 0x00000035 20766572 73696f6e 2031332e 302e3000 version 13.0.0.

# CHECK-OFFSETS: Hex dump of section '.debug_str_offsets':
# CHECK-OFFSETS: 0x00000000 00000000 00000000 00000000 ............
# CHECK-OFFSETS: 0x0000007e 00000000 00000000 00000000 ............
12 changes: 6 additions & 6 deletions lld/test/wasm/startstop.ll
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ entry:
; CHECK-NEXT: Value: 1024
; CHECK-NEXT: Content: 03000000040000002A0000002B000000

; ASM: 00000001 <get_start>:
; ASM: 0000006e <get_start>:
; ASM-EMPTY:
; ASM-NEXT: 3: i32.const 1024
; ASM-NEXT: 9: end
; ASM-NEXT: 70: i32.const 1024
; ASM-NEXT: 76: end

; ASM: 0000000a <get_end>:
; ASM: 00000077 <get_end>:
; ASM-EMPTY:
; ASM-NEXT: c: i32.const 1040
; ASM-NEXT: 12: end
; ASM-NEXT: 79: i32.const 1040
; ASM-NEXT: 7f: end
8 changes: 2 additions & 6 deletions lldb/docs/lldb-gdb-remote.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1998,16 +1998,12 @@ for this region.
// If the debug stub can support compression, it indictes this in the reply of the
// "qSupported" packet. e.g.
// LLDB SENDS: qSupported:xmlRegisters=i386,arm,mips
// STUB REPLIES: qXfer:features:read+;SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;DefaultCompressionMinSize=384
// STUB REPLIES: qXfer:features:read+;SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;
//
// If lldb knows how to use any of these compression algorithms, it can ask that this
// compression mode be enabled. It may optionally change the minimum packet size
// where compression is used. Typically small packets do not benefit from compression,
// as well as compression headers -- compression is most beneficial with larger packets.
// compression mode be enabled.
//
// QEnableCompression:type:zlib-deflate;
// or
// QEnableCompression:type:zlib-deflate;minsize:512;
//
// The debug stub should reply with an uncompressed "OK" packet to indicate that the
// request was accepted. All further packets the stub sends will use this compression.
Expand Down
27 changes: 16 additions & 11 deletions lldb/include/lldb/DataFormatters/TypeSynthetic.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ class SyntheticChildrenFrontEnd {

virtual size_t GetIndexOfChildWithName(ConstString name) = 0;

// this function is assumed to always succeed and it if fails, the front-end
// should know to deal with it in the correct way (most probably, by refusing
// to return any children) the return value of Update() should actually be
// interpreted as "ValueObjectSyntheticFilter cache is good/bad" if =true,
// ValueObjectSyntheticFilter is allowed to use the children it fetched
// previously and cached if =false, ValueObjectSyntheticFilter must throw
// away its cache, and query again for children
virtual bool Update() = 0;
/// This function is assumed to always succeed and if it fails, the front-end
/// should know to deal with it in the correct way (most probably, by refusing
/// to return any children). The return value of \ref Update should actually
/// be interpreted as "ValueObjectSyntheticFilter cache is good/bad". If this
/// function returns \ref lldb::ChildCacheState::eReuse, \ref
/// ValueObjectSyntheticFilter is allowed to use the children it fetched
/// previously and cached. Otherwise, \ref ValueObjectSyntheticFilter must
/// throw away its cache, and query again for children.
virtual lldb::ChildCacheState Update() = 0;

// if this function returns false, then CalculateNumChildren() MUST return 0
// since UI frontends might validly decide not to inquire for children given
Expand Down Expand Up @@ -116,7 +117,9 @@ class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
return UINT32_MAX;
}

bool Update() override { return false; }
lldb::ChildCacheState Update() override {
return lldb::ChildCacheState::eRefetch;
}

bool MightHaveChildren() override { return false; }

Expand Down Expand Up @@ -328,7 +331,9 @@ class TypeFilterImpl : public SyntheticChildren {
filter->GetExpressionPathAtIndex(idx), true);
}

bool Update() override { return false; }
lldb::ChildCacheState Update() override {
return lldb::ChildCacheState::eRefetch;
}

bool MightHaveChildren() override { return filter->GetCount() > 0; }

Expand Down Expand Up @@ -427,7 +432,7 @@ class ScriptedSyntheticChildren : public SyntheticChildren {

lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;

bool Update() override;
lldb::ChildCacheState Update() override;

bool MightHaveChildren() override;

Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/DataFormatters/VectorIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;

bool Update() override;
lldb::ChildCacheState Update() override;

bool MightHaveChildren() override;

Expand Down
9 changes: 9 additions & 0 deletions lldb/include/lldb/lldb-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,15 @@ enum CompletionType {
eTerminatorCompletion = (1ul << 27)
};

/// Specifies if children need to be re-computed
/// after a call to \ref SyntheticChildrenFrontEnd::Update.
enum class ChildCacheState {
eRefetch = 0, ///< Children need to be recomputed dynamically.

eReuse = 1, ///< Children did not change and don't need to be recomputed;
///< re-use what we computed the last time we called Update.
};

} // namespace lldb

#endif // LLDB_LLDB_ENUMERATIONS_H
6 changes: 4 additions & 2 deletions lldb/source/Core/ValueObjectSyntheticFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd {

bool MightHaveChildren() override { return m_backend.MightHaveChildren(); }

bool Update() override { return false; }
lldb::ChildCacheState Update() override {
return lldb::ChildCacheState::eRefetch;
}
};

ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
Expand Down Expand Up @@ -177,7 +179,7 @@ bool ValueObjectSynthetic::UpdateValue() {
}

// let our backend do its update
if (!m_synth_filter_up->Update()) {
if (m_synth_filter_up->Update() == lldb::ChildCacheState::eRefetch) {
LLDB_LOGF(log,
"[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
"filter said caches are stale - clearing",
Expand Down
8 changes: 5 additions & 3 deletions lldb/source/DataFormatters/TypeSynthetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,13 @@ size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) {
return m_interpreter->CalculateNumChildren(m_wrapper_sp, max);
}

bool ScriptedSyntheticChildren::FrontEnd::Update() {
lldb::ChildCacheState ScriptedSyntheticChildren::FrontEnd::Update() {
if (!m_wrapper_sp || m_interpreter == nullptr)
return false;
return lldb::ChildCacheState::eRefetch;

return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp);
return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp)
? lldb::ChildCacheState::eReuse
: lldb::ChildCacheState::eRefetch;
}

bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() {
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/DataFormatters/VectorType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
return child_sp;
}

bool Update() override {
lldb::ChildCacheState Update() override {
m_parent_format = m_backend.GetFormat();
CompilerType parent_type(m_backend.GetCompilerType());
CompilerType element_type;
Expand All @@ -258,7 +258,7 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
::CalculateNumChildren(element_type, num_elements, m_child_type)
.value_or(0);
m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type);
return false;
return lldb::ChildCacheState::eRefetch;
}

bool MightHaveChildren() override { return true; }
Expand Down
4 changes: 3 additions & 1 deletion lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

// return true if this object is now safe to use forever without ever
// updating again; the typical (and tested) answer here is 'false'
bool Update() override { return false; }
lldb::ChildCacheState Update() override {
return lldb::ChildCacheState::eRefetch;
}

// maybe return false if the block pointer is, say, null
bool MightHaveChildren() override { return true; }
Expand Down
16 changes: 8 additions & 8 deletions lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,24 @@ lldb::ValueObjectSP lldb_private::formatters::
return lldb::ValueObjectSP();
}

bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
Update() {
lldb::ChildCacheState
lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::Update() {
m_resume_ptr_sp.reset();
m_destroy_ptr_sp.reset();
m_promise_ptr_sp.reset();

ValueObjectSP valobj_sp = m_backend.GetNonSyntheticValue();
if (!valobj_sp)
return false;
return lldb::ChildCacheState::eRefetch;

lldb::addr_t frame_ptr_addr = GetCoroFramePtrFromHandle(valobj_sp);
if (frame_ptr_addr == 0 || frame_ptr_addr == LLDB_INVALID_ADDRESS)
return false;
return lldb::ChildCacheState::eRefetch;

auto ts = valobj_sp->GetCompilerType().GetTypeSystem();
auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
if (!ast_ctx)
return false;
return lldb::ChildCacheState::eRefetch;

// Create the `resume` and `destroy` children.
lldb::TargetSP target_sp = m_backend.GetTargetSP();
Expand All @@ -165,7 +165,7 @@ bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
CompilerType promise_type(
valobj_sp->GetCompilerType().GetTypeTemplateArgument(0));
if (!promise_type)
return false;
return lldb::ChildCacheState::eRefetch;

// Try to infer the promise_type if it was type-erased
if (promise_type.IsVoidType()) {
Expand All @@ -180,7 +180,7 @@ bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
// If we don't know the promise type, we don't display the `promise` member.
// `CreateValueObjectFromAddress` below would fail for `void` types.
if (promise_type.IsVoidType()) {
return false;
return lldb::ChildCacheState::eRefetch;
}

// Add the `promise` member. We intentionally add `promise` as a pointer type
Expand All @@ -194,7 +194,7 @@ bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
if (error.Success())
m_promise_ptr_sp = promisePtr->Clone(ConstString("promise"));

return false;
return lldb::ChildCacheState::eRefetch;
}

bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Language/CPlusPlus/Coroutines.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class StdlibCoroutineHandleSyntheticFrontEnd

lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;

bool Update() override;
lldb::ChildCacheState Update() override;

bool MightHaveChildren() override;

Expand Down
8 changes: 4 additions & 4 deletions lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class GenericBitsetFrontEnd : public SyntheticChildrenFrontEnd {
}

bool MightHaveChildren() override { return true; }
bool Update() override;
lldb::ChildCacheState Update() override;
size_t CalculateNumChildren() override { return m_elements.size(); }
ValueObjectSP GetChildAtIndex(size_t idx) override;

Expand Down Expand Up @@ -78,13 +78,13 @@ llvm::StringRef GenericBitsetFrontEnd::GetDataContainerMemberName() {
llvm_unreachable("Unknown StdLib enum");
}

bool GenericBitsetFrontEnd::Update() {
lldb::ChildCacheState GenericBitsetFrontEnd::Update() {
m_elements.clear();
m_first = nullptr;

TargetSP target_sp = m_backend.GetTargetSP();
if (!target_sp)
return false;
return lldb::ChildCacheState::eRefetch;

size_t size = 0;

Expand All @@ -94,7 +94,7 @@ bool GenericBitsetFrontEnd::Update() {
m_elements.assign(size, ValueObjectSP());
m_first =
m_backend.GetChildMemberWithName(GetDataContainerMemberName()).get();
return false;
return lldb::ChildCacheState::eRefetch;
}

ValueObjectSP GenericBitsetFrontEnd::GetChildAtIndex(size_t idx) {
Expand Down
8 changes: 4 additions & 4 deletions lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class GenericOptionalFrontend : public SyntheticChildrenFrontEnd {
size_t CalculateNumChildren() override { return m_has_value ? 1U : 0U; }

ValueObjectSP GetChildAtIndex(size_t idx) override;
bool Update() override;
lldb::ChildCacheState Update() override;

private:
bool m_has_value = false;
Expand All @@ -61,7 +61,7 @@ GenericOptionalFrontend::GenericOptionalFrontend(ValueObject &valobj,
}
}

bool GenericOptionalFrontend::Update() {
lldb::ChildCacheState GenericOptionalFrontend::Update() {
ValueObjectSP engaged_sp;

if (m_stdlib == StdLib::LibCxx)
Expand All @@ -71,14 +71,14 @@ bool GenericOptionalFrontend::Update() {
->GetChildMemberWithName("_M_engaged");

if (!engaged_sp)
return false;
return lldb::ChildCacheState::eRefetch;

// _M_engaged/__engaged is a bool flag and is true if the optional contains a
// value. Converting it to unsigned gives us a size of 1 if it contains a
// value and 0 if not.
m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0;

return false;
return lldb::ChildCacheState::eRefetch;
}

ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(size_t _idx) {
Expand Down
Loading