34 changes: 27 additions & 7 deletions clang/test/Preprocessor/ptrauth_feature.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,65 @@
// RUN: -fptrauth-vtable-pointer-address-discrimination \
// RUN: -fptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-init-fini | \
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,NOFUNC

// RUN: %clang_cc1 -E %s -triple=aarch64 \
// RUN: -fptrauth-calls \
// RUN: -fptrauth-returns \
// RUN: -fptrauth-vtable-pointer-address-discrimination \
// RUN: -fptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-init-fini | \
// RUN: FileCheck %s --check-prefixes=NOINTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
// RUN: FileCheck %s --check-prefixes=NOINTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,NOFUNC

// RUN: %clang_cc1 -E %s -triple=aarch64 \
// RUN: -fptrauth-intrinsics \
// RUN: -fptrauth-returns \
// RUN: -fptrauth-vtable-pointer-address-discrimination \
// RUN: -fptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-init-fini | \
// RUN: FileCheck %s --check-prefixes=INTRIN,NOCALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
// RUN: FileCheck %s --check-prefixes=INTRIN,NOCALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,NOFUNC

// RUN: %clang_cc1 -E %s -triple=aarch64 \
// RUN: -fptrauth-intrinsics \
// RUN: -fptrauth-calls \
// RUN: -fptrauth-vtable-pointer-address-discrimination \
// RUN: -fptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-init-fini | \
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,NORETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,NORETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,NOFUNC

// RUN: %clang_cc1 -E %s -triple=aarch64 \
// RUN: -fptrauth-intrinsics \
// RUN: -fptrauth-calls \
// RUN: -fptrauth-returns \
// RUN: -fptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-init-fini | \
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,NOVPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,NOVPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI,NOFUNC

// RUN: %clang_cc1 -E %s -triple=aarch64 \
// RUN: -fptrauth-intrinsics \
// RUN: -fptrauth-calls \
// RUN: -fptrauth-returns \
// RUN: -fptrauth-vtable-pointer-address-discrimination \
// RUN: -fptrauth-init-fini | \
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,INITFINI
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,INITFINI,NOFUNC

// RUN: %clang_cc1 -E %s -triple=aarch64 \
// RUN: -fptrauth-intrinsics \
// RUN: -fptrauth-calls \
// RUN: -fptrauth-returns \
// RUN: -fptrauth-vtable-pointer-address-discrimination \
// RUN: -fptrauth-vtable-pointer-type-discrimination | \
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI,NOFUNC

// RUN: %clang_cc1 -E %s -triple=aarch64 \
// RUN: -fptrauth-intrinsics \
// RUN: -fptrauth-calls \
// RUN: -fptrauth-returns \
// RUN: -fptrauth-vtable-pointer-address-discrimination \
// RUN: -fptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-function-pointer-type-discrimination | \
// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI,FUNC


#if __has_feature(ptrauth_intrinsics)
// INTRIN: has_ptrauth_intrinsics
Expand Down Expand Up @@ -111,3 +121,13 @@ void has_ptrauth_init_fini() {}
// NOINITFINI: no_ptrauth_init_fini
void no_ptrauth_init_fini() {}
#endif

#include <ptrauth.h>

#if __has_feature(ptrauth_function_pointer_type_discrimination)
// FUNC: has_ptrauth_function_pointer_type_discrimination
void has_ptrauth_function_pointer_type_discrimination() {}
#else
// NOFUNC: no_ptrauth_function_pointer_type_discrimination
void no_ptrauth_function_pointer_type_discrimination() {}
#endif
4 changes: 2 additions & 2 deletions clang/test/Sema/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ void test17(void) {
#define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4)
// FIXME: These are incorrectly treated as ICEs because strlen is treated as
// a builtin.
ASSERT(OPT("abc"));
ASSERT(!OPT("abcd"));
ASSERT(OPT("abc")); // expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
ASSERT(!OPT("abcd")); // expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
// In these cases, the strlen is non-constant, but the __builtin_constant_p
// is 0: the array size is not an ICE but is foldable.
ASSERT(!OPT(test17_c));
Expand Down
12 changes: 8 additions & 4 deletions clang/test/Sema/constant-builtins-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,17 +265,21 @@ char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 :
char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1];
char clz54[__builtin_clzg((unsigned __int128)0xf) == BITSIZE(__int128) - 4 ? 1 : -1];
char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1];
char clz56[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1))) == 0 ? 1 : -1];
char clz57[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1)), 42) == 0 ? 1 : -1];
char clz56[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1))) == 0 ? 1 : -1]; // expected-warning {{variable length array folded to constant array as an extension}}
// expected-note@-1 {{shift count 127 >= width of type 'int' (32 bits)}}
char clz57[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1)), 42) == 0 ? 1 : -1]; // expected-warning {{variable length array folded to constant array as an extension}}
// expected-note@-1 {{shift count 127 >= width of type 'int' (32 bits)}}
#endif
int clz58 = __builtin_clzg((unsigned _BitInt(128))0); // expected-error {{not a compile-time constant}}
char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char clz62[__builtin_clzg((unsigned _BitInt(128))0xf) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
char clz63[__builtin_clzg((unsigned _BitInt(128))0xf, 42) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
char clz64[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1))) == 0 ? 1 : -1];
char clz65[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1)), 42) == 0 ? 1 : -1];
char clz64[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1))) == 0 ? 1 : -1]; // expected-warning {{variable length array folded to constant array as an extension}}
// expected-note@-1 {{shift count 127 >= width of type 'int' (32 bits)}}
char clz65[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1)), 42) == 0 ? 1 : -1]; // expected-warning {{variable length array folded to constant array as an extension}}
// expected-note@-1 {{shift count 127 >= width of type 'int' (32 bits)}}

char ctz1[__builtin_ctz(1) == 0 ? 1 : -1];
char ctz2[__builtin_ctz(8) == 3 ? 1 : -1];
Expand Down
2 changes: 2 additions & 0 deletions clang/test/Sema/integer-overflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ void check_integer_overflows_in_function_calls(void) {
}
void check_integer_overflows_in_array_size(void) {
int arr[4608 * 1024 * 1024]; // expected-warning {{overflow in expression; result is 536'870'912 with type 'int'}}
// expected-warning@-1 {{variable length array folded to constant array as an extension}}
// expected-note@-2 {{value 4831838208 is outside the range of representable values of type 'int'}}
}

struct s {
Expand Down
8 changes: 8 additions & 0 deletions clang/test/Sema/shift-count-negative.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -pedantic %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp %s

enum shiftof {
X = (1<<-29) // c-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
// cpp-error@-1 {{expression is not an integral constant expression}}
// expected-note@-2 {{negative shift count -29}}
};
9 changes: 9 additions & 0 deletions clang/test/Sema/shift-count-overflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %clang_cc1 -fsyntax-only -verify=expected,c -pedantic %s
// RUN: %clang_cc1 -x c++ -std=c++98 -fsyntax-only -verify=expected,cpp %s
// RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -verify=expected,cpp %s

enum shiftof {
X = (1<<32) // c-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
// cpp-error@-1 {{expression is not an integral constant expression}}
// expected-note@-2 {{shift count 32 >= width of type 'int'}}
};
13 changes: 13 additions & 0 deletions clang/test/Sema/shift-negative-value.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -pedantic %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wshift-negative-value %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wall %s
// RUN: %clang_cc1 -x c++ -std=c++98 -fsyntax-only -verify=expected,cpp -Wshift-negative-value %s
// RUN: %clang_cc1 -x c++ -std=c++98 -fsyntax-only -verify=expected,cpp -Wall %s
// RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -verify=expected,cpp -Wshift-negative-value %s
// RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -verify=expected,cpp -Wall %s

enum shiftof {
X = (-1<<29) // c-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
// cpp-error@-1 {{expression is not an integral constant expression}}
// expected-note@-2 {{left shift of negative value -1}}
};
29 changes: 29 additions & 0 deletions clang/test/Sema/undefined-internal-basic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c11 -Wno-pointer-arith -Wno-gnu-alignof-expression -Wno-unused -pedantic-errors

static void *a(void); // expected-error {{function 'a' has internal linkage but is not defined}}
static void *b(void); // expected-error {{function 'b' has internal linkage but is not defined}}
static void *c(void); // expected-error {{function 'c' has internal linkage but is not defined}}
static void *d(void); // expected-error {{function 'd' has internal linkage but is not defined}}
static void *no_err(void);

int main(void)
{
a; // expected-note {{used here}}

int i = _Alignof(no_err);

int j = _Generic(&no_err, void *(*)(void): 0);

void *k = _Generic(&no_err, void *(*)(void): b(), default: 0); // expected-note {{used here}}

// FIXME according to the C standard there should be no error if the undefined internal is
// "part of the expression in a generic association that is not the result expression of its generic selection;"
// but, currently, clang wrongly emits an error in this case
k = _Generic(&no_err, void *(*)(void): 0, default: c()); // expected-note {{used here}}

k = _Generic(&no_err, int (*)(void) : 0, default : d()); // expected-note {{used here}}

int l = sizeof(no_err);

__typeof__(&no_err) x;
}
10 changes: 10 additions & 0 deletions clang/test/Sema/undefined-internal-typeof-c23.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c23 -pedantic-errors

// expected-no-diagnostics

static int f(void);

int main(void)
{
typeof(&f) x;
}
6 changes: 4 additions & 2 deletions clang/test/Sema/vla-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
// a different codepath when we have already emitted an error.)

int PotentiallyEvaluatedSizeofWarn(int n) {
return (int)sizeof *(0 << 32,(int(*)[n])0); // expected-warning {{left operand of comma operator has no effect}} expected-warning {{shift count >= width of type}}
return (int)sizeof *(0 << 32,(int(*)[n])0); /* expected-warning {{shift count >= width of type}}
expected-warning {{left operand of comma operator has no effect}} */
}

void PotentiallyEvaluatedTypeofWarn(int n) {
__typeof(*(0 << 32,(int(*)[n])0)) x; // expected-warning {{left operand of comma operator has no effect}} expected-warning {{shift count >= width of type}}
__typeof(*(0 << 32,(int(*)[n])0)) x; /* expected-warning {{shift count >= width of type}}
expected-warning {{left operand of comma operator has no effect}} */
(void)x;
}

Expand Down
16 changes: 10 additions & 6 deletions clang/test/SemaCXX/enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ void PR8089() {
// expressions with UB to be non-constant.
enum { overflow = 123456 * 234567 };
#if __cplusplus >= 201103L
// expected-warning@-2 {{not an integral constant expression}}
// expected-note@-3 {{value 28958703552 is outside the range of representable values}}
#else
// expected-warning@-5 {{overflow in expression; result is -1'106'067'520 with type 'int'}}
// expected-warning@-2 {{expression is not an integral constant expression; folding it to a constant is a GNU extension}}
// expected-note@-3 {{value 28958703552 is outside the range of representable values of type 'int'}}
#else
// expected-error@-5 {{expression is not an integral constant expression}}
// expected-note@-6 {{value 28958703552 is outside the range of representable values of type 'int'}}
// expected-warning@-7 {{overflow in expression; result is -1'106'067'520 with type 'int'}}
#endif

// FIXME: This is not consistent with the above case.
Expand All @@ -112,8 +114,10 @@ enum NoFold : int { overflow2 = 123456 * 234567 };
// expected-error@-2 {{enumerator value is not a constant expression}}
// expected-note@-3 {{value 28958703552 is outside the range of representable values}}
#else
// expected-warning@-5 {{overflow in expression; result is -1'106'067'520 with type 'int'}}
// expected-warning@-6 {{extension}}
// expected-warning@-5 {{enumeration types with a fixed underlying type are a C++11 extension}}
// expected-warning@-6 {{overflow in expression; result is -1'106'067'520 with type 'int'}}
// expected-error@-7 {{expression is not an integral constant expression}}
// expected-note@-8 {{value 28958703552 is outside the range of representable values of type 'int'}}
#endif

// PR28903
Expand Down
21 changes: 21 additions & 0 deletions clang/test/SemaCXX/lambda-pack-expansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,24 @@ void foo() {
take_by_ref(x);
}
}

namespace GH48937 {

template <typename... Ts>
consteval int f(Ts... ts) {
return ([]<Ts a = 42>(){ return a;}, ...)();
}

static_assert(f(0, 42) == 42);

template <typename Ts>
int g(Ts ts) {
return ([]<Ts a = 42>(){ return a;}, ...)(); // expected-error {{pack expansion does not contain any unexpanded parameter packs}}
}

template <typename... Ts>
int h(Ts... ts) {
return ([]<Ts a = 42>(){ return a;})(); // expected-error {{expression contains unexpanded parameter pack 'Ts'}}
}

}
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/shift.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void test() {
c = 1 << -1; // expected-warning {{shift count is negative}}
c = 1 >> -1; // expected-warning {{shift count is negative}}
c = 1 << (unsigned)-1; // expected-warning {{shift count >= width of type}}
// expected-warning@-1 {{implicit conversion}}
// expected-warning@-1 {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}}
c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}}
c = 1 << c;
c <<= 0;
Expand Down
12 changes: 12 additions & 0 deletions clang/test/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@
if config.clang_examples:
config.available_features.add("examples")

if config.llvm_examples:
config.available_features.add("llvm-examples")

if config.llvm_linked_bye_extension:
config.substitutions.append(("%offload-opt-loadbye", ""))
else:
loadbye = f"-load-pass-plugin={config.llvm_shlib_dir}/Bye{config.llvm_shlib_ext}"
config.substitutions.append(("%offload-opt-loadbye", f"--offload-opt={loadbye}"))


def have_host_jit_feature_support(feature_name):
clang_repl_exe = lit.util.which("clang-repl", config.clang_tools_dir)
Expand Down Expand Up @@ -213,6 +222,9 @@ def have_host_clang_repl_cuda():
if config.has_plugins and config.llvm_plugin_ext:
config.available_features.add("plugins")

if config.llvm_has_plugins and config.llvm_plugin_ext:
config.available_features.add("llvm-plugins")

if config.clang_default_pie_on_linux:
config.available_features.add("default-pie-on-linux")

Expand Down
4 changes: 4 additions & 0 deletions clang/test/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ config.llvm_obj_root = path(r"@LLVM_BINARY_DIR@")
config.llvm_tools_dir = lit_config.substitute(path(r"@LLVM_TOOLS_DIR@"))
config.llvm_libs_dir = lit_config.substitute(path(r"@LLVM_LIBS_DIR@"))
config.llvm_shlib_dir = lit_config.substitute(path(r"@SHLIBDIR@"))
config.llvm_shlib_ext = "@SHLIBEXT@"
config.llvm_plugin_ext = "@LLVM_PLUGIN_EXT@"
config.lit_tools_dir = path(r"@LLVM_LIT_TOOLS_DIR@")
config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@"
Expand Down Expand Up @@ -39,7 +40,10 @@ config.python_executable = "@Python3_EXECUTABLE@"
config.use_z3_solver = lit_config.params.get('USE_Z3_SOLVER', "@USE_Z3_SOLVER@")
config.has_plugins = @CLANG_PLUGIN_SUPPORT@
config.clang_vendor_uti = "@CLANG_VENDOR_UTI@"
config.llvm_examples = @LLVM_BUILD_EXAMPLES@
config.llvm_linked_bye_extension = @LLVM_BYE_LINK_INTO_TOOLS@
config.llvm_external_lit = path(r"@LLVM_EXTERNAL_LIT@")
config.llvm_has_plugins = @LLVM_ENABLE_PLUGINS@
config.standalone_build = @CLANG_BUILT_STANDALONE@
config.ppc_linux_default_ieeelongdouble = @PPC_LINUX_DEFAULT_IEEELONGDOUBLE@
config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@
Expand Down
2 changes: 2 additions & 0 deletions clang/tools/clang-linker-wrapper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ target_link_libraries(clang-linker-wrapper
PRIVATE
${CLANG_LINKER_WRAPPER_LIB_DEPS}
)

export_executable_symbols_for_plugins(clang-linker-wrapper)
74 changes: 74 additions & 0 deletions clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Remarks/HotnessThresholdParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileOutputBuffer.h"
Expand All @@ -62,6 +64,54 @@ using namespace llvm;
using namespace llvm::opt;
using namespace llvm::object;

// Various tools (e.g., llc and opt) duplicate this series of declarations for
// options related to passes and remarks.

static cl::opt<bool> RemarksWithHotness(
"pass-remarks-with-hotness",
cl::desc("With PGO, include profile count in optimization remarks"),
cl::Hidden);

static cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser>
RemarksHotnessThreshold(
"pass-remarks-hotness-threshold",
cl::desc("Minimum profile count required for "
"an optimization remark to be output. "
"Use 'auto' to apply the threshold from profile summary."),
cl::value_desc("N or 'auto'"), cl::init(0), cl::Hidden);

static cl::opt<std::string>
RemarksFilename("pass-remarks-output",
cl::desc("Output filename for pass remarks"),
cl::value_desc("filename"));

static cl::opt<std::string>
RemarksPasses("pass-remarks-filter",
cl::desc("Only record optimization remarks from passes whose "
"names match the given regular expression"),
cl::value_desc("regex"));

static cl::opt<std::string> RemarksFormat(
"pass-remarks-format",
cl::desc("The format used for serializing remarks (default: YAML)"),
cl::value_desc("format"), cl::init("yaml"));

static cl::list<std::string>
PassPlugins("load-pass-plugin",
cl::desc("Load passes from plugin library"));

static cl::opt<std::string> PassPipeline(
"passes",
cl::desc(
"A textual description of the pass pipeline. To have analysis passes "
"available before a certain pass, add 'require<foo-analysis>'. "
"'-passes' overrides the pass pipeline (but not all effects) from "
"specifying '--opt-level=O?' (O2 is the default) to "
"clang-linker-wrapper. Be sure to include the corresponding "
"'default<O?>' in '-passes'."));
static cl::alias PassPipeline2("p", cl::aliasopt(PassPipeline),
cl::desc("Alias for -passes"));

/// Path of the current binary.
static const char *LinkerExecutable;

Expand Down Expand Up @@ -628,6 +678,12 @@ std::unique_ptr<lto::LTO> createLTO(
Conf.CPU = Arch.str();
Conf.Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple);

Conf.RemarksFilename = RemarksFilename;
Conf.RemarksPasses = RemarksPasses;
Conf.RemarksWithHotness = RemarksWithHotness;
Conf.RemarksHotnessThreshold = RemarksHotnessThreshold;
Conf.RemarksFormat = RemarksFormat;

StringRef OptLevel = Args.getLastArgValue(OPT_opt_level, "O2");
Conf.MAttrs = Features;
std::optional<CodeGenOptLevel> CGOptLevelOrNone =
Expand All @@ -637,6 +693,17 @@ std::unique_ptr<lto::LTO> createLTO(
Conf.OptLevel = OptLevel[1] - '0';
Conf.DefaultTriple = Triple.getTriple();

// TODO: Should we complain about combining --opt-level and -passes, as opt
// does? That might be too limiting in clang-linker-wrapper, so for now we
// just warn in the help entry for -passes that the default<O?> corresponding
// to --opt-level=O? should be included there. The problem is that
// --opt-level produces effects in clang-linker-wrapper beyond what -passes
// appears to be able to achieve, so rejecting the combination of --opt-level
// and -passes would apparently make it impossible to combine those effects
// with a custom pass pipeline.
Conf.OptPipeline = PassPipeline;
Conf.PassPlugins = PassPlugins;

LTOError = false;
Conf.DiagHandler = diagnosticHandler;

Expand Down Expand Up @@ -1660,6 +1727,13 @@ int main(int Argc, char **Argv) {
NewArgv.push_back(Arg->getValue());
for (const opt::Arg *Arg : Args.filtered(OPT_offload_opt_eq_minus))
NewArgv.push_back(Args.MakeArgString(StringRef("-") + Arg->getValue()));
SmallVector<PassPlugin, 1> PluginList;
PassPlugins.setCallback([&](const std::string &PluginPath) {
auto Plugin = PassPlugin::Load(PluginPath);
if (!Plugin)
report_fatal_error(Plugin.takeError(), /*gen_crash_diag=*/false);
PluginList.emplace_back(Plugin.get());
});
cl::ParseCommandLineOptions(NewArgv.size(), &NewArgv[0]);

Verbose = Args.hasArg(OPT_verbose);
Expand Down
8 changes: 6 additions & 2 deletions clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,13 @@ def linker_arg_EQ : Joined<["--"], "linker-arg=">,

// Arguments for the LLVM backend.
def mllvm : Separate<["-"], "mllvm">, Flags<[WrapperOnlyOption]>,
MetaVarName<"<arg>">, HelpText<"Arguments passed to the LLVM invocation">;
MetaVarName<"<arg>">,
HelpText<"Arguments passed to LLVM, including Clang invocations, for which "
"the '-mllvm' prefix is preserved. Use '-mllvm --help' for a list "
"of options.">;
def offload_opt_eq_minus : Joined<["--", "-"], "offload-opt=-">, Flags<[HelpHidden, WrapperOnlyOption]>,
HelpText<"Options passed to LLVM">;
HelpText<"Options passed to LLVM, not including the Clang invocation. Use "
"'--offload-opt=--help' for a list of options.">;

// Standard linker flags also used by the linker wrapper.
def sysroot_EQ : Joined<["--"], "sysroot=">, HelpText<"Set the system root">;
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
${LOONGARCH64})
set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}
${HEXAGON} ${LOONGARCH64})
${HEXAGON} ${LOONGARCH64} ${SPARC} ${SPARCV9})
set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64}
${HEXAGON} ${LOONGARCH64})
set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/lib/builtins/riscv/restore.S
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

#if __riscv_xlen == 32

#ifndef __riscv_32e
#ifndef __riscv_abi_rve

.globl __riscv_restore_12
.type __riscv_restore_12,@function
Expand Down Expand Up @@ -109,7 +109,7 @@ __riscv_restore_0:

#elif __riscv_xlen == 64

#ifndef __riscv_64e
#ifndef __riscv_abi_rve

.globl __riscv_restore_12
.type __riscv_restore_12,@function
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/lib/builtins/riscv/save.S
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#if __riscv_xlen == 32

#ifndef __riscv_32e
#ifndef __riscv_abi_rve

.globl __riscv_save_12
.type __riscv_save_12,@function
Expand Down Expand Up @@ -115,7 +115,7 @@ __riscv_save_0:

#elif __riscv_xlen == 64

#ifndef __riscv_64e
#ifndef __riscv_abi_rve

.globl __riscv_save_12
.type __riscv_save_12,@function
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/msan/msan_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ void MsanTSDDtor(void *tsd) {
CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
return;
}
ScopedBlockSignals block(nullptr);
msan_current_thread = nullptr;
// Make sure that signal handler can not see a stale current thread pointer.
atomic_signal_fence(memory_order_seq_cst);
Expand Down
11 changes: 1 addition & 10 deletions compiler-rt/lib/nsan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ set(NSAN_SOURCES
nsan_suppressions.cpp
)

set(NSAN_PREINIT_SOURCES
nsan_preinit.cpp)

set(NSAN_HEADERS
nsan.h
nsan_flags.h
Expand Down Expand Up @@ -64,12 +61,6 @@ if(NOT APPLE)
ADDITIONAL_HEADERS ${NSAN_HEADERS}
CFLAGS ${NSAN_CFLAGS})

add_compiler_rt_object_libraries(RTNsan_preinit
ARCHS ${NSAN_SUPPORTED_ARCH}
SOURCES ${NSAN_PREINIT_SOURCES}
ADDITIONAL_HEADERS ${NSAN_HEADERS}
CFLAGS ${NSAN_CFLAGS})

file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "")
add_compiler_rt_object_libraries(RTNsan_dynamic_version_script_dummy
ARCHS ${NSAN_SUPPORTED_ARCH}
Expand All @@ -81,7 +72,7 @@ add_compiler_rt_runtime(
clang_rt.nsan
STATIC
ARCHS ${NSAN_SUPPORTED_ARCH}
OBJECT_LIBS RTNsan_preinit RTNsan
OBJECT_LIBS RTNsan
${NSAN_COMMON_RUNTIME_OBJECT_LIBS}
CFLAGS ${NSAN_CFLAGS}
PARENT_TARGET nsan)
Expand Down
7 changes: 6 additions & 1 deletion compiler-rt/lib/nsan/nsan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_shadow_args() {
bool __nsan::nsan_initialized;
bool __nsan::nsan_init_is_running;

extern "C" void __nsan_init() {
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_init() {
CHECK(!nsan_init_is_running);
if (nsan_initialized)
return;
Expand All @@ -801,3 +801,8 @@ extern "C" void __nsan_init() {
nsan_init_is_running = false;
nsan_initialized = true;
}

#if SANITIZER_CAN_USE_PREINIT_ARRAY
__attribute__((section(".preinit_array"),
used)) static void (*nsan_init_ptr)() = __nsan_init;
#endif
2 changes: 0 additions & 2 deletions compiler-rt/lib/nsan/nsan.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ using __sanitizer::uptr;
// Private nsan interface. Used e.g. by interceptors.
extern "C" {

void __nsan_init();

// This marks the shadow type of the given block of application memory as
// unknown.
// printf-free (see comment in nsan_interceptors.cc).
Expand Down
21 changes: 0 additions & 21 deletions compiler-rt/lib/nsan/nsan_preinit.cpp

This file was deleted.

2 changes: 2 additions & 0 deletions compiler-rt/lib/safestack/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ foreach(arch ${SAFESTACK_SUPPORTED_ARCH})
ARCHS ${arch}
SOURCES ${SAFESTACK_SOURCES}
$<TARGET_OBJECTS:RTInterception.${arch}>
OBJECT_LIBS RTSanitizerCommon
RTSanitizerCommonLibc
CFLAGS ${SAFESTACK_CFLAGS}
PARENT_TARGET safestack)
endforeach()
11 changes: 11 additions & 0 deletions compiler-rt/lib/safestack/safestack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,17 @@ INTERCEPTOR(int, pthread_create, pthread_t *thread,
pthread_attr_destroy(&tmpattr);
}

#if SANITIZER_SOLARIS
// Solaris pthread_attr_init initializes stacksize to 0 (the default), so
// hardcode the actual values as documented in pthread_create(3C).
if (size == 0)
# if defined(_LP64)
size = 2 * 1024 * 1024;
# else
size = 1024 * 1024;
# endif
#endif

SFS_CHECK(size);
size = RoundUpTo(size, kStackAlign);

Expand Down
35 changes: 28 additions & 7 deletions compiler-rt/lib/safestack/safestack_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "sanitizer_common/sanitizer_platform.h"

#include <dlfcn.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -68,6 +69,24 @@ static void *GetRealLibcAddress(const char *symbol) {
SFS_CHECK(real_##func);
#endif

#if SANITIZER_SOLARIS
# define _REAL(func) _##func
# define DEFINE__REAL(ret_type, func, ...) \
extern "C" ret_type _REAL(func)(__VA_ARGS__)

# if !defined(_LP64) && _FILE_OFFSET_BITS == 64
# define _REAL64(func) _##func##64
# else
# define _REAL64(func) _REAL(func)
# endif
# define DEFINE__REAL64(ret_type, func, ...) \
extern "C" ret_type _REAL64(func)(__VA_ARGS__)

DEFINE__REAL64(void *, mmap, void *a, size_t b, int c, int d, int e, off_t f);
DEFINE__REAL(int, munmap, void *a, size_t b);
DEFINE__REAL(int, mprotect, void *a, size_t b, int c);
#endif

using ThreadId = uint64_t;

inline ThreadId GetTid() {
Expand All @@ -91,11 +110,10 @@ inline int TgKill(pid_t pid, ThreadId tid, int sig) {
(void)pid;
return _REAL(_lwp_kill, tid, sig);
#elif SANITIZER_SOLARIS
# ifdef SYS_lwp_kill
return syscall(SYS_lwp_kill, tid, sig);
# else
return -1;
# endif
(void)pid;
errno = thr_kill(tid, sig);
// TgKill is expected to return -1 on error, not an errno.
return errno != 0 ? -1 : 0;
#elif SANITIZER_FREEBSD
return syscall(SYS_thr_kill2, pid, tid, sig);
#else
Expand All @@ -110,8 +128,7 @@ inline void *Mmap(void *addr, size_t length, int prot, int flags, int fd,
#elif SANITIZER_FREEBSD && (defined(__aarch64__) || defined(__x86_64__))
return (void *)__syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
#elif SANITIZER_SOLARIS
return (void *)(uintptr_t)syscall(SYS_mmap, addr, length, prot, flags, fd,
offset);
return _REAL64(mmap)(addr, length, prot, flags, fd, offset);
#else
return (void *)syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
#endif
Expand All @@ -121,6 +138,8 @@ inline int Munmap(void *addr, size_t length) {
#if SANITIZER_NETBSD
DEFINE__REAL(int, munmap, void *a, size_t b);
return _REAL(munmap, addr, length);
#elif SANITIZER_SOLARIS
return _REAL(munmap)(addr, length);
#else
return syscall(SYS_munmap, addr, length);
#endif
Expand All @@ -130,6 +149,8 @@ inline int Mprotect(void *addr, size_t length, int prot) {
#if SANITIZER_NETBSD
DEFINE__REAL(int, mprotect, void *a, size_t b, int c);
return _REAL(mprotect, addr, length, prot);
#elif SANITIZER_SOLARIS
return _REAL(mprotect)(addr, length, prot);
#else
return syscall(SYS_mprotect, addr, length, prot);
#endif
Expand Down
28 changes: 21 additions & 7 deletions compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ void InitializeShadowMemoryPlatform() {
#endif // #if !SANITIZER_GO

# if !SANITIZER_GO
static void ReExecIfNeeded() {
static void ReExecIfNeeded(bool ignore_heap) {
// Go maps shadow memory lazily and works fine with limited address space.
// Unlimited stack is not a problem as well, because the executable
// is not compiled with -pie.
Expand Down Expand Up @@ -266,7 +266,7 @@ static void ReExecIfNeeded() {

if (reexec) {
// Don't check the address space since we're going to re-exec anyway.
} else if (!CheckAndProtect(false, false, false)) {
} else if (!CheckAndProtect(false, ignore_heap, false)) {
// ASLR personality check.
// N.B. 'personality' is sometimes forbidden by sandboxes, so we only call
// this as a last resort (when the memory mapping is incompatible and TSan
Expand All @@ -290,10 +290,11 @@ static void ReExecIfNeeded() {
CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
reexec = true;
} else {
VReport(1,
"FATAL: ThreadSanitizer: memory layout is incompatible, "
"even though ASLR is disabled.\n"
"Please file a bug.\n");
Printf(
"FATAL: ThreadSanitizer: memory layout is incompatible, "
"even though ASLR is disabled.\n"
"Please file a bug.\n");
DumpProcessMap();
Die();
}
}
Expand Down Expand Up @@ -376,7 +377,8 @@ void InitializePlatformEarly() {
# endif

# if !SANITIZER_GO
ReExecIfNeeded();
// Heap has not been allocated yet
ReExecIfNeeded(false);
# endif
}

Expand All @@ -394,13 +396,25 @@ void InitializePlatform() {
# endif
}

// We called ReExecIfNeeded() in InitializePlatformEarly(), but there are
// intervening allocations that result in an edge case:
// 1) InitializePlatformEarly(): memory layout is compatible
// 2) Intervening allocations happen
// 3) InitializePlatform(): memory layout is incompatible and fails
// CheckAndProtect()
# if !SANITIZER_GO
// Heap has already been allocated
ReExecIfNeeded(true);
# endif

// Earlier initialization steps already re-exec'ed until we got a compatible
// memory layout, so we don't expect any more issues here.
if (!CheckAndProtect(true, true, true)) {
Printf(
"FATAL: ThreadSanitizer: unexpectedly found incompatible memory "
"layout.\n");
Printf("FATAL: Please file a bug.\n");
DumpProcessMap();
Die();
}

Expand Down
3 changes: 3 additions & 0 deletions compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
//
// UNSUPPORTED: android

// FIXME: SEGV on Ubuntu 24.04. Looking.
// UNSUPPORTED: linux

#include <assert.h>
#include <sanitizer/allocator_interface.h>
#include <sanitizer/hwasan_interface.h>
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/msan/Linux/sigandorset.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_msan -DLEFT_OK -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_msan -DRIGHT_OK -std=c++11 -O0 -g %s -o %t && not %run %t 2<&1 | FileCheck %s
// RUN: %clangxx_msan -DRIGHT_OK -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_msan -DLEFT_OK -DRIGHT_OK -std=c++11 -O0 -g %s -o %t && %run %t
// REQUIRES: !android

Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/safestack/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@
)
)

if config.host_os not in ["Linux", "FreeBSD", "NetBSD"]:
if config.host_os not in ["Linux", "FreeBSD", "NetBSD", "SunOS"]:
config.unsupported = True
4 changes: 3 additions & 1 deletion flang/include/flang/Common/Fortran-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
IgnoredDirective, HomonymousSpecific, HomonymousResult,
IgnoredIntrinsicFunctionType, PreviousScalarUse,
RedeclaredInaccessibleComponent, ImplicitShared, IndexVarRedefinition,
IncompatibleImplicitInterfaces, BadTypeForTarget)
IncompatibleImplicitInterfaces, BadTypeForTarget,
VectorSubscriptFinalization)

using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
Expand Down Expand Up @@ -142,6 +143,7 @@ class LanguageFeatureControl {
warnUsage_.set(UsageWarning::IndexVarRedefinition);
warnUsage_.set(UsageWarning::IncompatibleImplicitInterfaces);
warnUsage_.set(UsageWarning::BadTypeForTarget);
warnUsage_.set(UsageWarning::VectorSubscriptFinalization);
}
LanguageFeatureControl(const LanguageFeatureControl &) = default;

Expand Down
14 changes: 12 additions & 2 deletions flang/include/flang/Evaluate/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,16 @@ extern template semantics::UnorderedSymbolSet CollectSymbols(
extern template semantics::UnorderedSymbolSet CollectSymbols(
const Expr<SubscriptInteger> &);

// Collects Symbols of interest for the CUDA data transfer in an expression
template <typename A>
semantics::UnorderedSymbolSet CollectCudaSymbols(const A &);
extern template semantics::UnorderedSymbolSet CollectCudaSymbols(
const Expr<SomeType> &);
extern template semantics::UnorderedSymbolSet CollectCudaSymbols(
const Expr<SomeInteger> &);
extern template semantics::UnorderedSymbolSet CollectCudaSymbols(
const Expr<SubscriptInteger> &);

// Predicate: does a variable contain a vector-valued subscript (not a triplet)?
bool HasVectorSubscript(const Expr<SomeType> &);

Expand Down Expand Up @@ -1236,7 +1246,7 @@ bool CheckForCoindexedObject(parser::ContextualMessages &,
// Get the number of distinct symbols with CUDA attribute in the expression.
template <typename A> inline int GetNbOfCUDADeviceSymbols(const A &expr) {
semantics::UnorderedSymbolSet symbols;
for (const Symbol &sym : CollectSymbols(expr)) {
for (const Symbol &sym : CollectCudaSymbols(expr)) {
if (const auto *details =
sym.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()) {
if (details->cudaDataAttr() &&
Expand All @@ -1259,7 +1269,7 @@ template <typename A> inline bool HasCUDADeviceAttrs(const A &expr) {
inline bool HasCUDAImplicitTransfer(const Expr<SomeType> &expr) {
unsigned hostSymbols{0};
unsigned deviceSymbols{0};
for (const Symbol &sym : CollectSymbols(expr)) {
for (const Symbol &sym : CollectCudaSymbols(expr)) {
if (const auto *details =
sym.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()) {
if (details->cudaDataAttr() &&
Expand Down
3 changes: 2 additions & 1 deletion flang/include/flang/Evaluate/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,8 @@ int SelectedCharKind(const std::string &, int defaultKind);
std::optional<DynamicType> ComparisonType(
const DynamicType &, const DynamicType &);

bool IsInteroperableIntrinsicType(const DynamicType &,
// Returns nullopt for deferred, assumed, and non-constant lengths.
std::optional<bool> IsInteroperableIntrinsicType(const DynamicType &,
const common::LanguageFeatureControl * = nullptr,
bool checkCharLength = true);
bool IsCUDAIntrinsicType(const DynamicType &);
Expand Down
4 changes: 2 additions & 2 deletions flang/include/flang/Parser/provenance.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ class AllSources {
const std::string &message, const std::string &prefix,
llvm::raw_ostream::Colors color, bool echoSourceLine = false) const;
const SourceFile *GetSourceFile(
Provenance, std::size_t *offset = nullptr) const;
Provenance, std::size_t *offset = nullptr, bool topLevel = false) const;
const char *GetSource(ProvenanceRange) const;
std::optional<SourcePosition> GetSourcePosition(Provenance) const;
std::optional<ProvenanceRange> GetFirstFileProvenance() const;
std::string GetPath(Provenance) const; // __FILE__
std::string GetPath(Provenance, bool topLevel = false) const; // __FILE__
int GetLineNumber(Provenance) const; // __LINE__
Provenance CompilerInsertionProvenance(char ch);
ProvenanceRange IntersectionWithSourceFiles(ProvenanceRange) const;
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Semantics/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ inline const DerivedTypeSpec *DeclTypeSpec::AsDerived() const {
return const_cast<DeclTypeSpec *>(this)->AsDerived();
}

bool IsInteroperableIntrinsicType(
std::optional<bool> IsInteroperableIntrinsicType(
const DeclTypeSpec &, const common::LanguageFeatureControl &);

} // namespace Fortran::semantics
Expand Down
28 changes: 15 additions & 13 deletions flang/lib/Evaluate/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2831,7 +2831,8 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
}
}
} else if (!IsInteroperableIntrinsicType(
*type, &context.languageFeatures()) &&
*type, &context.languageFeatures())
.value_or(true) &&
context.languageFeatures().ShouldWarn(
common::UsageWarning::Interoperability)) {
context.messages().Say(at,
Expand Down Expand Up @@ -2933,24 +2934,25 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::HandleC_Loc(
context.messages().Say(arguments[0]->sourceLocation(),
"C_LOC() argument may not be zero-length character"_err_en_US);
} else if (typeAndShape->type().category() != TypeCategory::Derived &&
!IsInteroperableIntrinsicType(typeAndShape->type()) &&
!IsInteroperableIntrinsicType(typeAndShape->type()).value_or(true) &&
context.languageFeatures().ShouldWarn(
common::UsageWarning::Interoperability)) {
context.messages().Say(arguments[0]->sourceLocation(),
"C_LOC() argument has non-interoperable intrinsic type, kind, or length"_warn_en_US);
}

return SpecificCall{SpecificIntrinsic{"__builtin_c_loc"s,
characteristics::Procedure{
characteristics::FunctionResult{
DynamicType{GetBuiltinDerivedType(
builtinsScope_, "__builtin_c_ptr")}},
characteristics::DummyArguments{
characteristics::DummyArgument{"x"s,
characteristics::DummyDataObject{
std::move(*typeAndShape)}}},
characteristics::Procedure::Attrs{
characteristics::Procedure::Attr::Pure}}},
characteristics::DummyDataObject ddo{std::move(*typeAndShape)};
ddo.intent = common::Intent::In;
return SpecificCall{
SpecificIntrinsic{"__builtin_c_loc"s,
characteristics::Procedure{
characteristics::FunctionResult{
DynamicType{GetBuiltinDerivedType(
builtinsScope_, "__builtin_c_ptr")}},
characteristics::DummyArguments{
characteristics::DummyArgument{"x"s, std::move(ddo)}},
characteristics::Procedure::Attrs{
characteristics::Procedure::Attr::Pure}}},
std::move(arguments)};
}
}
Expand Down
29 changes: 29 additions & 0 deletions flang/lib/Evaluate/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,35 @@ template semantics::UnorderedSymbolSet CollectSymbols(
template semantics::UnorderedSymbolSet CollectSymbols(
const Expr<SubscriptInteger> &);

struct CollectCudaSymbolsHelper : public SetTraverse<CollectCudaSymbolsHelper,
semantics::UnorderedSymbolSet> {
using Base =
SetTraverse<CollectCudaSymbolsHelper, semantics::UnorderedSymbolSet>;
CollectCudaSymbolsHelper() : Base{*this} {}
using Base::operator();
semantics::UnorderedSymbolSet operator()(const Symbol &symbol) const {
return {symbol};
}
// Overload some of the operator() to filter out the symbols that are not
// of interest for CUDA data transfer logic.
semantics::UnorderedSymbolSet operator()(const Subscript &) const {
return {};
}
semantics::UnorderedSymbolSet operator()(const ProcedureRef &) const {
return {};
}
};
template <typename A>
semantics::UnorderedSymbolSet CollectCudaSymbols(const A &x) {
return CollectCudaSymbolsHelper{}(x);
}
template semantics::UnorderedSymbolSet CollectCudaSymbols(
const Expr<SomeType> &);
template semantics::UnorderedSymbolSet CollectCudaSymbols(
const Expr<SomeInteger> &);
template semantics::UnorderedSymbolSet CollectCudaSymbols(
const Expr<SubscriptInteger> &);

// HasVectorSubscript()
struct HasVectorSubscriptHelper
: public AnyTraverse<HasVectorSubscriptHelper, bool,
Expand Down
13 changes: 10 additions & 3 deletions flang/lib/Evaluate/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ std::optional<DynamicType> ComparisonType(
}
}

bool IsInteroperableIntrinsicType(const DynamicType &type,
std::optional<bool> IsInteroperableIntrinsicType(const DynamicType &type,
const common::LanguageFeatureControl *features, bool checkCharLength) {
switch (type.category()) {
case TypeCategory::Integer:
Expand All @@ -819,10 +819,17 @@ bool IsInteroperableIntrinsicType(const DynamicType &type,
case TypeCategory::Logical:
return type.kind() == 1; // C_BOOL
case TypeCategory::Character:
if (checkCharLength && type.knownLength().value_or(0) != 1) {
if (type.kind() != 1) { // C_CHAR
return false;
} else if (checkCharLength) {
if (type.knownLength()) {
return *type.knownLength() == 1;
} else {
return std::nullopt;
}
} else {
return true;
}
return type.kind() == 1 /* C_CHAR */;
default:
// Derived types are tested in Semantics/check-declarations.cpp
return false;
Expand Down
6 changes: 6 additions & 0 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,12 @@ static constexpr MathOperation mathOperations[] = {
{"atan", "catan", genFuncType<Ty::Complex<8>, Ty::Complex<8>>, genLibCall},
{"atan", RTNAME_STRING(CAtanF128), FuncTypeComplex16Complex16,
genLibF128Call},
{"atan", "atan2f", genFuncType<Ty::Real<4>, Ty::Real<4>, Ty::Real<4>>,
genMathOp<mlir::math::Atan2Op>},
{"atan", "atan2", genFuncType<Ty::Real<8>, Ty::Real<8>, Ty::Real<8>>,
genMathOp<mlir::math::Atan2Op>},
{"atan", RTNAME_STRING(Atan2F128), FuncTypeReal16Real16Real16,
genLibF128Call},
{"atan2", "atan2f", genFuncType<Ty::Real<4>, Ty::Real<4>, Ty::Real<4>>,
genMathOp<mlir::math::Atan2Op>},
{"atan2", "atan2", genFuncType<Ty::Real<8>, Ty::Real<8>, Ty::Real<8>>,
Expand Down
15 changes: 15 additions & 0 deletions flang/lib/Parser/preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "flang/Common/idioms.h"
#include "flang/Parser/characters.h"
#include "flang/Parser/message.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cinttypes>
Expand Down Expand Up @@ -289,6 +290,7 @@ void Preprocessor::DefineStandardMacros() {
// The values of these predefined macros depend on their invocation sites.
Define("__FILE__"s, "__FILE__"s);
Define("__LINE__"s, "__LINE__"s);
Define("__TIMESTAMP__"s, "__TIMESTAMP__"s);
}

void Preprocessor::Define(const std::string &macro, const std::string &value) {
Expand Down Expand Up @@ -377,6 +379,19 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement(
llvm::raw_string_ostream ss{buf};
ss << allSources_.GetLineNumber(prescanner.GetCurrentProvenance());
repl = ss.str();
} else if (name == "__TIMESTAMP__") {
auto path{allSources_.GetPath(
prescanner.GetCurrentProvenance(), /*topLevel=*/true)};
llvm::sys::fs::file_status status;
repl = "??? ??? ?? ??:??:?? ????";
if (!llvm::sys::fs::status(path, status)) {
auto modTime{llvm::sys::toTimeT(status.getLastModificationTime())};
if (std::string time{std::asctime(std::localtime(&modTime))};
time.size() > 1 && time[time.size() - 1] == '\n') {
time.erase(time.size() - 1); // clip terminal '\n'
repl = "\""s + time + '"';
}
}
}
if (!repl.empty()) {
ProvenanceRange insert{allSources_.AddCompilerInsertion(repl)};
Expand Down
17 changes: 11 additions & 6 deletions flang/lib/Parser/provenance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,19 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
}

const SourceFile *AllSources::GetSourceFile(
Provenance at, std::size_t *offset) const {
Provenance at, std::size_t *offset, bool topLevel) const {
const Origin &origin{MapToOrigin(at)};
return common::visit(common::visitors{
[&](const Inclusion &inc) {
if (offset) {
*offset = origin.covers.MemberOffset(at);
if (topLevel && !origin.replaces.empty()) {
return GetSourceFile(
origin.replaces.start(), offset, topLevel);
} else {
if (offset) {
*offset = origin.covers.MemberOffset(at);
}
return &inc.source;
}
return &inc.source;
},
[&](const Macro &) {
return GetSourceFile(
Expand Down Expand Up @@ -380,9 +385,9 @@ std::optional<ProvenanceRange> AllSources::GetFirstFileProvenance() const {
return std::nullopt;
}

std::string AllSources::GetPath(Provenance at) const {
std::string AllSources::GetPath(Provenance at, bool topLevel) const {
std::size_t offset{0};
const SourceFile *source{GetSourceFile(at, &offset)};
const SourceFile *source{GetSourceFile(at, &offset, topLevel)};
return source ? *source->GetSourcePosition(offset).path : ""s;
}

Expand Down
11 changes: 8 additions & 3 deletions flang/lib/Semantics/assignment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,14 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
const Scope &scope{context_.FindScope(lhsLoc)};
if (auto whyNot{WhyNotDefinable(lhsLoc, scope,
DefinabilityFlags{DefinabilityFlag::VectorSubscriptIsOk}, lhs)}) {
if (auto *msg{Say(lhsLoc,
"Left-hand side of assignment is not definable"_err_en_US)}) {
msg->Attach(std::move(*whyNot));
if (whyNot->IsFatal()) {
if (auto *msg{Say(lhsLoc,
"Left-hand side of assignment is not definable"_err_en_US)}) {
msg->Attach(
std::move(whyNot->set_severity(parser::Severity::Because)));
}
} else {
context_.Say(std::move(*whyNot));
}
}
auto rhsLoc{std::get<parser::Expr>(stmt.t).source};
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Semantics/check-allocate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
context
.Say(name_.source,
"Name in ALLOCATE statement is not definable"_err_en_US)
.Attach(std::move(*whyNot));
.Attach(std::move(whyNot->set_severity(parser::Severity::Because)));
return false;
}
}
Expand Down
22 changes: 16 additions & 6 deletions flang/lib/Semantics/check-call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,9 +679,14 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
flags.set(DefinabilityFlag::PointerDefinition);
}
if (auto whyNot{WhyNotDefinable(messages.at(), *scope, flags, actual)}) {
if (auto *msg{
messages.Say(std::move(*undefinableMessage), dummyName)}) {
msg->Attach(std::move(*whyNot));
if (whyNot->IsFatal()) {
if (auto *msg{
messages.Say(std::move(*undefinableMessage), dummyName)}) {
msg->Attach(
std::move(whyNot->set_severity(parser::Severity::Because)));
}
} else {
messages.Say(std::move(*whyNot));
}
}
}
Expand Down Expand Up @@ -1413,9 +1418,14 @@ static void CheckAssociated(evaluate::ActualArguments &arguments,
*scope,
DefinabilityFlags{DefinabilityFlag::PointerDefinition},
*pointerExpr)}) {
if (auto *msg{messages.Say(pointerArg->sourceLocation(),
"POINTER= argument of ASSOCIATED() is required by some other compilers to be a valid left-hand side of a pointer assignment statement"_port_en_US)}) {
msg->Attach(std::move(*whyNot));
if (whyNot->IsFatal()) {
if (auto *msg{messages.Say(pointerArg->sourceLocation(),
"POINTER= argument of ASSOCIATED() is required by some other compilers to be a valid left-hand side of a pointer assignment statement"_port_en_US)}) {
msg->Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
}
} else {
messages.Say(std::move(*whyNot));
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions flang/lib/Semantics/check-deallocate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,17 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
context_
.Say(name.source,
"Name in DEALLOCATE statement is not definable"_err_en_US)
.Attach(std::move(*whyNot));
.Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
} else if (auto whyNot{WhyNotDefinable(name.source,
context_.FindScope(name.source),
DefinabilityFlags{}, *symbol)}) {
// Catch problems with non-definability of the dynamic object
context_
.Say(name.source,
"Object in DEALLOCATE statement is not deallocatable"_err_en_US)
.Attach(std::move(*whyNot));
.Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
} else {
context_.CheckIndexVarRedefine(name);
}
Expand All @@ -77,14 +79,16 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
context_
.Say(source,
"Name in DEALLOCATE statement is not definable"_err_en_US)
.Attach(std::move(*whyNot));
.Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
} else if (auto whyNot{WhyNotDefinable(source,
context_.FindScope(source), DefinabilityFlags{},
*expr)}) {
context_
.Say(source,
"Object in DEALLOCATE statement is not deallocatable"_err_en_US)
.Attach(std::move(*whyNot));
.Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
}
}
},
Expand Down
8 changes: 5 additions & 3 deletions flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ void CheckHelper::CheckObjectEntity(
if (auto *msg{messages_.Say(
"'%s' may not be a local variable in a pure subprogram"_err_en_US,
symbol.name())}) {
msg->Attach(std::move(*whyNot));
msg->Attach(std::move(whyNot->set_severity(parser::Severity::Because)));
}
}
}
Expand Down Expand Up @@ -2982,7 +2982,8 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
msgs.Annex(std::move(bad));
}
} else if (!IsInteroperableIntrinsicType(
*type, context_.languageFeatures())) {
*type, context_.languageFeatures())
.value_or(false)) {
auto maybeDyType{evaluate::DynamicType::From(*type)};
if (type->category() == DeclTypeSpec::Logical) {
if (context_.ShouldWarn(common::UsageWarning::LogicalVsCBool)) {
Expand Down Expand Up @@ -3084,7 +3085,8 @@ parser::Messages CheckHelper::WhyNotInteroperableObject(const Symbol &symbol) {
type->characterTypeSpec().length().isDeferred()) {
// ok; F'2023 18.3.7 p2(6)
} else if (derived ||
IsInteroperableIntrinsicType(*type, context_.languageFeatures())) {
IsInteroperableIntrinsicType(*type, context_.languageFeatures())
.value_or(false)) {
// F'2023 18.3.7 p2(4,5)
} else if (type->category() == DeclTypeSpec::Logical) {
if (context_.ShouldWarn(common::UsageWarning::LogicalVsCBool) &&
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Semantics/check-do-forall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ class DoContext {
.Say(sourceLocation,
"'%s' may not be used as a DO variable"_err_en_US,
symbol->name())
.Attach(std::move(*why));
.Attach(std::move(why->set_severity(parser::Severity::Because)));
} else {
const DeclTypeSpec *symType{symbol->GetType()};
if (!symType) {
Expand Down
17 changes: 11 additions & 6 deletions flang/lib/Semantics/check-io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1034,11 +1034,16 @@ void IoChecker::CheckForDefinableVariable(
if (auto whyNot{WhyNotDefinable(at, context_.FindScope(at),
DefinabilityFlags{DefinabilityFlag::VectorSubscriptIsOk},
*expr)}) {
const Symbol *base{GetFirstSymbol(*expr)};
context_
.Say(at, "%s variable '%s' is not definable"_err_en_US, s,
(base ? base->name() : at).ToString())
.Attach(std::move(*whyNot));
if (whyNot->IsFatal()) {
const Symbol *base{GetFirstSymbol(*expr)};
context_
.Say(at, "%s variable '%s' is not definable"_err_en_US, s,
(base ? base->name() : at).ToString())
.Attach(
std::move(whyNot->set_severity(parser::Severity::Because)));
} else {
context_.Say(std::move(*whyNot));
}
}
}
}
Expand Down Expand Up @@ -1191,7 +1196,7 @@ void IoChecker::CheckNamelist(const Symbol &namelist, common::DefinedIo which,
.Say(namelistLocation,
"NAMELIST input group must not contain undefinable item '%s'"_err_en_US,
object.name())
.Attach(std::move(*why));
.Attach(std::move(why->set_severity(parser::Severity::Because)));
context_.SetError(namelist);
}
}
Expand Down
6 changes: 4 additions & 2 deletions flang/lib/Semantics/check-nullify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ void NullifyChecker::Leave(const parser::NullifyStmt &nullifyStmt) {
.Say(name.source,
"'%s' may not appear in NULLIFY"_err_en_US,
name.source)
.Attach(std::move(*whyNot));
.Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
}
}
},
Expand All @@ -44,7 +45,8 @@ void NullifyChecker::Leave(const parser::NullifyStmt &nullifyStmt) {
*checkedExpr)}) {
context_.messages()
.Say(at, "'%s' may not appear in NULLIFY"_err_en_US, at)
.Attach(std::move(*whyNot));
.Attach(std::move(
whyNot->set_severity(parser::Severity::Because)));
}
}
},
Expand Down
4 changes: 2 additions & 2 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2564,7 +2564,7 @@ void OmpStructureChecker::CheckIntentInPointerAndDefinable(
"Variable '%s' on the %s clause is not definable"_err_en_US,
symbol->name(),
parser::ToUpperCaseLetters(getClauseName(clause).str()))
.Attach(std::move(*msg));
.Attach(std::move(msg->set_severity(parser::Severity::Because)));
}
}
}
Expand Down Expand Up @@ -3369,7 +3369,7 @@ void OmpStructureChecker::CheckDefinableObjects(
"Variable '%s' on the %s clause is not definable"_err_en_US,
symbol->name(),
parser::ToUpperCaseLetters(getClauseName(clause).str()))
.Attach(std::move(*msg));
.Attach(std::move(msg->set_severity(parser::Severity::Because)));
}
}
}
Expand Down
83 changes: 48 additions & 35 deletions flang/lib/Semantics/definable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ template <typename... A>
static parser::Message BlameSymbol(parser::CharBlock at,
const parser::MessageFixedText &text, const Symbol &original, A &&...x) {
parser::Message message{at, text, original.name(), std::forward<A>(x)...};
message.set_severity(parser::Severity::Because);
message.set_severity(parser::Severity::Error);
evaluate::AttachDeclaration(message, original);
return message;
}
Expand Down Expand Up @@ -204,21 +204,19 @@ static std::optional<parser::Message> WhyNotDefinableLast(parser::CharBlock at,
if (auto dyType{evaluate::DynamicType::From(ultimate)}) {
if (!flags.test(DefinabilityFlag::PolymorphicOkInPure)) {
if (dyType->IsPolymorphic()) { // C1596
return BlameSymbol(at,
"'%s' is polymorphic in a pure subprogram"_because_en_US,
original);
return BlameSymbol(
at, "'%s' is polymorphic in a pure subprogram"_en_US, original);
}
}
if (const Symbol * impure{HasImpureFinal(ultimate)}) {
return BlameSymbol(at,
"'%s' has an impure FINAL procedure '%s'"_because_en_US, original,
impure->name());
return BlameSymbol(at, "'%s' has an impure FINAL procedure '%s'"_en_US,
original, impure->name());
}
if (const DerivedTypeSpec * derived{GetDerivedTypeSpec(dyType)}) {
if (!flags.test(DefinabilityFlag::PolymorphicOkInPure)) {
if (auto bad{FindPolymorphicAllocatableUltimateComponent(*derived)}) {
return BlameSymbol(at,
"'%s' has polymorphic component '%s' in a pure subprogram"_because_en_US,
"'%s' has polymorphic component '%s' in a pure subprogram"_en_US,
original, bad.BuildResultDesignatorName());
}
}
Expand All @@ -232,24 +230,33 @@ static std::optional<parser::Message> WhyNotDefinableLast(parser::CharBlock at,
static std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
const Scope &scope, DefinabilityFlags flags,
const evaluate::DataRef &dataRef) {
if (auto whyNot{
WhyNotDefinableBase(at, scope, flags, dataRef.GetFirstSymbol(),
std::holds_alternative<evaluate::SymbolRef>(dataRef.u),
DefinesComponentPointerTarget(dataRef, flags))}) {
return whyNot;
} else {
return WhyNotDefinableLast(at, scope, flags, dataRef.GetLastSymbol());
auto whyNotBase{
WhyNotDefinableBase(at, scope, flags, dataRef.GetFirstSymbol(),
std::holds_alternative<evaluate::SymbolRef>(dataRef.u),
DefinesComponentPointerTarget(dataRef, flags))};
if (!whyNotBase || !whyNotBase->IsFatal()) {
if (auto whyNotLast{
WhyNotDefinableLast(at, scope, flags, dataRef.GetLastSymbol())}) {
if (whyNotLast->IsFatal() || !whyNotBase) {
return whyNotLast;
}
}
}
return whyNotBase;
}

std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
const Scope &scope, DefinabilityFlags flags, const Symbol &original) {
if (auto base{WhyNotDefinableBase(at, scope, flags, original,
/*isWholeSymbol=*/true, /*isComponentPointerTarget=*/false)}) {
return base;
} else {
return WhyNotDefinableLast(at, scope, flags, original);
auto whyNotBase{WhyNotDefinableBase(at, scope, flags, original,
/*isWholeSymbol=*/true, /*isComponentPointerTarget=*/false)};
if (!whyNotBase || !whyNotBase->IsFatal()) {
if (auto whyNotLast{WhyNotDefinableLast(at, scope, flags, original)}) {
if (whyNotLast->IsFatal() || !whyNotBase) {
return whyNotLast;
}
}
}
return whyNotBase;
}

class DuplicatedSubscriptFinder
Expand Down Expand Up @@ -296,6 +303,7 @@ class DuplicatedSubscriptFinder
std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
const Scope &scope, DefinabilityFlags flags,
const evaluate::Expr<evaluate::SomeType> &expr) {
std::optional<parser::Message> portabilityWarning;
if (auto dataRef{evaluate::ExtractDataRef(expr, true, true)}) {
if (evaluate::HasVectorSubscript(expr)) {
if (flags.test(DefinabilityFlag::VectorSubscriptIsOk)) {
Expand Down Expand Up @@ -328,9 +336,14 @@ std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
}
}
if (anyRankMatch && !anyElemental) {
return parser::Message{at,
"Variable '%s' has a vector subscript and cannot be finalized by non-elemental subroutine '%s'"_because_en_US,
expr.AsFortran(), anyRankMatch->name()};
if (!portabilityWarning &&
scope.context().languageFeatures().ShouldWarn(
common::UsageWarning::VectorSubscriptFinalization)) {
portabilityWarning = parser::Message{at,
"Variable '%s' has a vector subscript and will be finalized by non-elemental subroutine '%s'"_port_en_US,
expr.AsFortran(), anyRankMatch->name()};
}
break;
}
const auto *parent{FindParentTypeSpec(*spec)};
spec = parent ? parent->AsDerived() : nullptr;
Expand All @@ -340,32 +353,33 @@ std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
if (!flags.test(DefinabilityFlag::DuplicatesAreOk) &&
DuplicatedSubscriptFinder{scope.context().foldingContext()}(expr)) {
return parser::Message{at,
"Variable has a vector subscript with a duplicated element"_because_en_US};
"Variable has a vector subscript with a duplicated element"_err_en_US};
}
} else {
return parser::Message{at,
"Variable '%s' has a vector subscript"_because_en_US,
expr.AsFortran()};
"Variable '%s' has a vector subscript"_err_en_US, expr.AsFortran()};
}
}
if (FindPureProcedureContaining(scope) &&
evaluate::ExtractCoarrayRef(expr)) {
return parser::Message(at,
"A pure subprogram may not define the coindexed object '%s'"_because_en_US,
"A pure subprogram may not define the coindexed object '%s'"_err_en_US,
expr.AsFortran());
}
return WhyNotDefinable(at, scope, flags, *dataRef);
if (auto whyNotDataRef{WhyNotDefinable(at, scope, flags, *dataRef)}) {
return whyNotDataRef;
}
} else if (evaluate::IsNullPointer(expr)) {
return parser::Message{
at, "'%s' is a null pointer"_because_en_US, expr.AsFortran()};
at, "'%s' is a null pointer"_err_en_US, expr.AsFortran()};
} else if (flags.test(DefinabilityFlag::PointerDefinition)) {
if (const auto *procDesignator{
std::get_if<evaluate::ProcedureDesignator>(&expr.u)}) {
// Defining a procedure pointer
if (const Symbol * procSym{procDesignator->GetSymbol()}) {
if (evaluate::ExtractCoarrayRef(expr)) { // C1027
return BlameSymbol(at,
"Procedure pointer '%s' may not be a coindexed object"_because_en_US,
"Procedure pointer '%s' may not be a coindexed object"_err_en_US,
*procSym, expr.AsFortran());
}
if (const auto *component{procDesignator->GetComponent()}) {
Expand All @@ -379,13 +393,12 @@ std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
}
}
return parser::Message{
at, "'%s' is not a definable pointer"_because_en_US, expr.AsFortran()};
at, "'%s' is not a definable pointer"_err_en_US, expr.AsFortran()};
} else if (!evaluate::IsVariable(expr)) {
return parser::Message{at,
"'%s' is not a variable or pointer"_because_en_US, expr.AsFortran()};
} else {
return std::nullopt;
return parser::Message{
at, "'%s' is not a variable or pointer"_err_en_US, expr.AsFortran()};
}
return portabilityWarning;
}

} // namespace Fortran::semantics
5 changes: 3 additions & 2 deletions flang/lib/Semantics/definable.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ using DefinabilityFlags =
common::EnumSet<DefinabilityFlag, DefinabilityFlag_enumSize>;

// Tests a symbol or LHS variable or pointer for definability in a given scope.
// When the entity is not definable, returns a "because:" Message suitable for
// attachment to an error message to explain why the entity cannot be defined.
// When the entity is not definable, returns a Message suitable for attachment
// to an error or warning message (as a "because: addendum) to explain why the
// entity cannot be defined.
// When the entity can be defined in that context, returns std::nullopt.
std::optional<parser::Message> WhyNotDefinable(
parser::CharBlock, const Scope &, DefinabilityFlags, const Symbol &);
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Semantics/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1584,7 +1584,8 @@ class ArrayConstructorContext {
std::optional<Expr<SubscriptInteger>> LengthIfGood() const {
if (type_) {
auto len{type_->LEN()};
if (len && IsConstantExpr(*len) && !ContainsAnyImpliedDoIndex(*len)) {
if (explicitType_ ||
(len && IsConstantExpr(*len) && !ContainsAnyImpliedDoIndex(*len))) {
return len;
}
}
Expand Down
5 changes: 3 additions & 2 deletions flang/lib/Semantics/pointer-assignment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ bool PointerAssignmentChecker::CheckLeftHandSide(const SomeExpr &lhs) {
DefinabilityFlags{DefinabilityFlag::PointerDefinition}, lhs)}) {
if (auto *msg{Say(
"The left-hand side of a pointer assignment is not definable"_err_en_US)}) {
msg->Attach(std::move(*whyNot));
msg->Attach(std::move(whyNot->set_severity(parser::Severity::Because)));
}
return false;
} else if (evaluate::IsAssumedRank(lhs)) {
Expand Down Expand Up @@ -226,7 +226,8 @@ bool PointerAssignmentChecker::Check(const SomeExpr &rhs) {
foldingContext_.messages().at(), scope_, {}, rhs)}) {
if (auto *msg{
Say("Pointer target is not a definable variable"_warn_en_US)}) {
msg->Attach(std::move(*because));
msg->Attach(
std::move(because->set_severity(parser::Severity::Because)));
}
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6554,7 +6554,7 @@ bool DeclarationVisitor::PassesLocalityChecks(
name.source, currScope(), DefinabilityFlags{}, symbol)}) {
SayWithReason(name, symbol,
"'%s' may not appear in a locality-spec because it is not definable"_err_en_US,
std::move(*whyNot));
std::move(whyNot->set_severity(parser::Severity::Because)));
return false;
}
return PassesSharedLocalityChecks(name, symbol);
Expand Down
9 changes: 6 additions & 3 deletions flang/lib/Semantics/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -891,10 +891,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const DeclTypeSpec &x) {
return o << x.AsFortran();
}

bool IsInteroperableIntrinsicType(
std::optional<bool> IsInteroperableIntrinsicType(
const DeclTypeSpec &type, const common::LanguageFeatureControl &features) {
auto dyType{evaluate::DynamicType::From(type)};
return dyType && IsInteroperableIntrinsicType(*dyType, &features);
if (auto dyType{evaluate::DynamicType::From(type)}) {
return IsInteroperableIntrinsicType(*dyType, &features);
} else {
return std::nullopt;
}
}

} // namespace Fortran::semantics
34 changes: 32 additions & 2 deletions flang/test/Lower/CUDA/cuda-data-transfer.cuf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ module mod1
type :: t1
integer :: i
end type

contains
function dev1(a)
integer, device :: a(:)
integer :: dev1
end function
end

subroutine sub1()
Expand Down Expand Up @@ -213,11 +219,35 @@ subroutine sub10(a, b)
res = a + b
end subroutine



! CHECK-LABEL: func.func @_QPsub10(
! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a"}

! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %1 {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub10Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: cuf.data_transfer %[[A]]#1 to %{{.*}}#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<i32>, !fir.ref<i32>
! CHECK-NOT: cuf.data_transfer

subroutine sub11(n)
integer :: n
real, dimension(10) :: h
real, dimension(n), device :: d
do i=1,10
h(i) = d(i)
end do
end subroutine

! CHECK-LABEL: func.func @_QPsub11
! CHECK: %[[RHS:.*]] = hlfir.designate %{{.*}} (%{{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
! CHECK: %[[LHS:.*]] = hlfir.designate %{{.*}} (%{{.*}}) : (!fir.ref<!fir.array<10xf32>>, i64) -> !fir.ref<f32>
! CHECK: cuf.data_transfer %[[RHS]] to %[[LHS]] {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<f32>, !fir.ref<f32>

subroutine sub12()
use mod1
integer, device :: a(10)
integer :: x
x = dev1(a)
end subroutine

! CHECK-LABEL: func.func @_QPsub12
! CHECK: %{{.*}} = fir.call @_QMmod1Pdev1
! CHECK: hlfir.assign
! CHECK-NOT: cuf.data_transfer
9 changes: 5 additions & 4 deletions flang/test/Lower/HLFIR/array-ctor-character.f90
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ subroutine test_set_length_sanitize(i, c1)
call takes_char([character(len=i):: c1])
end subroutine
! CHECK-LABEL: func.func @_QPtest_set_length_sanitize(
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare {{.*}}Ec1
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare {{.*}}Ei
! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare {{.*}}Ec1
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %arg0
! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_26:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_27:.*]] = arith.cmpi sgt, %[[VAL_25]], %[[VAL_26]] : i64
! CHECK: %[[VAL_28:.*]] = arith.select %[[VAL_27]], %[[VAL_25]], %[[VAL_26]] : i64
! CHECK: %[[VAL_29:.*]] = hlfir.set_length %[[VAL_6]]#0 len %[[VAL_28]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: %[[VAL_29:.*]] = hlfir.set_length %[[VAL_2]]#0 len %[[VAL_28]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,?>>
55 changes: 55 additions & 0 deletions flang/test/Lower/Intrinsics/atan.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
! Check that correct runtime calls are used.
! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck --check-prefixes=CHECK-RUNTIME %s
! RUN: %flang_fc1 -mllvm -math-runtime=precise -emit-fir %s -o - | FileCheck --check-prefixes=CHECK-RUNTIME %s

! Check that the correct math dialect operations are used.
! RUN: bbc -emit-fir %s -o - | FileCheck --check-prefixes=CHECK-NORMAL %s
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck --check-prefixes=CHECK-NORMAL %s

function test_real4(x)
real :: x, test_real4
test_real4 = atan(x)
end function

! CHECK-RUNTIME: {{%[A-Za-z0-9._]+}} = fir.call @atanf({{.*}}) {{.*}}: (f32) -> f32
! CHECK-NORMAL: {{%[A-Za-z0-9._]+}} = math.atan {{.*}} {{.*}}: f32

function test_real8(x)
real(8) :: x, test_real8
test_real8 = atan(x)
end function

! CHECK-RUNTIME: {{%[A-Za-z0-9._]+}} = fir.call @atan({{.*}}) {{.*}}: (f64) -> f64
! CHECK-NORMAL: {{%[A-Za-z0-9._]+}} = math.atan {{.*}} {{.*}}: f64

function test_complex4(x)
complex :: x, test_complex4
test_complex4 = atan(x)
end function

! CHECK-RUNTIME: {{%[A-Za-z0-9._]+}} = fir.call @catanf({{.*}}) {{.*}}: (!fir.complex<4>) -> !fir.complex<4>
! CHECK-NORMAL: {{%[A-Za-z0-9._]+}} = fir.call @catanf({{.*}}) {{.*}}: (!fir.complex<4>) -> !fir.complex<4>

function test_complex8(x)
complex(kind=8) :: x, test_complex8
test_complex8 = atan(x)
end function

! CHECK-RUNTIME: {{%[A-Za-z0-9._]+}} = fir.call @catan({{.*}}) {{.*}}: (!fir.complex<8>) -> !fir.complex<8>
! CHECK-NORMAL: {{%[A-Za-z0-9._]+}} = fir.call @catan({{.*}}) {{.*}}: (!fir.complex<8>) -> !fir.complex<8>

function test_real4_2(y, x)
real :: y, x, test_real4_2
test_real4_2 = atan(y, x)
end function

! CHECK-RUNTIME: {{%[A-Za-z0-9._]+}} = fir.call @atan2f({{.*}}) {{.*}}: (f32, f32) -> f32
! CHECK-NORMAL: {{%[A-Za-z0-9._]+}} = math.atan2 {{.*}} {{.*}}: f32

function test_real8_2(y, x)
real(8) :: y, x, test_real8_2
test_real8_2 = atan(y, x)
end function

! CHECK-RUNTIME: {{%[A-Za-z0-9._]+}} = fir.call @atan2({{.*}}) {{.*}}: (f64, f64) -> f64
! CHECK-NORMAL: {{%[A-Za-z0-9._]+}} = math.atan2 {{.*}} {{.*}}: f64
17 changes: 14 additions & 3 deletions flang/test/Lower/Intrinsics/atan_real16.f90
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@
! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s

function test_real16(x)
real(16) :: x, test_real16
test_real16 = atan(x)
end function real16

! CHECK-LABEL: @_QPtest_real16
! CHECK: fir.call @_FortranAAtanF128({{.*}}){{.*}}: (f128) -> f128
real(16) :: a, b
b = atan(a)
end

function test_real16_2(y, x)
real(16) :: y, x, test_real16
test_real16 = atan(y, x)
end function real16_2

! CHECK-LABEL: @_QPtest_real16
! CHECK: fir.call @_FortranAAtan2F128({{.*}}){{.*}}: (f128, f128) -> f128
12 changes: 12 additions & 0 deletions flang/test/Preprocessing/timestamp.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
!RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
!CHECK: INTEGER, PARAMETER :: tslen = 24_4
!CHECK: LOGICAL, PARAMETER :: tsspaces = .true._4
!CHECK: LOGICAL, PARAMETER :: tscolons = .true._4

integer, parameter :: tsLen = len(__TIMESTAMP__)
character(tsLen), parameter :: ts = __TIMESTAMP__
integer, parameter :: spaces(*) = [4, 8, 11, 20]
integer, parameter :: colons(*) = [14, 17]
logical, parameter :: tsSpaces = all([character(1)::(ts(spaces(j):spaces(j)),j=1,size(spaces))] == ' ')
logical, parameter :: tsColons = all([character(1)::(ts(colons(j):colons(j)),j=1,size(colons))] == ':')
end
1 change: 0 additions & 1 deletion flang/test/Semantics/array-constr-len.f90
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@ subroutine subr(s,n)
print *, [(s(1:j),j=1,0)]
print *, [(s(1:1),j=1,0)] ! ok
print *, [character(2)::(s(1:n),j=1,0)] ! ok
!ERROR: Array constructor implied DO loop has no iterations and indeterminate character length
print *, [character(n)::(s(1:n),j=1,0)]
end
9 changes: 7 additions & 2 deletions flang/test/Semantics/c_loc01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module m
contains
subroutine subr
end
subroutine test(assumedType, poly, nclen)
subroutine test(assumedType, poly, nclen, n)
type(*), target :: assumedType
class(*), target :: poly
type(c_ptr) cp
Expand All @@ -19,9 +19,12 @@ subroutine test(assumedType, poly, nclen)
real, target :: arr(3)
type(hasLen(1)), target :: clen
type(hasLen(*)), target :: nclen
integer, intent(in) :: n
character(2), target :: ch
real :: arr1(purefun1(c_loc(targ))) ! ok
real :: arr2(purefun2(c_funloc(subr))) ! ok
character(:), allocatable, target :: deferred
character(n), pointer :: p2ch
!ERROR: C_LOC() argument must be a data pointer or target
cp = c_loc(notATarget)
!ERROR: C_LOC() argument must be a data pointer or target
Expand All @@ -39,7 +42,9 @@ subroutine test(assumedType, poly, nclen)
cp = c_loc(ch(2:1))
!WARNING: C_LOC() argument has non-interoperable intrinsic type, kind, or length
cp = c_loc(ch)
cp = c_loc(ch(1:1)) ! ok)
cp = c_loc(ch(1:1)) ! ok
cp = c_loc(deferred) ! ok
cp = c_loc(p2ch) ! ok
!ERROR: PRIVATE name '__address' is only accessible within module '__fortran_builtins'
cp = c_ptr(0)
!ERROR: PRIVATE name '__address' is only accessible within module '__fortran_builtins'
Expand Down
8 changes: 3 additions & 5 deletions flang/test/Semantics/definable02.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror

! Ensure that FINAL subroutine can be called for array with vector-valued
! subscript.
Expand Down Expand Up @@ -36,11 +36,9 @@ program test
x1(:) = [t1()] ! ok
x2(:) = [t2()] ! ok
x3(:) = [t3()] ! ok
!ERROR: Left-hand side of assignment is not definable
!BECAUSE: Variable 'x1([INTEGER(8)::1_8])' has a vector subscript and cannot be finalized by non-elemental subroutine 'f1'
!PORTABILITY: Variable 'x1([INTEGER(8)::1_8])' has a vector subscript and will be finalized by non-elemental subroutine 'f1'
x1([1]) = [t1()]
!ERROR: Left-hand side of assignment is not definable
!BECAUSE: Variable 'x2([INTEGER(8)::1_8])' has a vector subscript and cannot be finalized by non-elemental subroutine 'f2'
!PORTABILITY: Variable 'x2([INTEGER(8)::1_8])' has a vector subscript and will be finalized by non-elemental subroutine 'f2'
x2([1]) = [t2()]
x3([1]) = [t3()] ! ok
end
5 changes: 2 additions & 3 deletions flang/test/Semantics/final03.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror
! PDT sensitivity of FINAL subroutines
module m
type :: pdt(k)
Expand All @@ -20,8 +20,7 @@ program test
type(pdt(1)) x1(1)
type(pdt(2)) x2(1)
type(pdt(3)) x3(1)
!ERROR: Left-hand side of assignment is not definable
!BECAUSE: Variable 'x1([INTEGER(8)::1_8])' has a vector subscript and cannot be finalized by non-elemental subroutine 'finalarr'
!PORTABILITY: Variable 'x1([INTEGER(8)::1_8])' has a vector subscript and will be finalized by non-elemental subroutine 'finalarr'
x1([1]) = pdt(1)()
x2([1]) = pdt(2)() ! ok, doesn't match either
x3([1]) = pdt(3)() ! ok, calls finalElem
Expand Down
5 changes: 3 additions & 2 deletions libc/benchmarks/LibcDefaultImplementations.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include "LibcFunctionPrototypes.h"
#include "src/__support/macros/config.h"
#include "llvm/ADT/ArrayRef.h"
#include <cstddef>

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

extern void *memcpy(void *__restrict, const void *__restrict, size_t);
extern void *memmove(void *, const void *, size_t);
Expand All @@ -11,7 +12,7 @@ extern void bzero(void *, size_t);
extern int memcmp(const void *, const void *, size_t);
extern int bcmp(const void *, const void *, size_t);

} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

// List of implementations to test.

Expand Down
5 changes: 3 additions & 2 deletions libc/benchmarks/LibcMemoryBenchmarkMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "LibcBenchmark.h"
#include "LibcMemoryBenchmark.h"
#include "MemorySizeDistributions.h"
#include "src/__support/macros/config.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
Expand All @@ -21,7 +22,7 @@
#include <cstring>
#include <unistd.h>

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

extern void *memcpy(void *__restrict, const void *__restrict, size_t);
extern void *memmove(void *, const void *, size_t);
Expand All @@ -30,7 +31,7 @@ extern void bzero(void *, size_t);
extern int memcmp(const void *, const void *, size_t);
extern int bcmp(const void *, const void *, size_t);

} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

namespace llvm {
namespace libc_benchmarks {
Expand Down
5 changes: 3 additions & 2 deletions libc/benchmarks/automemcpy/lib/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
// function at the end of the file.

#include "automemcpy/CodeGen.h"
#include "src/__support/macros/config.h"
#include <cassert>
#include <llvm/ADT/STLExtras.h>
#include <llvm/ADT/StringSet.h>
Expand Down Expand Up @@ -542,11 +543,11 @@ static void Serialize(raw_ostream &Stream,
Stream << "using llvm::libc_benchmarks::MemmoveConfiguration;\n";
Stream << "using llvm::libc_benchmarks::MemsetConfiguration;\n";
Stream << "\n";
Stream << "namespace LIBC_NAMESPACE {\n";
Stream << "namespace LIBC_NAMESPACE_DECL {\n";
Stream << "\n";
codegen::functions::Serialize(Stream, Descriptors);
Stream << "\n";
Stream << "} // namespace LIBC_NAMESPACE\n";
Stream << "} // namespace LIBC_NAMESPACE_DECL\n";
Stream << "\n";
Stream << "namespace llvm {\n";
Stream << "namespace automemcpy {\n";
Expand Down
5 changes: 3 additions & 2 deletions libc/benchmarks/automemcpy/unittests/CodeGenTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "automemcpy/CodeGen.h"
#include "automemcpy/RandomFunctionGenerator.h"
#include "src/__support/macros/config.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <optional>
Expand Down Expand Up @@ -63,7 +64,7 @@ using llvm::libc_benchmarks::MemcpyConfiguration;
using llvm::libc_benchmarks::MemmoveConfiguration;
using llvm::libc_benchmarks::MemsetConfiguration;

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

static void memcpy_0xE00E29EE73994E2B(char *__restrict dst, const char *__restrict src, size_t size) {
using namespace LIBC_NAMESPACE::x86;
Expand Down Expand Up @@ -134,7 +135,7 @@ static void bzero_0x475977492C218AD4(char * dst, size_t size) {
return splat_set<Align<_32,Arg::Dst>::Then<Loop<_32>>>(dst, 0, size);
}

} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

namespace llvm {
namespace automemcpy {
Expand Down
5 changes: 3 additions & 2 deletions libc/benchmarks/gpu/BenchmarkLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
#include "src/__support/CPP/string_view.h"
#include "src/__support/OSUtil/io.h" // write_to_stderr
#include "src/__support/big_int.h" // is_big_int
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
#include "src/__support/uint128.h"

#include <stdint.h>

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {
namespace benchmarks {

// cpp::string_view specialization
Expand Down Expand Up @@ -94,4 +95,4 @@ template BenchmarkLogger &BenchmarkLogger::operator<< <UInt<320>>(UInt<320>);
BenchmarkLogger log;

} // namespace benchmarks
} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL
6 changes: 4 additions & 2 deletions libc/benchmarks/gpu/BenchmarkLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#ifndef LLVM_LIBC_BENCHMARKS_GPU_BENCHMARKLOGGER_H
#define LLVM_LIBC_BENCHMARKS_GPU_BENCHMARKLOGGER_H

namespace LIBC_NAMESPACE {
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {
namespace benchmarks {

// A class to log to standard output in the context of hermetic tests.
Expand All @@ -22,6 +24,6 @@ struct BenchmarkLogger {
extern BenchmarkLogger log;

} // namespace benchmarks
} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

#endif /* LLVM_LIBC_BENCHMARKS_GPU_BENCHMARKLOGGER_H */
12 changes: 6 additions & 6 deletions libc/benchmarks/gpu/LibcGpuBenchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
#include "src/__support/FPUtil/sqrt.h"
#include "src/__support/GPU/utils.h"
#include "src/__support/fixedvector.h"
#include "src/__support/macros/config.h"
#include "src/time/gpu/time_utils.h"

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {
namespace benchmarks {

FixedVector<Benchmark *, 64> benchmarks;
Expand Down Expand Up @@ -52,11 +53,10 @@ void Benchmark::run_benchmarks() {
uint64_t id = gpu::get_thread_id();
gpu::sync_threads();

for (Benchmark *b : benchmarks)
for (Benchmark *b : benchmarks) {
results[id] = b->run();
gpu::sync_threads();
if (id == 0) {
for (Benchmark const *b : benchmarks) {
gpu::sync_threads();
if (id == 0) {
BenchmarkResult all_results = reduce_results(results);
constexpr auto GREEN = "\033[32m";
constexpr auto RESET = "\033[0m";
Expand Down Expand Up @@ -136,4 +136,4 @@ BenchmarkResult benchmark(const BenchmarkOptions &options,
};

} // namespace benchmarks
} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL
5 changes: 3 additions & 2 deletions libc/benchmarks/gpu/LibcGpuBenchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
#include "src/__support/CPP/functional.h"
#include "src/__support/CPP/limits.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/macros/config.h"
#include "src/time/clock.h"

#include <stdint.h>

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

namespace benchmarks {

Expand Down Expand Up @@ -99,7 +100,7 @@ class Benchmark {
const cpp::string_view get_name() const { return name; }
};
} // namespace benchmarks
} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

#define BENCHMARK(SuiteName, TestName, Func) \
LIBC_NAMESPACE::benchmarks::Benchmark SuiteName##_##TestName##_Instance( \
Expand Down
14 changes: 13 additions & 1 deletion libc/benchmarks/gpu/src/ctype/isalnum_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,16 @@ uint64_t BM_IsAlnum() {
char x = 'c';
return LIBC_NAMESPACE::latency(LIBC_NAMESPACE::isalnum, x);
}
BENCHMARK(LlvmLibcIsAlNumGpuBenchmark, IsAlnumWrapper, BM_IsAlnum);
BENCHMARK(LlvmLibcIsAlNumGpuBenchmark, IsAlnum, BM_IsAlnum);

uint64_t BM_IsAlnumCapital() {
char x = 'A';
return LIBC_NAMESPACE::latency(LIBC_NAMESPACE::isalnum, x);
}
BENCHMARK(LlvmLibcIsAlNumGpuBenchmark, IsAlnumCapital, BM_IsAlnumCapital);

uint64_t BM_IsAlnumNotAlnum() {
char x = '{';
return LIBC_NAMESPACE::latency(LIBC_NAMESPACE::isalnum, x);
}
BENCHMARK(LlvmLibcIsAlNumGpuBenchmark, IsAlnumNotAlnum, BM_IsAlnumNotAlnum);
4 changes: 2 additions & 2 deletions libc/benchmarks/gpu/timing/amdgpu/timing.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
else \
asm("" ::"v"(VARIABLE))

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

// Returns the overhead associated with calling the profiling region. This
// allows us to substract the constant-time overhead from the latency to
Expand Down Expand Up @@ -107,6 +107,6 @@ template <typename F, typename T1, typename T2>
return stop - start;
}

} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_UTILS_GPU_TIMING_AMDGPU
4 changes: 2 additions & 2 deletions libc/benchmarks/gpu/timing/nvptx/timing.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

#include <stdint.h>

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

// Returns the overhead associated with calling the profiling region. This
// allows us to substract the constant-time overhead from the latency to
Expand Down Expand Up @@ -94,6 +94,6 @@ static LIBC_INLINE uint64_t latency(F f, T1 t1, T2 t2) {

return stop - start;
}
} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_UTILS_GPU_TIMING_NVPTX
10 changes: 5 additions & 5 deletions libc/cmake/modules/LLVMLibCObjectRules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ function(create_object_library fq_target_name)
endif()
endif()

if(fq_deps_list)
add_dependencies(${fq_target_name} ${fq_deps_list})
# Add deps as link libraries to inherit interface compile and link options.
target_link_libraries(${fq_target_name} PUBLIC ${fq_deps_list})
endif()
list(APPEND fq_deps_list libc.src.__support.macros.config)
list(REMOVE_DUPLICATES fq_deps_list)
add_dependencies(${fq_target_name} ${fq_deps_list})
# Add deps as link libraries to inherit interface compile and link options.
target_link_libraries(${fq_target_name} PUBLIC ${fq_deps_list})

set_target_properties(
${fq_target_name}
Expand Down
5 changes: 0 additions & 5 deletions libc/config/gpu/api.td
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@ def FenvAPI: PublicAPI<"fenv.h"> {
}

def StdIOAPI : PublicAPI<"stdio.h"> {
let Macros = [
SimpleMacroDef<"_IOFBF", "0">,
SimpleMacroDef<"_IOLBF", "1">,
SimpleMacroDef<"_IONBF", "2">,
];
let Types = [
"FILE",
"off_t",
Expand Down
4 changes: 4 additions & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.round
libc.src.math.roundf
libc.src.math.roundl
libc.src.math.roundeven
libc.src.math.roundevenf
libc.src.math.roundevenl
libc.src.math.scalbn
libc.src.math.scalbnf
libc.src.math.scalbnl
Expand Down Expand Up @@ -622,6 +625,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.remquof128
libc.src.math.rintf128
libc.src.math.roundf128
libc.src.math.roundevenf128
libc.src.math.scalbnf128
libc.src.math.sqrtf128
libc.src.math.truncf128
Expand Down
3 changes: 0 additions & 3 deletions libc/config/linux/api.td
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ def StdIOAPI : PublicAPI<"stdio.h"> {
SimpleMacroDef<"stderr", "stderr">,
SimpleMacroDef<"stdin", "stdin">,
SimpleMacroDef<"stdout", "stdout">,
SimpleMacroDef<"_IOFBF", "0">,
SimpleMacroDef<"_IOLBF", "1">,
SimpleMacroDef<"_IONBF", "2">,
];
let Types = [
"FILE",
Expand Down
5 changes: 3 additions & 2 deletions libc/config/linux/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
#ifndef LLVM_LIBC_CONFIG_LINUX_APP_H
#define LLVM_LIBC_CONFIG_LINUX_APP_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"

#include <stdint.h>

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

// Data structure to capture properties of the linux/ELF TLS image.
struct TLSImage {
Expand Down Expand Up @@ -104,6 +105,6 @@ void cleanup_tls(uintptr_t tls_addr, uintptr_t tls_size);
// Set the thread pointer for the current thread.
bool set_thread_ptr(uintptr_t val);

} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_CONFIG_LINUX_APP_H
14 changes: 7 additions & 7 deletions libc/docs/dev/clang_tidy_checks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ implementation-in-namespace
---------------------------

It is part of our implementation standards that all implementation pieces live
under the ``LIBC_NAMESPACE`` namespace. This prevents pollution of the global
namespace. Without a formal check to ensure this, an implementation might
compile and pass unit tests, but not produce a usable libc function.
under the ``LIBC_NAMESPACE_DECL`` namespace. This prevents pollution of the
global namespace. Without a formal check to ensure this, an implementation
might compile and pass unit tests, but not produce a usable libc function.

This check that ensures any function call resolves to a function within the
``LIBC_NAMESPACE`` namespace.
``LIBC_NAMESPACE_DECL`` namespace.

.. code-block:: c++

// Correct: implementation inside the correct namespace.
namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {
void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {}
// Namespaces within LIBC_NAMESPACE namespace are allowed.
namespace inner{
Expand Down Expand Up @@ -87,7 +87,7 @@ are always external and can be intercepted.

.. code-block:: c++

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

// Allow calls with the fully qualified name.
LIBC_NAMESPACE::strlen("hello");
Expand All @@ -104,4 +104,4 @@ are always external and can be intercepted.
// Allow calling into specific global functions (explained above)
::malloc(10);

} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL
5 changes: 3 additions & 2 deletions libc/fuzzing/__support/hashtable_fuzz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
#include "include/llvm-libc-types/ENTRY.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/HashTable/table.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {

// A fuzzing payload starts with
// - uint16_t: initial capacity for table A
Expand Down Expand Up @@ -179,4 +180,4 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
return 0;
}

} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL
10 changes: 10 additions & 0 deletions libc/hdr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ add_proxy_header_library(
libc.include.signal
)

add_proxy_header_library(
stdio_macros
HDRS
stdio_macros.h
FULL_BUILD_DEPENDS
libc.include.stdio
libc.include.llvm-libc-macros.stdio_macros
libc.include.llvm-libc-macros.file_seek_macros
)

add_proxy_header_library(
sys_epoll_macros
HDRS
Expand Down
23 changes: 23 additions & 0 deletions libc/hdr/stdio_macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===-- Definition of macros from stdio.h --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_HDR_STDIO_MACROS_H
#define LLVM_LIBC_HDR_STDIO_MACROS_H

#ifdef LIBC_FULL_BUILD

#include "include/llvm-libc-macros/file-seek-macros.h"
#include "include/llvm-libc-macros/stdio-macros.h"

#else // Overlay mode

#include <stdio.h>

#endif // LLVM_LIBC_FULL_BUILD

#endif // LLVM_LIBC_HDR_STDIO_MACROS_H
27 changes: 27 additions & 0 deletions libc/hdr/types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,30 @@ add_proxy_header_library(
libc.include.llvm-libc-types.struct_sigaction
libc.include.signal
)

add_proxy_header_library(
FILE
HDRS
FILE.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.FILE
libc.include.stdio
)

add_proxy_header_library(
off_t
HDRS
off_t.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.off_t
libc.include.stdio
)

add_proxy_header_library(
cookie_io_functions_t
HDRS
cookie_io_functions_t.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.cookie_io_functions_t
libc.include.stdio
)
22 changes: 22 additions & 0 deletions libc/hdr/types/FILE.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Proxy for FILE ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_HDR_TYPES_FILE_H
#define LLVM_LIBC_HDR_TYPES_FILE_H

#ifdef LIBC_FULL_BUILD

#include "include/llvm-libc-types/FILE.h"

#else // Overlay mode

#include <stdio.h>

#endif // LLVM_LIBC_FULL_BUILD

#endif // LLVM_LIBC_HDR_TYPES_FILE_H
22 changes: 22 additions & 0 deletions libc/hdr/types/cookie_io_functions_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Proxy for cookie_io_functions_t -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_HDR_TYPES_COOKIE_IO_FUNCTIONS_T_H
#define LLVM_LIBC_HDR_TYPES_COOKIE_IO_FUNCTIONS_T_H

#ifdef LIBC_FULL_BUILD

#include "include/llvm-libc-types/cookie_io_functions_t.h"

#else // Overlay mode

#include <stdio.h>

#endif // LLVM_LIBC_FULL_BUILD

#endif // LLVM_LIBC_HDR_TYPES_COOKIE_IO_FUNCTIONS_T_H
22 changes: 22 additions & 0 deletions libc/hdr/types/off_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Proxy for off_t ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_HDR_TYPES_OFF_T_H
#define LLVM_LIBC_HDR_TYPES_OFF_T_H

#ifdef LIBC_FULL_BUILD

#include "include/llvm-libc-types/off_t.h"

#else // Overlay mode

#include <stdio.h>

#endif // LLVM_LIBC_FULL_BUILD

#endif // LLVM_LIBC_HDR_TYPES_OFF_T_H
4 changes: 4 additions & 0 deletions libc/include/llvm-libc-macros/stdio-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@

#define BUFSIZ 1024

#define _IONBF 2
#define _IOLBF 1
#define _IOFBF 0

#endif // LLVM_LIBC_MACROS_STDIO_MACROS_H
6 changes: 3 additions & 3 deletions libc/newhdrgen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
if(LLVM_LIBC_FULL_BUILD)

enable_testing()

set(NEWHDGEN_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests)
set(TEST_OUTPUT_DIR ${CMAKE_BINARY_DIR}/newhdrgen/output)

add_test(
NAME newhdrgen_integration_test
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR} python3 ${NEWHDGEN_TESTS_DIR}/test_integration.py
COMMAND python3 ${NEWHDGEN_TESTS_DIR}/test_integration.py --output_dir ${TEST_OUTPUT_DIR}
)

add_custom_target(check-newhdrgen
COMMAND ${CMAKE_CTEST_COMMAND} -R newhdrgen_integration_test
COMMAND ${CMAKE_CTEST_COMMAND} -R newhdrgen_integration_test --output-on-failure
)

message(STATUS "Integration test for newhdrgen added.")
Expand Down
42 changes: 0 additions & 42 deletions libc/newhdrgen/tests/output/test_small.h

This file was deleted.

23 changes: 12 additions & 11 deletions libc/newhdrgen/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,14 @@
from pathlib import Path
import os
import argparse
import sys


class TestHeaderGenIntegration(unittest.TestCase):
def setUp(self):
parser = argparse.ArgumentParser(
description="TestHeaderGenIntegration arguments"
)
parser.add_argument(
"--output_dir", type=str, help="Output directory for generated headers"
)
args, _ = parser.parse_known_args()
output_dir_env = os.getenv("TEST_OUTPUT_DIR")

self.output_dir = Path(
args.output_dir
if args.output_dir
else output_dir_env if output_dir_env else "libc/newhdrgen/tests/output"
args.output_dir if args.output_dir else "libc/newhdrgen/tests/output"
)

self.maxDiff = None
Expand Down Expand Up @@ -71,4 +62,14 @@ def test_generate_header(self):


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="TestHeaderGenIntegration arguments")
parser.add_argument(
"--output_dir", type=str, help="Output directory for generated headers"
)
args, remaining_argv = parser.parse_known_args()

TestHeaderGenIntegration.output_dir = args.output_dir

sys.argv[1:] = remaining_argv

unittest.main()
6 changes: 0 additions & 6 deletions libc/newhdrgen/yaml/stdio.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
header: stdio.h
macros:
- macro_name: _IONBF
macro_value: 2
- macro_name: _IOLBF
macro_value: 1
- macro_name: _IOFBF
macro_value: 0
- macro_name: stdout
macro_value: stdout
- macro_name: stdin
Expand Down
5 changes: 3 additions & 2 deletions libc/src/__support/CPP/algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_ALGORITHM_H

#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {
namespace cpp {

template <class T> LIBC_INLINE constexpr const T &max(const T &a, const T &b) {
Expand All @@ -41,6 +42,6 @@ LIBC_INLINE constexpr bool all_of(InputIt first, InputIt last, UnaryPred p) {
}

} // namespace cpp
} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_CPP_ALGORITHM_H
5 changes: 3 additions & 2 deletions libc/src/__support/CPP/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@

#include "src/__support/CPP/iterator.h" // reverse_iterator
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include <stddef.h> // For size_t.

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {
namespace cpp {

template <class T, size_t N> struct array {
Expand Down Expand Up @@ -74,6 +75,6 @@ template <class T, size_t N> struct array {
};

} // namespace cpp
} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_CPP_ARRAY_H
5 changes: 3 additions & 2 deletions libc/src/__support/CPP/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_ATOMIC_H

#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"

#include "type_traits.h"

namespace LIBC_NAMESPACE {
namespace LIBC_NAMESPACE_DECL {
namespace cpp {

enum class MemoryOrder : int {
Expand Down Expand Up @@ -211,6 +212,6 @@ LIBC_INLINE void atomic_signal_fence([[maybe_unused]] MemoryOrder mem_ord) {
}

} // namespace cpp
} // namespace LIBC_NAMESPACE
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_CPP_ATOMIC_H
7 changes: 5 additions & 2 deletions libc/src/__support/CPP/bit.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
#include "src/__support/CPP/limits.h" // numeric_limits
#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/sanitizer.h"

#include <stdint.h>

namespace LIBC_NAMESPACE::cpp {
namespace LIBC_NAMESPACE_DECL {
namespace cpp {

#if __has_builtin(__builtin_memcpy_inline)
#define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
Expand Down Expand Up @@ -290,6 +292,7 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll)
#endif // __builtin_popcountg
#undef ADD_SPECIALIZATION

} // namespace LIBC_NAMESPACE::cpp
} // namespace cpp
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
7 changes: 5 additions & 2 deletions libc/src/__support/CPP/bitset.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_BITSET_H

#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include <stddef.h> // For size_t.

namespace LIBC_NAMESPACE::cpp {
namespace LIBC_NAMESPACE_DECL {
namespace cpp {

template <size_t NumberOfBits> struct bitset {
static_assert(NumberOfBits != 0,
Expand Down Expand Up @@ -86,6 +88,7 @@ template <size_t NumberOfBits> struct bitset {
size_t Data[NUMBER_OF_UNITS] = {0};
};

} // namespace LIBC_NAMESPACE::cpp
} // namespace cpp
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_CPP_BITSET_H
7 changes: 5 additions & 2 deletions libc/src/__support/CPP/cstddef.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_CSTDDEF_H

#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "type_traits.h" // For enable_if_t, is_integral_v.

namespace LIBC_NAMESPACE::cpp {
namespace LIBC_NAMESPACE_DECL {
namespace cpp {

enum class byte : unsigned char {};

Expand Down Expand Up @@ -66,6 +68,7 @@ to_integer(byte b) noexcept {
return static_cast<IntegerType>(b);
}

} // namespace LIBC_NAMESPACE::cpp
} // namespace cpp
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_CPP_CSTDDEF_H
7 changes: 5 additions & 2 deletions libc/src/__support/CPP/expected.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_EXPECTED_H

#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {
namespace LIBC_NAMESPACE_DECL {
namespace cpp {

// This is used to hold an unexpected value so that a different constructor is
// selected.
Expand Down Expand Up @@ -52,6 +54,7 @@ template <class T, class E> class expected {
LIBC_INLINE constexpr const T *operator->() const { return &exp; }
};

} // namespace LIBC_NAMESPACE::cpp
} // namespace cpp
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_CPP_EXPECTED_H
Loading