Merge llvm, clang, compiler-rt, libc++, lld, and lldb release_80 branch

r354130, resolve conflicts, and bump version numbers.
This commit is contained in:
Dimitry Andric 2019-02-15 21:44:42 +00:00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang800-import/; revision=344177
68 changed files with 814 additions and 509 deletions

View File

@ -25,7 +25,7 @@ struct ioctl_desc {
const char *name; const char *name;
}; };
const unsigned ioctl_table_max = 1202; const unsigned ioctl_table_max = 1200;
static ioctl_desc ioctl_table[ioctl_table_max]; static ioctl_desc ioctl_table[ioctl_table_max];
static unsigned ioctl_table_size = 0; static unsigned ioctl_table_size = 0;
@ -298,9 +298,6 @@ static void ioctl_table_fill() {
_(IRFRAMETTY_GET_DEVICE, WRITE, sizeof(unsigned int)); _(IRFRAMETTY_GET_DEVICE, WRITE, sizeof(unsigned int));
_(IRFRAMETTY_GET_DONGLE, WRITE, sizeof(unsigned int)); _(IRFRAMETTY_GET_DONGLE, WRITE, sizeof(unsigned int));
_(IRFRAMETTY_SET_DONGLE, READ, sizeof(unsigned int)); _(IRFRAMETTY_SET_DONGLE, READ, sizeof(unsigned int));
/* Entries from file: dev/isa/satlinkio.h */
_(SATIORESET, NONE, 0);
_(SATIOGID, WRITE, struct_satlink_id_sz);
/* Entries from file: dev/isa/isvio.h */ /* Entries from file: dev/isa/isvio.h */
_(ISV_CMD, READWRITE, struct_isv_cmd_sz); _(ISV_CMD, READWRITE, struct_isv_cmd_sz);
/* Entries from file: dev/isa/wtreg.h */ /* Entries from file: dev/isa/wtreg.h */
@ -649,8 +646,8 @@ static void ioctl_table_fill() {
_(SPKRTUNE, NONE, 0); _(SPKRTUNE, NONE, 0);
_(SPKRGETVOL, WRITE, sizeof(unsigned int)); _(SPKRGETVOL, WRITE, sizeof(unsigned int));
_(SPKRSETVOL, READ, sizeof(unsigned int)); _(SPKRSETVOL, READ, sizeof(unsigned int));
/* Entries from file: dev/nvmm/nvmm_ioctl.h */
#if 0 /* WIP */ #if 0 /* WIP */
/* Entries from file: dev/nvmm/nvmm_ioctl.h */
_(NVMM_IOC_CAPABILITY, WRITE, struct_nvmm_ioc_capability_sz); _(NVMM_IOC_CAPABILITY, WRITE, struct_nvmm_ioc_capability_sz);
_(NVMM_IOC_MACHINE_CREATE, READWRITE, struct_nvmm_ioc_machine_create_sz); _(NVMM_IOC_MACHINE_CREATE, READWRITE, struct_nvmm_ioc_machine_create_sz);
_(NVMM_IOC_MACHINE_DESTROY, READ, struct_nvmm_ioc_machine_destroy_sz); _(NVMM_IOC_MACHINE_DESTROY, READ, struct_nvmm_ioc_machine_destroy_sz);
@ -659,7 +656,7 @@ static void ioctl_table_fill() {
_(NVMM_IOC_VCPU_DESTROY, READ, struct_nvmm_ioc_vcpu_destroy_sz); _(NVMM_IOC_VCPU_DESTROY, READ, struct_nvmm_ioc_vcpu_destroy_sz);
_(NVMM_IOC_VCPU_SETSTATE, READ, struct_nvmm_ioc_vcpu_setstate_sz); _(NVMM_IOC_VCPU_SETSTATE, READ, struct_nvmm_ioc_vcpu_setstate_sz);
_(NVMM_IOC_VCPU_GETSTATE, READ, struct_nvmm_ioc_vcpu_getstate_sz); _(NVMM_IOC_VCPU_GETSTATE, READ, struct_nvmm_ioc_vcpu_getstate_sz);
_(NVMM_IOC_VCPU_INJECT, READWRITE, struct_nvmm_ioc_vcpu_inject_sz); _(NVMM_IOC_VCPU_INJECT, READ, struct_nvmm_ioc_vcpu_inject_sz);
_(NVMM_IOC_VCPU_RUN, READWRITE, struct_nvmm_ioc_vcpu_run_sz); _(NVMM_IOC_VCPU_RUN, READWRITE, struct_nvmm_ioc_vcpu_run_sz);
_(NVMM_IOC_GPA_MAP, READ, struct_nvmm_ioc_gpa_map_sz); _(NVMM_IOC_GPA_MAP, READ, struct_nvmm_ioc_gpa_map_sz);
_(NVMM_IOC_GPA_UNMAP, READ, struct_nvmm_ioc_gpa_unmap_sz); _(NVMM_IOC_GPA_UNMAP, READ, struct_nvmm_ioc_gpa_unmap_sz);

View File

@ -122,7 +122,6 @@
#include <dev/ic/nvmeio.h> #include <dev/ic/nvmeio.h>
#include <dev/ir/irdaio.h> #include <dev/ir/irdaio.h>
#include <dev/isa/isvio.h> #include <dev/isa/isvio.h>
#include <dev/isa/satlinkio.h>
#include <dev/isa/wtreg.h> #include <dev/isa/wtreg.h>
#include <dev/iscsi/iscsi_ioctl.h> #include <dev/iscsi/iscsi_ioctl.h>
#include <dev/nvmm/nvmm_ioctl.h> #include <dev/nvmm/nvmm_ioctl.h>
@ -639,7 +638,6 @@ unsigned struct_rf_recon_req_sz = sizeof(rf_recon_req);
unsigned struct_rio_conf_sz = sizeof(rio_conf); unsigned struct_rio_conf_sz = sizeof(rio_conf);
unsigned struct_rio_interface_sz = sizeof(rio_interface); unsigned struct_rio_interface_sz = sizeof(rio_interface);
unsigned struct_rio_stats_sz = sizeof(rio_stats); unsigned struct_rio_stats_sz = sizeof(rio_stats);
unsigned struct_satlink_id_sz = sizeof(satlink_id);
unsigned struct_scan_io_sz = sizeof(scan_io); unsigned struct_scan_io_sz = sizeof(scan_io);
unsigned struct_scbusaccel_args_sz = sizeof(scbusaccel_args); unsigned struct_scbusaccel_args_sz = sizeof(scbusaccel_args);
unsigned struct_scbusiodetach_args_sz = sizeof(scbusiodetach_args); unsigned struct_scbusiodetach_args_sz = sizeof(scbusiodetach_args);
@ -1105,9 +1103,6 @@ unsigned IOCTL_IRDA_GET_TURNAROUNDMASK = IRDA_GET_TURNAROUNDMASK;
unsigned IOCTL_IRFRAMETTY_GET_DEVICE = IRFRAMETTY_GET_DEVICE; unsigned IOCTL_IRFRAMETTY_GET_DEVICE = IRFRAMETTY_GET_DEVICE;
unsigned IOCTL_IRFRAMETTY_GET_DONGLE = IRFRAMETTY_GET_DONGLE; unsigned IOCTL_IRFRAMETTY_GET_DONGLE = IRFRAMETTY_GET_DONGLE;
unsigned IOCTL_IRFRAMETTY_SET_DONGLE = IRFRAMETTY_SET_DONGLE; unsigned IOCTL_IRFRAMETTY_SET_DONGLE = IRFRAMETTY_SET_DONGLE;
unsigned IOCTL_SATIORESET = SATIORESET;
unsigned IOCTL_SATIOGID = SATIOGID;
unsigned IOCTL_SATIOSBUFSIZE = SATIOSBUFSIZE;
unsigned IOCTL_ISV_CMD = ISV_CMD; unsigned IOCTL_ISV_CMD = ISV_CMD;
unsigned IOCTL_WTQICMD = WTQICMD; unsigned IOCTL_WTQICMD = WTQICMD;
unsigned IOCTL_ISCSI_GET_VERSION = ISCSI_GET_VERSION; unsigned IOCTL_ISCSI_GET_VERSION = ISCSI_GET_VERSION;

View File

@ -803,7 +803,6 @@ extern unsigned struct_rf_recon_req_sz;
extern unsigned struct_rio_conf_sz; extern unsigned struct_rio_conf_sz;
extern unsigned struct_rio_interface_sz; extern unsigned struct_rio_interface_sz;
extern unsigned struct_rio_stats_sz; extern unsigned struct_rio_stats_sz;
extern unsigned struct_satlink_id_sz;
extern unsigned struct_scan_io_sz; extern unsigned struct_scan_io_sz;
extern unsigned struct_scbusaccel_args_sz; extern unsigned struct_scbusaccel_args_sz;
extern unsigned struct_scbusiodetach_args_sz; extern unsigned struct_scbusiodetach_args_sz;
@ -1266,9 +1265,6 @@ extern unsigned IOCTL_IRDA_GET_TURNAROUNDMASK;
extern unsigned IOCTL_IRFRAMETTY_GET_DEVICE; extern unsigned IOCTL_IRFRAMETTY_GET_DEVICE;
extern unsigned IOCTL_IRFRAMETTY_GET_DONGLE; extern unsigned IOCTL_IRFRAMETTY_GET_DONGLE;
extern unsigned IOCTL_IRFRAMETTY_SET_DONGLE; extern unsigned IOCTL_IRFRAMETTY_SET_DONGLE;
extern unsigned IOCTL_SATIORESET;
extern unsigned IOCTL_SATIOGID;
extern unsigned IOCTL_SATIOSBUFSIZE;
extern unsigned IOCTL_ISV_CMD; extern unsigned IOCTL_ISV_CMD;
extern unsigned IOCTL_WTQICMD; extern unsigned IOCTL_WTQICMD;
extern unsigned IOCTL_ISCSI_GET_VERSION; extern unsigned IOCTL_ISCSI_GET_VERSION;

View File

@ -165,7 +165,8 @@ struct WasmSymbolInfo {
StringRef Name; StringRef Name;
uint8_t Kind; uint8_t Kind;
uint32_t Flags; uint32_t Flags;
StringRef Module; // For undefined symbols the module name of the import StringRef ImportModule; // For undefined symbols the module of the import
StringRef ImportName; // For undefined symbols the name of the import
union { union {
// For function or global symbols, the index in function or global index // For function or global symbols, the index in function or global index
// space. // space.
@ -284,6 +285,7 @@ const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
const unsigned WASM_SYMBOL_UNDEFINED = 0x10; const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40;
#define WASM_RELOC(name, value) name = value, #define WASM_RELOC(name, value) name = value,

View File

@ -19,7 +19,8 @@ class MCSymbolWasm : public MCSymbol {
bool IsWeak = false; bool IsWeak = false;
bool IsHidden = false; bool IsHidden = false;
bool IsComdat = false; bool IsComdat = false;
std::string ModuleName; Optional<std::string> ImportModule;
Optional<std::string> ImportName;
wasm::WasmSignature *Signature = nullptr; wasm::WasmSignature *Signature = nullptr;
Optional<wasm::WasmGlobalType> GlobalType; Optional<wasm::WasmGlobalType> GlobalType;
Optional<wasm::WasmEventType> EventType; Optional<wasm::WasmEventType> EventType;
@ -32,7 +33,7 @@ class MCSymbolWasm : public MCSymbol {
// Use a module name of "env" for now, for compatibility with existing tools. // Use a module name of "env" for now, for compatibility with existing tools.
// This is temporary, and may change, as the ABI is not yet stable. // This is temporary, and may change, as the ABI is not yet stable.
MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary) MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary)
: MCSymbol(SymbolKindWasm, Name, isTemporary), ModuleName("env") {} : MCSymbol(SymbolKindWasm, Name, isTemporary) {}
static bool classof(const MCSymbol *S) { return S->isWasm(); } static bool classof(const MCSymbol *S) { return S->isWasm(); }
const MCExpr *getSize() const { return SymbolSize; } const MCExpr *getSize() const { return SymbolSize; }
@ -55,8 +56,21 @@ class MCSymbolWasm : public MCSymbol {
bool isComdat() const { return IsComdat; } bool isComdat() const { return IsComdat; }
void setComdat(bool isComdat) { IsComdat = isComdat; } void setComdat(bool isComdat) { IsComdat = isComdat; }
const StringRef getModuleName() const { return ModuleName; } const StringRef getImportModule() const {
void setModuleName(StringRef Name) { ModuleName = Name; } if (ImportModule.hasValue()) {
return ImportModule.getValue();
}
return "env";
}
void setImportModule(StringRef Name) { ImportModule = Name; }
const StringRef getImportName() const {
if (ImportName.hasValue()) {
return ImportName.getValue();
}
return getName();
}
void setImportName(StringRef Name) { ImportName = Name; }
const wasm::WasmSignature *getSignature() const { return Signature; } const wasm::WasmSignature *getSignature() const { return Signature; }
void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; } void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; }

View File

@ -161,25 +161,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
} }
if (T.isOSWindows() && !T.isOSCygMing()) { if (T.isOSWindows() && !T.isOSCygMing()) {
// Win32 does not support long double // XXX: The earliest documentation available at the moment is for VS2015/VC19:
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support?view=vs-2015
// XXX: In order to use an MSVCRT older than VC19,
// the specific library version must be explicit in the target triple,
// e.g., x86_64-pc-windows-msvc18.
bool hasPartialC99 = true;
if (T.isKnownWindowsMSVCEnvironment()) {
unsigned Major, Minor, Micro;
T.getEnvironmentVersion(Major, Minor, Micro);
hasPartialC99 = (Major == 0 || Major >= 19);
}
// Latest targets support C89 math functions, in part.
bool isARM = (T.getArch() == Triple::aarch64 ||
T.getArch() == Triple::arm);
bool hasPartialFloat = (isARM ||
T.getArch() == Triple::x86_64);
// Win32 does not support float C89 math functions, in general.
if (!hasPartialFloat) {
TLI.setUnavailable(LibFunc_acosf);
TLI.setUnavailable(LibFunc_asinf);
TLI.setUnavailable(LibFunc_atan2f);
TLI.setUnavailable(LibFunc_atanf);
TLI.setUnavailable(LibFunc_ceilf);
TLI.setUnavailable(LibFunc_cosf);
TLI.setUnavailable(LibFunc_coshf);
TLI.setUnavailable(LibFunc_expf);
TLI.setUnavailable(LibFunc_floorf);
TLI.setUnavailable(LibFunc_fmodf);
TLI.setUnavailable(LibFunc_log10f);
TLI.setUnavailable(LibFunc_logf);
TLI.setUnavailable(LibFunc_modff);
TLI.setUnavailable(LibFunc_powf);
TLI.setUnavailable(LibFunc_sinf);
TLI.setUnavailable(LibFunc_sinhf);
TLI.setUnavailable(LibFunc_sqrtf);
TLI.setUnavailable(LibFunc_tanf);
TLI.setUnavailable(LibFunc_tanhf);
}
if (!isARM)
TLI.setUnavailable(LibFunc_fabsf);
TLI.setUnavailable(LibFunc_frexpf);
TLI.setUnavailable(LibFunc_ldexpf);
// Win32 does not support long double C89 math functions.
TLI.setUnavailable(LibFunc_acosl); TLI.setUnavailable(LibFunc_acosl);
TLI.setUnavailable(LibFunc_asinl); TLI.setUnavailable(LibFunc_asinl);
TLI.setUnavailable(LibFunc_atanl);
TLI.setUnavailable(LibFunc_atan2l); TLI.setUnavailable(LibFunc_atan2l);
TLI.setUnavailable(LibFunc_atanl);
TLI.setUnavailable(LibFunc_ceill); TLI.setUnavailable(LibFunc_ceill);
TLI.setUnavailable(LibFunc_copysignl);
TLI.setUnavailable(LibFunc_cosl); TLI.setUnavailable(LibFunc_cosl);
TLI.setUnavailable(LibFunc_coshl); TLI.setUnavailable(LibFunc_coshl);
TLI.setUnavailable(LibFunc_expl); TLI.setUnavailable(LibFunc_expl);
TLI.setUnavailable(LibFunc_fabsf); // Win32 and Win64 both lack fabsf
TLI.setUnavailable(LibFunc_fabsl); TLI.setUnavailable(LibFunc_fabsl);
TLI.setUnavailable(LibFunc_floorl); TLI.setUnavailable(LibFunc_floorl);
TLI.setUnavailable(LibFunc_fmaxl);
TLI.setUnavailable(LibFunc_fminl);
TLI.setUnavailable(LibFunc_fmodl); TLI.setUnavailable(LibFunc_fmodl);
TLI.setUnavailable(LibFunc_frexpl); TLI.setUnavailable(LibFunc_frexpl);
TLI.setUnavailable(LibFunc_ldexpf);
TLI.setUnavailable(LibFunc_ldexpl); TLI.setUnavailable(LibFunc_ldexpl);
TLI.setUnavailable(LibFunc_log10l);
TLI.setUnavailable(LibFunc_logl); TLI.setUnavailable(LibFunc_logl);
TLI.setUnavailable(LibFunc_modfl); TLI.setUnavailable(LibFunc_modfl);
TLI.setUnavailable(LibFunc_powl); TLI.setUnavailable(LibFunc_powl);
@ -189,81 +230,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_tanl); TLI.setUnavailable(LibFunc_tanl);
TLI.setUnavailable(LibFunc_tanhl); TLI.setUnavailable(LibFunc_tanhl);
// Win32 only has C89 math // Win32 does not fully support C99 math functions.
TLI.setUnavailable(LibFunc_acosh); if (!hasPartialC99) {
TLI.setUnavailable(LibFunc_acoshf); TLI.setUnavailable(LibFunc_acosh);
TLI.setUnavailable(LibFunc_acoshl); TLI.setUnavailable(LibFunc_acoshf);
TLI.setUnavailable(LibFunc_asinh); TLI.setUnavailable(LibFunc_asinh);
TLI.setUnavailable(LibFunc_asinhf); TLI.setUnavailable(LibFunc_asinhf);
TLI.setUnavailable(LibFunc_asinhl); TLI.setUnavailable(LibFunc_atanh);
TLI.setUnavailable(LibFunc_atanh); TLI.setUnavailable(LibFunc_atanhf);
TLI.setUnavailable(LibFunc_atanhf); TLI.setAvailableWithName(LibFunc_cabs, "_cabs");
TLI.setUnavailable(LibFunc_atanhl); TLI.setUnavailable(LibFunc_cabsf);
TLI.setUnavailable(LibFunc_cabs); TLI.setUnavailable(LibFunc_cbrt);
TLI.setUnavailable(LibFunc_cabsf); TLI.setUnavailable(LibFunc_cbrtf);
TLI.setUnavailable(LibFunc_cabsl); TLI.setAvailableWithName(LibFunc_copysign, "_copysign");
TLI.setUnavailable(LibFunc_cbrt); TLI.setAvailableWithName(LibFunc_copysignf, "_copysignf");
TLI.setUnavailable(LibFunc_cbrtf); TLI.setUnavailable(LibFunc_exp2);
TLI.setUnavailable(LibFunc_cbrtl); TLI.setUnavailable(LibFunc_exp2f);
TLI.setUnavailable(LibFunc_exp2); TLI.setUnavailable(LibFunc_expm1);
TLI.setUnavailable(LibFunc_exp2f); TLI.setUnavailable(LibFunc_expm1f);
TLI.setUnavailable(LibFunc_exp2l); TLI.setUnavailable(LibFunc_fmax);
TLI.setUnavailable(LibFunc_expm1);
TLI.setUnavailable(LibFunc_expm1f);
TLI.setUnavailable(LibFunc_expm1l);
TLI.setUnavailable(LibFunc_log2);
TLI.setUnavailable(LibFunc_log2f);
TLI.setUnavailable(LibFunc_log2l);
TLI.setUnavailable(LibFunc_log1p);
TLI.setUnavailable(LibFunc_log1pf);
TLI.setUnavailable(LibFunc_log1pl);
TLI.setUnavailable(LibFunc_logb);
TLI.setUnavailable(LibFunc_logbf);
TLI.setUnavailable(LibFunc_logbl);
TLI.setUnavailable(LibFunc_nearbyint);
TLI.setUnavailable(LibFunc_nearbyintf);
TLI.setUnavailable(LibFunc_nearbyintl);
TLI.setUnavailable(LibFunc_rint);
TLI.setUnavailable(LibFunc_rintf);
TLI.setUnavailable(LibFunc_rintl);
TLI.setUnavailable(LibFunc_round);
TLI.setUnavailable(LibFunc_roundf);
TLI.setUnavailable(LibFunc_roundl);
TLI.setUnavailable(LibFunc_trunc);
TLI.setUnavailable(LibFunc_truncf);
TLI.setUnavailable(LibFunc_truncl);
// Win32 provides some C99 math with mangled names
TLI.setAvailableWithName(LibFunc_copysign, "_copysign");
if (T.getArch() == Triple::x86) {
// Win32 on x86 implements single-precision math functions as macros
TLI.setUnavailable(LibFunc_acosf);
TLI.setUnavailable(LibFunc_asinf);
TLI.setUnavailable(LibFunc_atanf);
TLI.setUnavailable(LibFunc_atan2f);
TLI.setUnavailable(LibFunc_ceilf);
TLI.setUnavailable(LibFunc_copysignf);
TLI.setUnavailable(LibFunc_cosf);
TLI.setUnavailable(LibFunc_coshf);
TLI.setUnavailable(LibFunc_expf);
TLI.setUnavailable(LibFunc_floorf);
TLI.setUnavailable(LibFunc_fminf);
TLI.setUnavailable(LibFunc_fmaxf); TLI.setUnavailable(LibFunc_fmaxf);
TLI.setUnavailable(LibFunc_fmodf); TLI.setUnavailable(LibFunc_fmin);
TLI.setUnavailable(LibFunc_logf); TLI.setUnavailable(LibFunc_fminf);
TLI.setUnavailable(LibFunc_log10f); TLI.setUnavailable(LibFunc_log1p);
TLI.setUnavailable(LibFunc_modff); TLI.setUnavailable(LibFunc_log1pf);
TLI.setUnavailable(LibFunc_powf); TLI.setUnavailable(LibFunc_log2);
TLI.setUnavailable(LibFunc_sinf); TLI.setUnavailable(LibFunc_log2f);
TLI.setUnavailable(LibFunc_sinhf); TLI.setAvailableWithName(LibFunc_logb, "_logb");
TLI.setUnavailable(LibFunc_sqrtf); if (hasPartialFloat)
TLI.setUnavailable(LibFunc_tanf); TLI.setAvailableWithName(LibFunc_logbf, "_logbf");
TLI.setUnavailable(LibFunc_tanhf); else
TLI.setUnavailable(LibFunc_logbf);
TLI.setUnavailable(LibFunc_rint);
TLI.setUnavailable(LibFunc_rintf);
TLI.setUnavailable(LibFunc_round);
TLI.setUnavailable(LibFunc_roundf);
TLI.setUnavailable(LibFunc_trunc);
TLI.setUnavailable(LibFunc_truncf);
} }
// Win32 does *not* provide these functions, but they are // Win32 does not support long double C99 math functions.
// generally available on POSIX-compliant systems: TLI.setUnavailable(LibFunc_acoshl);
TLI.setUnavailable(LibFunc_asinhl);
TLI.setUnavailable(LibFunc_atanhl);
TLI.setUnavailable(LibFunc_cabsl);
TLI.setUnavailable(LibFunc_cbrtl);
TLI.setUnavailable(LibFunc_copysignl);
TLI.setUnavailable(LibFunc_exp2l);
TLI.setUnavailable(LibFunc_expm1l);
TLI.setUnavailable(LibFunc_fmaxl);
TLI.setUnavailable(LibFunc_fminl);
TLI.setUnavailable(LibFunc_log1pl);
TLI.setUnavailable(LibFunc_log2l);
TLI.setUnavailable(LibFunc_logbl);
TLI.setUnavailable(LibFunc_nearbyintl);
TLI.setUnavailable(LibFunc_rintl);
TLI.setUnavailable(LibFunc_roundl);
TLI.setUnavailable(LibFunc_truncl);
// Win32 does not support these functions, but
// they are generally available on POSIX-compliant systems.
TLI.setUnavailable(LibFunc_access); TLI.setUnavailable(LibFunc_access);
TLI.setUnavailable(LibFunc_bcmp); TLI.setUnavailable(LibFunc_bcmp);
TLI.setUnavailable(LibFunc_bcopy); TLI.setUnavailable(LibFunc_bcopy);
@ -318,12 +344,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_utime); TLI.setUnavailable(LibFunc_utime);
TLI.setUnavailable(LibFunc_utimes); TLI.setUnavailable(LibFunc_utimes);
TLI.setUnavailable(LibFunc_write); TLI.setUnavailable(LibFunc_write);
// Win32 does *not* provide provide these functions, but they are
// specified by C99:
TLI.setUnavailable(LibFunc_atoll);
TLI.setUnavailable(LibFunc_frexpf);
TLI.setUnavailable(LibFunc_llabs);
} }
switch (T.getOS()) { switch (T.getOS()) {

View File

@ -559,6 +559,11 @@ static void AttemptToFoldSymbolOffsetDifference(
if (Asm->isThumbFunc(&SA)) if (Asm->isThumbFunc(&SA))
Addend |= 1; Addend |= 1;
// If symbol is labeled as micromips, we set low-bit to ensure
// correct offset in .gcc_except_table
if (Asm->getBackend().isMicroMips(&SA))
Addend |= 1;
// Clear the symbol expr pointers to indicate we have folded these // Clear the symbol expr pointers to indicate we have folded these
// operands. // operands.
A = B = nullptr; A = B = nullptr;

View File

@ -3364,10 +3364,11 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
} }
if (FileNumber == -1) { if (FileNumber == -1) {
if (!getContext().getAsmInfo()->hasSingleParameterDotFile()) // Ignore the directive if there is no number and the target doesn't support
return Error(DirectiveLoc, // numberless .file directives. This allows some portability of assembler
"target does not support '.file' without a number"); // between different object file formats.
getStreamer().EmitFileDirective(Filename); if (getContext().getAsmInfo()->hasSingleParameterDotFile())
getStreamer().EmitFileDirective(Filename);
} else { } else {
// In case there is a -g option as well as debug info from directive .file, // In case there is a -g option as well as debug info from directive .file,
// we turn off the -g option, directly use the existing debug info instead. // we turn off the -g option, directly use the existing debug info instead.

View File

@ -982,7 +982,8 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_GLOBAL:
case wasm::WASM_SYMBOL_TYPE_EVENT: case wasm::WASM_SYMBOL_TYPE_EVENT:
encodeULEB128(Sym.ElementIndex, W.OS); encodeULEB128(Sym.ElementIndex, W.OS);
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
(Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
writeString(Sym.Name); writeString(Sym.Name);
break; break;
case wasm::WASM_SYMBOL_TYPE_DATA: case wasm::WASM_SYMBOL_TYPE_DATA:
@ -1162,8 +1163,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
MCSymbolWasm *MemorySym = MCSymbolWasm *MemorySym =
cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory")); cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory"));
wasm::WasmImport MemImport; wasm::WasmImport MemImport;
MemImport.Module = MemorySym->getModuleName(); MemImport.Module = MemorySym->getImportModule();
MemImport.Field = MemorySym->getName(); MemImport.Field = MemorySym->getImportName();
MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
Imports.push_back(MemImport); Imports.push_back(MemImport);
@ -1173,8 +1174,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
MCSymbolWasm *TableSym = MCSymbolWasm *TableSym =
cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table")); cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table"));
wasm::WasmImport TableImport; wasm::WasmImport TableImport;
TableImport.Module = TableSym->getModuleName(); TableImport.Module = TableSym->getImportModule();
TableImport.Field = TableSym->getName(); TableImport.Field = TableSym->getImportName();
TableImport.Kind = wasm::WASM_EXTERNAL_TABLE; TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF; TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF;
Imports.push_back(TableImport); Imports.push_back(TableImport);
@ -1200,8 +1201,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
if (!WS.isDefined() && !WS.isComdat()) { if (!WS.isDefined() && !WS.isComdat()) {
if (WS.isFunction()) { if (WS.isFunction()) {
wasm::WasmImport Import; wasm::WasmImport Import;
Import.Module = WS.getModuleName(); Import.Module = WS.getImportModule();
Import.Field = WS.getName(); Import.Field = WS.getImportName();
Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
Import.SigIndex = getFunctionType(WS); Import.SigIndex = getFunctionType(WS);
Imports.push_back(Import); Imports.push_back(Import);
@ -1211,8 +1212,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
report_fatal_error("undefined global symbol cannot be weak"); report_fatal_error("undefined global symbol cannot be weak");
wasm::WasmImport Import; wasm::WasmImport Import;
Import.Module = WS.getModuleName(); Import.Module = WS.getImportModule();
Import.Field = WS.getName(); Import.Field = WS.getImportName();
Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
Import.Global = WS.getGlobalType(); Import.Global = WS.getGlobalType();
Imports.push_back(Import); Imports.push_back(Import);
@ -1222,8 +1223,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
report_fatal_error("undefined event symbol cannot be weak"); report_fatal_error("undefined event symbol cannot be weak");
wasm::WasmImport Import; wasm::WasmImport Import;
Import.Module = WS.getModuleName(); Import.Module = WS.getImportModule();
Import.Field = WS.getName(); Import.Field = WS.getImportName();
Import.Kind = wasm::WASM_EXTERNAL_EVENT; Import.Kind = wasm::WASM_EXTERNAL_EVENT;
Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION; Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
Import.Event.SigIndex = getEventType(WS); Import.Event.SigIndex = getEventType(WS);
@ -1448,6 +1449,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
if (WS.isUndefined()) if (WS.isUndefined())
Flags |= wasm::WASM_SYMBOL_UNDEFINED; Flags |= wasm::WASM_SYMBOL_UNDEFINED;
if (WS.getName() != WS.getImportName())
Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
wasm::WasmSymbolInfo Info; wasm::WasmSymbolInfo Info;
Info.Name = WS.getName(); Info.Name = WS.getName();

View File

@ -505,9 +505,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Function.SymbolName = Info.Name; Function.SymbolName = Info.Name;
} else { } else {
wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Info.Name = readString(Ctx);
else
Info.Name = Import.Field;
Signature = &Signatures[Import.SigIndex]; Signature = &Signatures[Import.SigIndex];
Info.Name = Import.Field; Info.ImportName = Import.Field;
Info.Module = Import.Module; Info.ImportModule = Import.Module;
} }
break; break;
@ -530,8 +534,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Global.SymbolName = Info.Name; Global.SymbolName = Info.Name;
} else { } else {
wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
Info.Name = Import.Field; if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Info.Name = readString(Ctx);
else
Info.Name = Import.Field;
GlobalType = &Import.Global; GlobalType = &Import.Global;
Info.ImportName = Import.Field;
Info.ImportModule = Import.Module;
} }
break; break;
@ -585,9 +594,14 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
} else { } else {
wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex]; wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Info.Name = readString(Ctx);
else
Info.Name = Import.Field;
EventType = &Import.Event; EventType = &Import.Event;
Signature = &Signatures[EventType->SigIndex]; Signature = &Signatures[EventType->SigIndex];
Info.Name = Import.Field; Info.ImportName = Import.Field;
Info.ImportModule = Import.Module;
} }
break; break;
} }

View File

@ -202,6 +202,12 @@ void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
char buf[len]; char buf[len];
::pthread_getname_np(::pthread_self(), buf, len); ::pthread_getname_np(::pthread_self(), buf, len);
Name.append(buf, buf + strlen(buf));
#elif defined(__OpenBSD__)
constexpr uint32_t len = get_max_thread_name_length_impl();
char buf[len];
::pthread_get_name_np(::pthread_self(), buf, len);
Name.append(buf, buf + strlen(buf)); Name.append(buf, buf + strlen(buf));
#elif defined(__linux__) #elif defined(__linux__)
#if HAVE_PTHREAD_GETNAME_NP #if HAVE_PTHREAD_GETNAME_NP

View File

@ -2292,6 +2292,31 @@ void AArch64InstrInfo::copyPhysRegTuple(MachineBasicBlock &MBB,
} }
} }
void AArch64InstrInfo::copyGPRRegTuple(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
DebugLoc DL, unsigned DestReg,
unsigned SrcReg, bool KillSrc,
unsigned Opcode, unsigned ZeroReg,
llvm::ArrayRef<unsigned> Indices) const {
const TargetRegisterInfo *TRI = &getRegisterInfo();
unsigned NumRegs = Indices.size();
#ifndef NDEBUG
uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
"GPR reg sequences should not be able to overlap");
#endif
for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
MIB.addReg(ZeroReg);
AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
MIB.addImm(0);
}
}
void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I, MachineBasicBlock::iterator I,
const DebugLoc &DL, unsigned DestReg, const DebugLoc &DL, unsigned DestReg,
@ -2431,6 +2456,22 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
return; return;
} }
if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
AArch64::XZR, Indices);
return;
}
if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
AArch64::WZR, Indices);
return;
}
if (AArch64::FPR128RegClass.contains(DestReg) && if (AArch64::FPR128RegClass.contains(DestReg) &&
AArch64::FPR128RegClass.contains(SrcReg)) { AArch64::FPR128RegClass.contains(SrcReg)) {
if (Subtarget.hasNEON()) { if (Subtarget.hasNEON()) {

View File

@ -122,6 +122,10 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
bool KillSrc, unsigned Opcode, bool KillSrc, unsigned Opcode,
llvm::ArrayRef<unsigned> Indices) const; llvm::ArrayRef<unsigned> Indices) const;
void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
DebugLoc DL, unsigned DestReg, unsigned SrcReg,
bool KillSrc, unsigned Opcode, unsigned ZeroReg,
llvm::ArrayRef<unsigned> Indices) const;
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
bool KillSrc) const override; bool KillSrc) const override;

View File

@ -649,10 +649,12 @@ def FPR128Op : RegisterOperand<FPR128, "printOperand"> {
// ARMv8.1a atomic CASP register operands // ARMv8.1a atomic CASP register operands
def WSeqPairs : RegisterTuples<[sube32, subo32], def WSeqPairs : RegisterTuples<[sube32, subo32],
[(rotl GPR32, 0), (rotl GPR32, 1)]>; [(decimate (rotl GPR32, 0), 2),
def XSeqPairs : RegisterTuples<[sube64, subo64], (decimate (rotl GPR32, 1), 2)]>;
[(rotl GPR64, 0), (rotl GPR64, 1)]>; def XSeqPairs : RegisterTuples<[sube64, subo64],
[(decimate (rotl GPR64, 0), 2),
(decimate (rotl GPR64, 1), 2)]>;
def WSeqPairsClass : RegisterClass<"AArch64", [untyped], 32, def WSeqPairsClass : RegisterClass<"AArch64", [untyped], 32,
(add WSeqPairs)>{ (add WSeqPairs)>{

View File

@ -1779,8 +1779,8 @@ static DecodeStatus DecodeGPRSeqPairsClassRegisterClass(MCInst &Inst,
if (RegNo & 0x1) if (RegNo & 0x1)
return Fail; return Fail;
unsigned Register = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo); unsigned Reg = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo / 2);
Inst.addOperand(MCOperand::createReg(Register)); Inst.addOperand(MCOperand::createReg(Reg));
return Success; return Success;
} }

View File

@ -5618,55 +5618,96 @@ SDValue SystemZTargetLowering::combineBSWAP(
static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) { static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
// We have a SELECT_CCMASK or BR_CCMASK comparing the condition code // We have a SELECT_CCMASK or BR_CCMASK comparing the condition code
// set by the CCReg instruction using the CCValid / CCMask masks, // set by the CCReg instruction using the CCValid / CCMask masks,
// If the CCReg instruction is itself a (ICMP (SELECT_CCMASK)) testing // If the CCReg instruction is itself a ICMP testing the condition
// the condition code set by some other instruction, see whether we // code set by some other instruction, see whether we can directly
// can directly use that condition code. // use that condition code.
bool Invert = false;
// Verify that we have an appropriate mask for a EQ or NE comparison. // Verify that we have an ICMP against some constant.
if (CCValid != SystemZ::CCMASK_ICMP) if (CCValid != SystemZ::CCMASK_ICMP)
return false; return false;
if (CCMask == SystemZ::CCMASK_CMP_NE) auto *ICmp = CCReg.getNode();
Invert = !Invert;
else if (CCMask != SystemZ::CCMASK_CMP_EQ)
return false;
// Verify that we have an ICMP that is the user of a SELECT_CCMASK.
SDNode *ICmp = CCReg.getNode();
if (ICmp->getOpcode() != SystemZISD::ICMP) if (ICmp->getOpcode() != SystemZISD::ICMP)
return false; return false;
SDNode *Select = ICmp->getOperand(0).getNode(); auto *CompareLHS = ICmp->getOperand(0).getNode();
if (Select->getOpcode() != SystemZISD::SELECT_CCMASK) auto *CompareRHS = dyn_cast<ConstantSDNode>(ICmp->getOperand(1));
if (!CompareRHS)
return false; return false;
// Verify that the ICMP compares against one of select values. // Optimize the case where CompareLHS is a SELECT_CCMASK.
auto *CompareVal = dyn_cast<ConstantSDNode>(ICmp->getOperand(1)); if (CompareLHS->getOpcode() == SystemZISD::SELECT_CCMASK) {
if (!CompareVal) // Verify that we have an appropriate mask for a EQ or NE comparison.
return false; bool Invert = false;
auto *TrueVal = dyn_cast<ConstantSDNode>(Select->getOperand(0)); if (CCMask == SystemZ::CCMASK_CMP_NE)
if (!TrueVal) Invert = !Invert;
return false; else if (CCMask != SystemZ::CCMASK_CMP_EQ)
auto *FalseVal = dyn_cast<ConstantSDNode>(Select->getOperand(1)); return false;
if (!FalseVal)
return false;
if (CompareVal->getZExtValue() == FalseVal->getZExtValue())
Invert = !Invert;
else if (CompareVal->getZExtValue() != TrueVal->getZExtValue())
return false;
// Compute the effective CC mask for the new branch or select. // Verify that the ICMP compares against one of select values.
auto *NewCCValid = dyn_cast<ConstantSDNode>(Select->getOperand(2)); auto *TrueVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(0));
auto *NewCCMask = dyn_cast<ConstantSDNode>(Select->getOperand(3)); if (!TrueVal)
if (!NewCCValid || !NewCCMask) return false;
return false; auto *FalseVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1));
CCValid = NewCCValid->getZExtValue(); if (!FalseVal)
CCMask = NewCCMask->getZExtValue(); return false;
if (Invert) if (CompareRHS->getZExtValue() == FalseVal->getZExtValue())
CCMask ^= CCValid; Invert = !Invert;
else if (CompareRHS->getZExtValue() != TrueVal->getZExtValue())
return false;
// Return the updated CCReg link. // Compute the effective CC mask for the new branch or select.
CCReg = Select->getOperand(4); auto *NewCCValid = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(2));
return true; auto *NewCCMask = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(3));
if (!NewCCValid || !NewCCMask)
return false;
CCValid = NewCCValid->getZExtValue();
CCMask = NewCCMask->getZExtValue();
if (Invert)
CCMask ^= CCValid;
// Return the updated CCReg link.
CCReg = CompareLHS->getOperand(4);
return true;
}
// Optimize the case where CompareRHS is (SRA (SHL (IPM))).
if (CompareLHS->getOpcode() == ISD::SRA) {
auto *SRACount = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1));
if (!SRACount || SRACount->getZExtValue() != 30)
return false;
auto *SHL = CompareLHS->getOperand(0).getNode();
if (SHL->getOpcode() != ISD::SHL)
return false;
auto *SHLCount = dyn_cast<ConstantSDNode>(SHL->getOperand(1));
if (!SHLCount || SHLCount->getZExtValue() != 30 - SystemZ::IPM_CC)
return false;
auto *IPM = SHL->getOperand(0).getNode();
if (IPM->getOpcode() != SystemZISD::IPM)
return false;
// Avoid introducing CC spills (because SRA would clobber CC).
if (!CompareLHS->hasOneUse())
return false;
// Verify that the ICMP compares against zero.
if (CompareRHS->getZExtValue() != 0)
return false;
// Compute the effective CC mask for the new branch or select.
switch (CCMask) {
case SystemZ::CCMASK_CMP_EQ: break;
case SystemZ::CCMASK_CMP_NE: break;
case SystemZ::CCMASK_CMP_LT: CCMask = SystemZ::CCMASK_CMP_GT; break;
case SystemZ::CCMASK_CMP_GT: CCMask = SystemZ::CCMASK_CMP_LT; break;
case SystemZ::CCMASK_CMP_LE: CCMask = SystemZ::CCMASK_CMP_GE; break;
case SystemZ::CCMASK_CMP_GE: CCMask = SystemZ::CCMASK_CMP_LE; break;
default: return false;
}
// Return the updated CCReg link.
CCReg = IPM->getOperand(0);
return true;
}
return false;
} }
SDValue SystemZTargetLowering::combineBR_CCMASK( SDValue SystemZTargetLowering::combineBR_CCMASK(

View File

@ -557,80 +557,6 @@ bool SystemZInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
return false; return false;
} }
// If Reg is a virtual register, return its definition, otherwise return null.
static MachineInstr *getDef(unsigned Reg,
const MachineRegisterInfo *MRI) {
if (TargetRegisterInfo::isPhysicalRegister(Reg))
return nullptr;
return MRI->getUniqueVRegDef(Reg);
}
// Return true if MI is a shift of type Opcode by Imm bits.
static bool isShift(MachineInstr *MI, unsigned Opcode, int64_t Imm) {
return (MI->getOpcode() == Opcode &&
!MI->getOperand(2).getReg() &&
MI->getOperand(3).getImm() == Imm);
}
// If the destination of MI has no uses, delete it as dead.
static void eraseIfDead(MachineInstr *MI, const MachineRegisterInfo *MRI) {
if (MRI->use_nodbg_empty(MI->getOperand(0).getReg()))
MI->eraseFromParent();
}
// Compare compares SrcReg against zero. Check whether SrcReg contains
// the result of an IPM sequence whose input CC survives until Compare,
// and whether Compare is therefore redundant. Delete it and return
// true if so.
static bool removeIPMBasedCompare(MachineInstr &Compare, unsigned SrcReg,
const MachineRegisterInfo *MRI,
const TargetRegisterInfo *TRI) {
MachineInstr *LGFR = nullptr;
MachineInstr *RLL = getDef(SrcReg, MRI);
if (RLL && RLL->getOpcode() == SystemZ::LGFR) {
LGFR = RLL;
RLL = getDef(LGFR->getOperand(1).getReg(), MRI);
}
if (!RLL || !isShift(RLL, SystemZ::RLL, 31))
return false;
MachineInstr *SRL = getDef(RLL->getOperand(1).getReg(), MRI);
if (!SRL || !isShift(SRL, SystemZ::SRL, SystemZ::IPM_CC))
return false;
MachineInstr *IPM = getDef(SRL->getOperand(1).getReg(), MRI);
if (!IPM || IPM->getOpcode() != SystemZ::IPM)
return false;
// Check that there are no assignments to CC between the IPM and Compare,
if (IPM->getParent() != Compare.getParent())
return false;
MachineBasicBlock::iterator MBBI = IPM, MBBE = Compare.getIterator();
for (++MBBI; MBBI != MBBE; ++MBBI) {
MachineInstr &MI = *MBBI;
if (MI.modifiesRegister(SystemZ::CC, TRI))
return false;
}
Compare.eraseFromParent();
if (LGFR)
eraseIfDead(LGFR, MRI);
eraseIfDead(RLL, MRI);
eraseIfDead(SRL, MRI);
eraseIfDead(IPM, MRI);
return true;
}
bool SystemZInstrInfo::optimizeCompareInstr(
MachineInstr &Compare, unsigned SrcReg, unsigned SrcReg2, int Mask,
int Value, const MachineRegisterInfo *MRI) const {
assert(!SrcReg2 && "Only optimizing constant comparisons so far");
bool IsLogical = (Compare.getDesc().TSFlags & SystemZII::IsLogical) != 0;
return Value == 0 && !IsLogical &&
removeIPMBasedCompare(Compare, SrcReg, MRI, &RI);
}
bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB, bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
ArrayRef<MachineOperand> Pred, ArrayRef<MachineOperand> Pred,
unsigned TrueReg, unsigned FalseReg, unsigned TrueReg, unsigned FalseReg,

View File

@ -208,9 +208,6 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
int *BytesAdded = nullptr) const override; int *BytesAdded = nullptr) const override;
bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
unsigned &SrcReg2, int &Mask, int &Value) const override; unsigned &SrcReg2, int &Mask, int &Value) const override;
bool optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
unsigned SrcReg2, int Mask, int Value,
const MachineRegisterInfo *MRI) const override;
bool canInsertSelect(const MachineBasicBlock&, ArrayRef<MachineOperand> Cond, bool canInsertSelect(const MachineBasicBlock&, ArrayRef<MachineOperand> Cond,
unsigned, unsigned, int&, int&, int&) const override; unsigned, unsigned, int&, int&, int&) const override;
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,

View File

@ -164,17 +164,17 @@ static SDValue emitCLC(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
} }
// Convert the current CC value into an integer that is 0 if CC == 0, // Convert the current CC value into an integer that is 0 if CC == 0,
// less than zero if CC == 1 and greater than zero if CC >= 2. // greater than zero if CC == 1 and less than zero if CC >= 2.
// The sequence starts with IPM, which puts CC into bits 29 and 28 // The sequence starts with IPM, which puts CC into bits 29 and 28
// of an integer and clears bits 30 and 31. // of an integer and clears bits 30 and 31.
static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg, static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg,
SelectionDAG &DAG) { SelectionDAG &DAG) {
SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg); SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg);
SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM, SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM,
DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32)); DAG.getConstant(30 - SystemZ::IPM_CC, DL, MVT::i32));
SDValue ROTL = DAG.getNode(ISD::ROTL, DL, MVT::i32, SRL, SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL,
DAG.getConstant(31, DL, MVT::i32)); DAG.getConstant(30, DL, MVT::i32));
return ROTL; return SRA;
} }
std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp( std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp(
@ -184,7 +184,8 @@ std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp(
if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) { if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
uint64_t Bytes = CSize->getZExtValue(); uint64_t Bytes = CSize->getZExtValue();
assert(Bytes > 0 && "Caller should have handled 0-size case"); assert(Bytes > 0 && "Caller should have handled 0-size case");
SDValue CCReg = emitCLC(DAG, DL, Chain, Src1, Src2, Bytes); // Swap operands to invert CC == 1 vs. CC == 2 cases.
SDValue CCReg = emitCLC(DAG, DL, Chain, Src2, Src1, Bytes);
Chain = CCReg.getValue(1); Chain = CCReg.getValue(1);
return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain); return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain);
} }
@ -232,7 +233,8 @@ std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrcmp(
SDValue Src2, MachinePointerInfo Op1PtrInfo, SDValue Src2, MachinePointerInfo Op1PtrInfo,
MachinePointerInfo Op2PtrInfo) const { MachinePointerInfo Op2PtrInfo) const {
SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other); SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other);
SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src1, Src2, // Swap operands to invert CC == 1 vs. CC == 2 cases.
SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src2, Src1,
DAG.getConstant(0, DL, MVT::i32)); DAG.getConstant(0, DL, MVT::i32));
SDValue CCReg = Unused.getValue(1); SDValue CCReg = Unused.getValue(1);
Chain = Unused.getValue(2); Chain = Unused.getValue(2);

View File

@ -113,8 +113,15 @@ void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) {
} }
void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym, void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym,
StringRef ModuleName) { StringRef ImportModule) {
OS << "\t.import_module\t" << Sym->getName() << ", " << ModuleName << '\n'; OS << "\t.import_module\t" << Sym->getName() << ", "
<< ImportModule << '\n';
}
void WebAssemblyTargetAsmStreamer::emitImportName(const MCSymbolWasm *Sym,
StringRef ImportName) {
OS << "\t.import_name\t" << Sym->getName() << ", "
<< ImportName << '\n';
} }
void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {

View File

@ -45,7 +45,10 @@ class WebAssemblyTargetStreamer : public MCTargetStreamer {
virtual void emitEventType(const MCSymbolWasm *Sym) = 0; virtual void emitEventType(const MCSymbolWasm *Sym) = 0;
/// .import_module /// .import_module
virtual void emitImportModule(const MCSymbolWasm *Sym, virtual void emitImportModule(const MCSymbolWasm *Sym,
StringRef ModuleName) = 0; StringRef ImportModule) = 0;
/// .import_name
virtual void emitImportName(const MCSymbolWasm *Sym,
StringRef ImportName) = 0;
protected: protected:
void emitValueType(wasm::ValType Type); void emitValueType(wasm::ValType Type);
@ -67,7 +70,8 @@ class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer {
void emitIndIdx(const MCExpr *Value) override; void emitIndIdx(const MCExpr *Value) override;
void emitGlobalType(const MCSymbolWasm *Sym) override; void emitGlobalType(const MCSymbolWasm *Sym) override;
void emitEventType(const MCSymbolWasm *Sym) override; void emitEventType(const MCSymbolWasm *Sym) override;
void emitImportModule(const MCSymbolWasm *Sym, StringRef ModuleName) override; void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override;
void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override;
}; };
/// This part is for Wasm object output /// This part is for Wasm object output
@ -82,7 +86,9 @@ class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer {
void emitGlobalType(const MCSymbolWasm *Sym) override {} void emitGlobalType(const MCSymbolWasm *Sym) override {}
void emitEventType(const MCSymbolWasm *Sym) override {} void emitEventType(const MCSymbolWasm *Sym) override {}
void emitImportModule(const MCSymbolWasm *Sym, void emitImportModule(const MCSymbolWasm *Sym,
StringRef ModuleName) override {} StringRef ImportModule) override {}
void emitImportName(const MCSymbolWasm *Sym,
StringRef ImportName) override {}
}; };
/// This part is for null output /// This part is for null output
@ -98,6 +104,7 @@ class WebAssemblyTargetNullStreamer final : public WebAssemblyTargetStreamer {
void emitGlobalType(const MCSymbolWasm *) override {} void emitGlobalType(const MCSymbolWasm *) override {}
void emitEventType(const MCSymbolWasm *) override {} void emitEventType(const MCSymbolWasm *) override {}
void emitImportModule(const MCSymbolWasm *, StringRef) override {} void emitImportModule(const MCSymbolWasm *, StringRef) override {}
void emitImportName(const MCSymbolWasm *, StringRef) override {}
}; };
} // end namespace llvm } // end namespace llvm

View File

@ -111,9 +111,16 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
F.hasFnAttribute("wasm-import-module")) { F.hasFnAttribute("wasm-import-module")) {
StringRef Name = StringRef Name =
F.getFnAttribute("wasm-import-module").getValueAsString(); F.getFnAttribute("wasm-import-module").getValueAsString();
Sym->setModuleName(Name); Sym->setImportModule(Name);
getTargetStreamer()->emitImportModule(Sym, Name); getTargetStreamer()->emitImportModule(Sym, Name);
} }
if (TM.getTargetTriple().isOSBinFormatWasm() &&
F.hasFnAttribute("wasm-import-name")) {
StringRef Name =
F.getFnAttribute("wasm-import-name").getValueAsString();
Sym->setImportName(Name);
getTargetStreamer()->emitImportName(Sym, Name);
}
} }
} }

View File

@ -36,11 +36,6 @@ using namespace llvm;
#define DEBUG_TYPE "wasm-fix-function-bitcasts" #define DEBUG_TYPE "wasm-fix-function-bitcasts"
static cl::opt<bool>
TemporaryWorkarounds("wasm-temporary-workarounds",
cl::desc("Apply certain temporary workarounds"),
cl::init(true), cl::Hidden);
namespace { namespace {
class FixFunctionBitcasts final : public ModulePass { class FixFunctionBitcasts final : public ModulePass {
StringRef getPassName() const override { StringRef getPassName() const override {
@ -227,6 +222,17 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
return Wrapper; return Wrapper;
} }
// Test whether a main function with type FuncTy should be rewritten to have
// type MainTy.
bool shouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy) {
// Only fix the main function if it's the standard zero-arg form. That way,
// the standard cases will work as expected, and users will see signature
// mismatches from the linker for non-standard cases.
return FuncTy->getReturnType() == MainTy->getReturnType() &&
FuncTy->getNumParams() == 0 &&
!FuncTy->isVarArg();
}
bool FixFunctionBitcasts::runOnModule(Module &M) { bool FixFunctionBitcasts::runOnModule(Module &M) {
LLVM_DEBUG(dbgs() << "********** Fix Function Bitcasts **********\n"); LLVM_DEBUG(dbgs() << "********** Fix Function Bitcasts **********\n");
@ -243,14 +249,14 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
// "int main(int argc, char *argv[])", create an artificial call with it // "int main(int argc, char *argv[])", create an artificial call with it
// bitcasted to that type so that we generate a wrapper for it, so that // bitcasted to that type so that we generate a wrapper for it, so that
// the C runtime can call it. // the C runtime can call it.
if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") { if (F.getName() == "main") {
Main = &F; Main = &F;
LLVMContext &C = M.getContext(); LLVMContext &C = M.getContext();
Type *MainArgTys[] = {Type::getInt32Ty(C), Type *MainArgTys[] = {Type::getInt32Ty(C),
PointerType::get(Type::getInt8PtrTy(C), 0)}; PointerType::get(Type::getInt8PtrTy(C), 0)};
FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys, FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys,
/*isVarArg=*/false); /*isVarArg=*/false);
if (F.getFunctionType() != MainTy) { if (shouldFixMainFunction(F.getFunctionType(), MainTy)) {
LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: " LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: "
<< *F.getFunctionType() << "\n"); << *F.getFunctionType() << "\n");
Value *Args[] = {UndefValue::get(MainArgTys[0]), Value *Args[] = {UndefValue::get(MainArgTys[0]),
@ -298,12 +304,18 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
Main->setName("__original_main"); Main->setName("__original_main");
Function *MainWrapper = Function *MainWrapper =
cast<Function>(CallMain->getCalledValue()->stripPointerCasts()); cast<Function>(CallMain->getCalledValue()->stripPointerCasts());
MainWrapper->setName("main");
MainWrapper->setLinkage(Main->getLinkage());
MainWrapper->setVisibility(Main->getVisibility());
Main->setLinkage(Function::PrivateLinkage);
Main->setVisibility(Function::DefaultVisibility);
delete CallMain; delete CallMain;
if (Main->isDeclaration()) {
// The wrapper is not needed in this case as we don't need to export
// it to anyone else.
MainWrapper->eraseFromParent();
} else {
// Otherwise give the wrapper the same linkage as the original main
// function, so that it can be called from the same places.
MainWrapper->setName("main");
MainWrapper->setLinkage(Main->getLinkage());
MainWrapper->setVisibility(Main->getVisibility());
}
} }
return true; return true;

View File

@ -321,6 +321,7 @@ static cl::opt<unsigned long long> ClOriginBase("msan-origin-base",
cl::desc("Define custom MSan OriginBase"), cl::desc("Define custom MSan OriginBase"),
cl::Hidden, cl::init(0)); cl::Hidden, cl::init(0));
static const char *const kMsanModuleCtorName = "msan.module_ctor";
static const char *const kMsanInitName = "__msan_init"; static const char *const kMsanInitName = "__msan_init";
namespace { namespace {
@ -586,6 +587,8 @@ class MemorySanitizer {
/// An empty volatile inline asm that prevents callback merge. /// An empty volatile inline asm that prevents callback merge.
InlineAsm *EmptyAsm; InlineAsm *EmptyAsm;
Function *MsanCtorFunction;
}; };
/// A legacy function pass for msan instrumentation. /// A legacy function pass for msan instrumentation.
@ -839,6 +842,8 @@ Value *MemorySanitizer::getKmsanShadowOriginAccessFn(bool isStore, int size) {
} }
/// Module-level initialization. /// Module-level initialization.
///
/// inserts a call to __msan_init to the module's constructor list.
void MemorySanitizer::initializeModule(Module &M) { void MemorySanitizer::initializeModule(Module &M) {
auto &DL = M.getDataLayout(); auto &DL = M.getDataLayout();
@ -913,7 +918,22 @@ void MemorySanitizer::initializeModule(Module &M) {
OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000); OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000);
if (!CompileKernel) { if (!CompileKernel) {
getOrCreateInitFunction(M, kMsanInitName); std::tie(MsanCtorFunction, std::ignore) =
getOrCreateSanitizerCtorAndInitFunctions(
M, kMsanModuleCtorName, kMsanInitName,
/*InitArgTypes=*/{},
/*InitArgs=*/{},
// This callback is invoked when the functions are created the first
// time. Hook them into the global ctors list in that case:
[&](Function *Ctor, Function *) {
if (!ClWithComdat) {
appendToGlobalCtors(M, Ctor, 0);
return;
}
Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName);
Ctor->setComdat(MsanCtorComdat);
appendToGlobalCtors(M, Ctor, 0, Ctor);
});
if (TrackOrigins) if (TrackOrigins)
M.getOrInsertGlobal("__msan_track_origins", IRB.getInt32Ty(), [&] { M.getOrInsertGlobal("__msan_track_origins", IRB.getInt32Ty(), [&] {
@ -4458,6 +4478,8 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
} }
bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) { bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) {
if (!CompileKernel && (&F == MsanCtorFunction))
return false;
MemorySanitizerVisitor Visitor(F, *this, TLI); MemorySanitizerVisitor Visitor(F, *this, TLI);
// Clear out readonly/readnone attributes. // Clear out readonly/readnone attributes.

View File

@ -103,13 +103,6 @@ def ObjCInstanceMethod : SubsetSubject<ObjCMethod,
[{S->isInstanceMethod()}], [{S->isInstanceMethod()}],
"Objective-C instance methods">; "Objective-C instance methods">;
def ObjCInterfaceDeclInitMethod : SubsetSubject<ObjCMethod,
[{S->getMethodFamily() == OMF_init &&
(isa<ObjCInterfaceDecl>(S->getDeclContext()) ||
(isa<ObjCCategoryDecl>(S->getDeclContext()) &&
cast<ObjCCategoryDecl>(S->getDeclContext())->IsClassExtension()))}],
"init methods of interface or class extension declarations">;
def Struct : SubsetSubject<Record, def Struct : SubsetSubject<Record,
[{!S->isUnion()}], "structs">; [{!S->isUnion()}], "structs">;
@ -329,6 +322,7 @@ def TargetMSP430 : TargetArch<["msp430"]>;
def TargetRISCV : TargetArch<["riscv32", "riscv64"]>; def TargetRISCV : TargetArch<["riscv32", "riscv64"]>;
def TargetX86 : TargetArch<["x86"]>; def TargetX86 : TargetArch<["x86"]>;
def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>;
def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> { def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> {
let OSes = ["Win32"]; let OSes = ["Win32"];
} }
@ -1500,6 +1494,22 @@ def AMDGPUNumVGPR : InheritableAttr {
let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
} }
def WebAssemblyImportModule : InheritableAttr,
TargetSpecificAttr<TargetWebAssembly> {
let Spellings = [Clang<"import_module">];
let Args = [StringArgument<"ImportModule">];
let Documentation = [WebAssemblyImportModuleDocs];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
def WebAssemblyImportName : InheritableAttr,
TargetSpecificAttr<TargetWebAssembly> {
let Spellings = [Clang<"import_name">];
let Args = [StringArgument<"ImportName">];
let Documentation = [WebAssemblyImportNameDocs];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
def NoSplitStack : InheritableAttr { def NoSplitStack : InheritableAttr {
let Spellings = [GCC<"no_split_stack">]; let Spellings = [GCC<"no_split_stack">];
let Subjects = SubjectList<[Function], ErrorDiag>; let Subjects = SubjectList<[Function], ErrorDiag>;
@ -1745,7 +1755,7 @@ def ObjCExplicitProtocolImpl : InheritableAttr {
def ObjCDesignatedInitializer : Attr { def ObjCDesignatedInitializer : Attr {
let Spellings = [Clang<"objc_designated_initializer">]; let Spellings = [Clang<"objc_designated_initializer">];
let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag>; let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
let Documentation = [Undocumented]; let Documentation = [Undocumented];
} }

View File

@ -3652,7 +3652,40 @@ definition (
For more information see For more information see
`gcc documentation <https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Microsoft-Windows-Variable-Attributes.html>`_ `gcc documentation <https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Microsoft-Windows-Variable-Attributes.html>`_
or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_. or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_.
}]; }]; }
def WebAssemblyImportModuleDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Clang supports the ``__attribute__((import_module(<module_name>)))``
attribute for the WebAssembly target. This attribute may be attached to a
function declaration, where it modifies how the symbol is to be imported
within the WebAssembly linking environment.
WebAssembly imports use a two-level namespace scheme, consisting of a module
name, which typically identifies a module from which to import, and a field
name, which typically identifies a field from that module to import. By
default, module names for C/C++ symbols are assigned automatically by the
linker. This attribute can be used to override the default behavior, and
reuqest a specific module name be used instead.
}];
}
def WebAssemblyImportNameDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Clang supports the ``__attribute__((import_name(<name>)))``
attribute for the WebAssembly target. This attribute may be attached to a
function declaration, where it modifies how the symbol is to be imported
within the WebAssembly linking environment.
WebAssembly imports use a two-level namespace scheme, consisting of a module
name, which typically identifies a module from which to import, and a field
name, which typically identifies a field from that module to import. By
default, field names for C/C++ symbols are the same as their C/C++ symbol
names. This attribute can be used to override the default behavior, and
reuqest a specific field name be used instead.
}];
} }
def ArtificialDocs : Documentation { def ArtificialDocs : Documentation {

View File

@ -204,8 +204,8 @@ TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h",
TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_ReadStatusReg, "ii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_ReadStatusReg, "LLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_WriteStatusReg, "vii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
#undef BUILTIN #undef BUILTIN

View File

@ -3460,6 +3460,9 @@ def warn_objc_secondary_init_missing_init_call : Warning<
def warn_objc_implementation_missing_designated_init_override : Warning< def warn_objc_implementation_missing_designated_init_override : Warning<
"method override for the designated initializer of the superclass %objcinstance0 not found">, "method override for the designated initializer of the superclass %objcinstance0 not found">,
InGroup<ObjCDesignatedInit>; InGroup<ObjCDesignatedInit>;
def err_designated_init_attr_non_init : Error<
"'objc_designated_initializer' attribute only applies to init methods "
"of interface or class extension declarations">;
// objc_bridge attribute diagnostics. // objc_bridge attribute diagnostics.
def err_objc_attr_not_id : Error< def err_objc_attr_not_id : Error<

View File

@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H #ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H
#define LLVM_CLANG_BASIC_OPENCLOPTIONS_H #define LLVM_CLANG_BASIC_OPENCLOPTIONS_H
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
namespace clang { namespace clang {
@ -42,25 +43,29 @@ class OpenCLOptions {
// Is supported as either an extension or an (optional) core feature for // Is supported as either an extension or an (optional) core feature for
// OpenCL version \p CLVer. // OpenCL version \p CLVer.
bool isSupported(llvm::StringRef Ext, unsigned CLVer) const { bool isSupported(llvm::StringRef Ext, LangOptions LO) const {
// In C++ mode all extensions should work at least as in v2.0.
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
auto I = OptMap.find(Ext)->getValue(); auto I = OptMap.find(Ext)->getValue();
return I.Supported && I.Avail <= CLVer; return I.Supported && I.Avail <= CLVer;
} }
// Is supported (optional) OpenCL core features for OpenCL version \p CLVer. // Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
// For supported extension, return false. // For supported extension, return false.
bool isSupportedCore(llvm::StringRef Ext, unsigned CLVer) const { bool isSupportedCore(llvm::StringRef Ext, LangOptions LO) const {
// In C++ mode all extensions should work at least as in v2.0.
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
auto I = OptMap.find(Ext)->getValue(); auto I = OptMap.find(Ext)->getValue();
return I.Supported && I.Avail <= CLVer && return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core;
I.Core != ~0U && CLVer >= I.Core;
} }
// Is supported OpenCL extension for OpenCL version \p CLVer. // Is supported OpenCL extension for OpenCL version \p CLVer.
// For supported (optional) core feature, return false. // For supported (optional) core feature, return false.
bool isSupportedExtension(llvm::StringRef Ext, unsigned CLVer) const { bool isSupportedExtension(llvm::StringRef Ext, LangOptions LO) const {
// In C++ mode all extensions should work at least as in v2.0.
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
auto I = OptMap.find(Ext)->getValue(); auto I = OptMap.find(Ext)->getValue();
return I.Supported && I.Avail <= CLVer && return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core);
(I.Core == ~0U || CLVer < I.Core);
} }
void enable(llvm::StringRef Ext, bool V = true) { void enable(llvm::StringRef Ext, bool V = true) {
@ -122,10 +127,10 @@ class OpenCLOptions {
I->second.Enabled = false; I->second.Enabled = false;
} }
void enableSupportedCore(unsigned CLVer) { void enableSupportedCore(LangOptions LO) {
for (llvm::StringMap<Info>::iterator I = OptMap.begin(), for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end();
E = OptMap.end(); I != E; ++I) I != E; ++I)
if (isSupportedCore(I->getKey(), CLVer)) if (isSupportedCore(I->getKey(), LO))
I->second.Enabled = true; I->second.Enabled = true;
} }
@ -133,6 +138,6 @@ class OpenCLOptions {
friend class ASTReader; friend class ASTReader;
}; };
} // end namespace clang } // end namespace clang
#endif #endif

View File

@ -552,9 +552,9 @@ def cuda_compile_host_device : Flag<["--"], "cuda-compile-host-device">,
HelpText<"Compile CUDA code for both host and device (default). Has no " HelpText<"Compile CUDA code for both host and device (default). Has no "
"effect on non-CUDA compilations.">; "effect on non-CUDA compilations.">;
def cuda_include_ptx_EQ : Joined<["--"], "cuda-include-ptx=">, Flags<[DriverOption]>, def cuda_include_ptx_EQ : Joined<["--"], "cuda-include-ptx=">, Flags<[DriverOption]>,
HelpText<"Include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">; HelpText<"Include PTX for the following GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">;
def no_cuda_include_ptx_EQ : Joined<["--"], "no-cuda-include-ptx=">, Flags<[DriverOption]>, def no_cuda_include_ptx_EQ : Joined<["--"], "no-cuda-include-ptx=">, Flags<[DriverOption]>,
HelpText<"Do not include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">; HelpText<"Do not include PTX for the following GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">;
def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">, Flags<[DriverOption]>, def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">, Flags<[DriverOption]>,
HelpText<"CUDA GPU architecture (e.g. sm_35). May be specified more than once.">; HelpText<"CUDA GPU architecture (e.g. sm_35). May be specified more than once.">;
def hip_link : Flag<["--"], "hip-link">, def hip_link : Flag<["--"], "hip-link">,

View File

@ -360,11 +360,6 @@ class Parser : public CodeCompletionHandler {
/// just a regular sub-expression. /// just a regular sub-expression.
SourceLocation ExprStatementTokLoc; SourceLocation ExprStatementTokLoc;
/// Tests whether an expression value is discarded based on token lookahead.
/// It will return true if the lexer is currently processing the })
/// terminating a GNU statement expression and false otherwise.
bool isExprValueDiscarded();
public: public:
Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
~Parser() override; ~Parser() override;

View File

@ -1369,7 +1369,6 @@ class Sema {
void PopCompoundScope(); void PopCompoundScope();
sema::CompoundScopeInfo &getCurCompoundScope() const; sema::CompoundScopeInfo &getCurCompoundScope() const;
bool isCurCompoundStmtAStmtExpr() const;
bool hasAnyUnrecoverableErrorsInThisFunction() const; bool hasAnyUnrecoverableErrorsInThisFunction() const;
@ -3690,17 +3689,16 @@ class Sema {
return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation());
} }
FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) {
return FullExprArg( return FullExprArg(ActOnFinishFullExpr(Arg, CC).get());
ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get());
} }
FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) {
ExprResult FE = ExprResult FE =
ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
/*DiscardedValue*/ true); /*DiscardedValue*/ true);
return FullExprArg(FE.get()); return FullExprArg(FE.get());
} }
StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true); StmtResult ActOnExprStmt(ExprResult Arg);
StmtResult ActOnExprStmtError(); StmtResult ActOnExprStmtError();
StmtResult ActOnNullStmt(SourceLocation SemiLoc, StmtResult ActOnNullStmt(SourceLocation SemiLoc,
@ -5346,12 +5344,13 @@ class Sema {
CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
bool BoundToLvalueReference); bool BoundToLvalueReference);
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) { ExprResult ActOnFinishFullExpr(Expr *Expr) {
return ActOnFinishFullExpr( return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc()
Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue); : SourceLocation());
} }
ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC, ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
bool DiscardedValue, bool IsConstexpr = false); bool DiscardedValue = false,
bool IsConstexpr = false);
StmtResult ActOnFinishFullStmt(Stmt *Stmt); StmtResult ActOnFinishFullStmt(Stmt *Stmt);
// Marks SS invalid if it represents an incomplete type. // Marks SS invalid if it represents an incomplete type.

View File

@ -331,9 +331,15 @@ class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {
break; break;
} }
if (getTriple().isOSFreeBSD()) { switch (getTriple().getOS()) {
case llvm::Triple::FreeBSD:
case llvm::Triple::NetBSD:
case llvm::Triple::OpenBSD:
LongDoubleWidth = LongDoubleAlign = 64; LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble(); LongDoubleFormat = &llvm::APFloat::IEEEdouble();
break;
default:
break;
} }
// PPC32 supports atomics up to 4 bytes. // PPC32 supports atomics up to 4 bytes.

View File

@ -7052,19 +7052,16 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
llvm::Type *RegisterType = Int64Ty; llvm::Type *RegisterType = Int64Ty;
llvm::Type *ValueType = Int32Ty;
llvm::Type *Types[] = { RegisterType }; llvm::Type *Types[] = { RegisterType };
if (BuiltinID == AArch64::BI_ReadStatusReg) { if (BuiltinID == AArch64::BI_ReadStatusReg) {
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types); llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
llvm::Value *Call = Builder.CreateCall(F, Metadata);
return Builder.CreateTrunc(Call, ValueType); return Builder.CreateCall(F, Metadata);
} }
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types); llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1)); llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1));
ArgValue = Builder.CreateZExt(ArgValue, RegisterType);
return Builder.CreateCall(F, { Metadata, ArgValue }); return Builder.CreateCall(F, { Metadata, ArgValue });
} }

View File

@ -1631,11 +1631,15 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
? LangOptions::TrivialAutoVarInitKind::Uninitialized ? LangOptions::TrivialAutoVarInitKind::Uninitialized
: getContext().getLangOpts().getTrivialAutoVarInit())); : getContext().getLangOpts().getTrivialAutoVarInit()));
auto initializeWhatIsTechnicallyUninitialized = [&]() { auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) {
if (trivialAutoVarInit == if (trivialAutoVarInit ==
LangOptions::TrivialAutoVarInitKind::Uninitialized) LangOptions::TrivialAutoVarInitKind::Uninitialized)
return; return;
// Only initialize a __block's storage: we always initialize the header.
if (emission.IsEscapingByRef)
Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false);
CharUnits Size = getContext().getTypeSizeInChars(type); CharUnits Size = getContext().getTypeSizeInChars(type);
if (!Size.isZero()) { if (!Size.isZero()) {
switch (trivialAutoVarInit) { switch (trivialAutoVarInit) {
@ -1713,7 +1717,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
}; };
if (isTrivialInitializer(Init)) { if (isTrivialInitializer(Init)) {
initializeWhatIsTechnicallyUninitialized(); initializeWhatIsTechnicallyUninitialized(Loc);
return; return;
} }
@ -1727,7 +1731,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
} }
if (!constant) { if (!constant) {
initializeWhatIsTechnicallyUninitialized(); initializeWhatIsTechnicallyUninitialized(Loc);
LValue lv = MakeAddrLValue(Loc, type); LValue lv = MakeAddrLValue(Loc, type);
lv.setNonGC(true); lv.setNonGC(true);
return EmitExprAsInit(Init, &D, lv, capturedByInit); return EmitExprAsInit(Init, &D, lv, capturedByInit);

View File

@ -3762,13 +3762,15 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
} }
} }
// Microsoft's link.exe doesn't support alignments greater than 32 for common // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
// symbols, so symbols with greater alignment requirements cannot be common. // common symbols, so symbols with greater alignment requirements cannot be
// common.
// Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
// alignments for common symbols via the aligncomm directive, so this // alignments for common symbols via the aligncomm directive, so this
// restriction only applies to MSVC environments. // restriction only applies to MSVC environments.
if (Context.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() && if (Context.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
Context.getTypeAlignIfKnown(D->getType()) > 32) Context.getTypeAlignIfKnown(D->getType()) >
Context.toBits(CharUnits::fromQuantity(32)))
return true; return true;
return false; return false;

View File

@ -761,6 +761,22 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override { CodeGen::CodeGenModule &CGM) const override {
TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (const auto *Attr = FD->getAttr<WebAssemblyImportModuleAttr>()) {
llvm::Function *Fn = cast<llvm::Function>(GV);
llvm::AttrBuilder B;
B.addAttribute("wasm-import-module", Attr->getImportModule());
Fn->addAttributes(llvm::AttributeList::FunctionIndex, B);
}
if (const auto *Attr = FD->getAttr<WebAssemblyImportNameAttr>()) {
llvm::Function *Fn = cast<llvm::Function>(GV);
llvm::AttrBuilder B;
B.addAttribute("wasm-import-name", Attr->getImportName());
Fn->addAttributes(llvm::AttributeList::FunctionIndex, B);
}
}
if (auto *FD = dyn_cast_or_null<FunctionDecl>(D)) { if (auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
llvm::Function *Fn = cast<llvm::Function>(GV); llvm::Function *Fn = cast<llvm::Function>(GV);
if (!FD->doesThisDeclarationHaveABody() && !FD->hasPrototype()) if (!FD->doesThisDeclarationHaveABody() && !FD->hasPrototype())

View File

@ -1408,10 +1408,10 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
DAL.AddFlagArg( DAL.AddFlagArg(
A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
} else { } else {
// Don't warn about /Oy- in 64-bit builds (where // Don't warn about /Oy- in x86-64 builds (where
// SupportsForcingFramePointer is false). The flag having no effect // SupportsForcingFramePointer is false). The flag having no effect
// there is a compiler-internal optimization, and people shouldn't have // there is a compiler-internal optimization, and people shouldn't have
// to special-case their build files for 64-bit clang-cl. // to special-case their build files for x86-64 clang-cl.
A->claim(); A->claim();
} }
break; break;
@ -1442,8 +1442,8 @@ MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
const OptTable &Opts = getDriver().getOpts(); const OptTable &Opts = getDriver().getOpts();
// /Oy and /Oy- only has an effect under X86-32. // /Oy and /Oy- don't have an effect on X86-64
bool SupportsForcingFramePointer = getArch() == llvm::Triple::x86; bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
// The -O[12xd] flag actually expands to several flags. We must desugar the // The -O[12xd] flag actually expands to several flags. We must desugar the
// flags so that options embedded can be negated. For example, the '-O2' flag // flags so that options embedded can be negated. For example, the '-O2' flag

View File

@ -1059,10 +1059,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
// OpenCL definitions. // OpenCL definitions.
if (LangOpts.OpenCL) { if (LangOpts.OpenCL) {
#define OPENCLEXT(Ext) \ #define OPENCLEXT(Ext) \
if (TI.getSupportedOpenCLOpts().isSupported(#Ext, \ if (TI.getSupportedOpenCLOpts().isSupported(#Ext, LangOpts)) \
LangOpts.OpenCLVersion)) \ Builder.defineMacro(#Ext);
Builder.defineMacro(#Ext);
#include "clang/Basic/OpenCLExtensions.def" #include "clang/Basic/OpenCLExtensions.def"
auto Arch = TI.getTriple().getArch(); auto Arch = TI.getTriple().getArch();

View File

@ -564,8 +564,8 @@ __nop(void) {
#if defined(__aarch64__) #if defined(__aarch64__)
unsigned __int64 __getReg(int); unsigned __int64 __getReg(int);
long _InterlockedAdd(long volatile *Addend, long Value); long _InterlockedAdd(long volatile *Addend, long Value);
int _ReadStatusReg(int); __int64 _ReadStatusReg(int);
void _WriteStatusReg(int, int); void _WriteStatusReg(int, __int64);
static inline unsigned short _byteswap_ushort (unsigned short val) { static inline unsigned short _byteswap_ushort (unsigned short val) {
return __builtin_bswap16(val); return __builtin_bswap16(val);

View File

@ -2741,7 +2741,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
// Otherwise, eat the semicolon. // Otherwise, eat the semicolon.
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
return Actions.ActOnExprStmt(Res, isExprValueDiscarded()); return Actions.ActOnExprStmt(Res);
} }
ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {

View File

@ -314,7 +314,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
ExprResult CombinerResult = ExprResult CombinerResult =
Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
D->getLocation(), /*DiscardedValue*/ false); D->getLocation(), /*DiscardedValue=*/true);
Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
@ -356,7 +356,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
if (Actions.getLangOpts().CPlusPlus) { if (Actions.getLangOpts().CPlusPlus) {
InitializerResult = Actions.ActOnFinishFullExpr( InitializerResult = Actions.ActOnFinishFullExpr(
ParseAssignmentExpression().get(), D->getLocation(), ParseAssignmentExpression().get(), D->getLocation(),
/*DiscardedValue*/ false); /*DiscardedValue=*/true);
} else { } else {
ConsumeToken(); ConsumeToken();
ParseOpenMPReductionInitializerForDecl(OmpPrivParm); ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
@ -364,7 +364,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
} else { } else {
InitializerResult = Actions.ActOnFinishFullExpr( InitializerResult = Actions.ActOnFinishFullExpr(
ParseAssignmentExpression().get(), D->getLocation(), ParseAssignmentExpression().get(), D->getLocation(),
/*DiscardedValue*/ false); /*DiscardedValue=*/true);
} }
Actions.ActOnOpenMPDeclareReductionInitializerEnd( Actions.ActOnOpenMPDeclareReductionInitializerEnd(
D, InitializerResult.get(), OmpPrivParm); D, InitializerResult.get(), OmpPrivParm);
@ -1455,7 +1455,7 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
ExprResult LHS(ParseCastExpression( ExprResult LHS(ParseCastExpression(
/*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
// Parse ')'. // Parse ')'.
RLoc = Tok.getLocation(); RLoc = Tok.getLocation();
@ -1711,8 +1711,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
SourceLocation ELoc = Tok.getLocation(); SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
Val = Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
} }
// Parse ')'. // Parse ')'.
@ -1997,8 +1996,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.ColonLoc = Tok.getLocation(); Data.ColonLoc = Tok.getLocation();
SourceLocation ELoc = ConsumeToken(); SourceLocation ELoc = ConsumeToken();
ExprResult Tail = ParseAssignmentExpression(); ExprResult Tail = ParseAssignmentExpression();
Tail = Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
if (Tail.isUsable()) if (Tail.isUsable())
Data.TailExpr = Tail.get(); Data.TailExpr = Tail.get();
else else

View File

@ -693,13 +693,12 @@ void Parser::HandlePragmaOpenCLExtension() {
if (Name == "all") { if (Name == "all") {
if (State == Disable) { if (State == Disable) {
Opt.disableAll(); Opt.disableAll();
Opt.enableSupportedCore(getLangOpts().OpenCLVersion); Opt.enableSupportedCore(getLangOpts());
} else { } else {
PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1; PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
} }
} else if (State == Begin) { } else if (State == Begin) {
if (!Opt.isKnown(Name) || if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
!Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
Opt.support(Name); Opt.support(Name);
} }
Actions.setCurrentOpenCLExtension(Name); Actions.setCurrentOpenCLExtension(Name);
@ -709,9 +708,9 @@ void Parser::HandlePragmaOpenCLExtension() {
Actions.setCurrentOpenCLExtension(""); Actions.setCurrentOpenCLExtension("");
} else if (!Opt.isKnown(Name)) } else if (!Opt.isKnown(Name))
PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident; PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion)) else if (Opt.isSupportedExtension(Name, getLangOpts()))
Opt.enable(Name, State == Enable); Opt.enable(Name, State == Enable);
else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion)) else if (Opt.isSupportedCore(Name, getLangOpts()))
PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident; PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
else else
PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident; PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;

View File

@ -439,7 +439,7 @@ StmtResult Parser::ParseExprStatement() {
// Otherwise, eat the semicolon. // Otherwise, eat the semicolon.
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
return Actions.ActOnExprStmt(Expr, isExprValueDiscarded()); return Actions.ActOnExprStmt(Expr);
} }
/// ParseSEHTryBlockCommon /// ParseSEHTryBlockCommon
@ -958,16 +958,6 @@ bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
return true; return true;
} }
bool Parser::isExprValueDiscarded() {
if (Actions.isCurCompoundStmtAStmtExpr()) {
// Look to see if the next two tokens close the statement expression;
// if so, this expression statement is the last statement in a
// statment expression.
return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren);
}
return true;
}
/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
/// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// ActOnCompoundStmt action. This expects the '{' to be the current token, and
/// consume the '}' at the end of the block. It does not manipulate the scope /// consume the '}' at the end of the block. It does not manipulate the scope
@ -1072,7 +1062,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
// Eat the semicolon at the end of stmt and convert the expr into a // Eat the semicolon at the end of stmt and convert the expr into a
// statement. // statement.
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
R = Actions.ActOnExprStmt(Res, isExprValueDiscarded()); R = Actions.ActOnExprStmt(Res);
} }
} }
@ -1708,16 +1698,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
if (!Value.isInvalid()) { if (!Value.isInvalid()) {
if (ForEach) if (ForEach)
FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); FirstPart = Actions.ActOnForEachLValueExpr(Value.get());
else { else
// We already know this is not an init-statement within a for loop, so FirstPart = Actions.ActOnExprStmt(Value);
// if we are parsing a C++11 range-based for loop, we should treat this
// expression statement as being a discarded value expression because
// we will err below. This way we do not warn on an unused expression
// that was an error in the first place, like with: for (expr : expr);
bool IsRangeBasedFor =
getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor);
}
} }
if (Tok.is(tok::semi)) { if (Tok.is(tok::semi)) {

View File

@ -637,7 +637,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
// Filter out "fpsw" and "mxcsr". They aren't valid GCC asm clobber // Filter out "fpsw" and "mxcsr". They aren't valid GCC asm clobber
// constraints. Clang always adds fpsr to the clobber list anyway. // constraints. Clang always adds fpsr to the clobber list anyway.
llvm::erase_if(Clobbers, [](const std::string &C) { llvm::erase_if(Clobbers, [](const std::string &C) {
return C == "fpsw" || C == "mxcsr"; return C == "fpsr" || C == "mxcsr";
}); });
// Build the vector of clobber StringRefs. // Build the vector of clobber StringRefs.

View File

@ -256,11 +256,12 @@ void Sema::Initialize() {
// Initialize predefined OpenCL types and supported extensions and (optional) // Initialize predefined OpenCL types and supported extensions and (optional)
// core features. // core features.
if (getLangOpts().OpenCL) { if (getLangOpts().OpenCL) {
getOpenCLOptions().addSupport(Context.getTargetInfo().getSupportedOpenCLOpts()); getOpenCLOptions().addSupport(
getOpenCLOptions().enableSupportedCore(getLangOpts().OpenCLVersion); Context.getTargetInfo().getSupportedOpenCLOpts());
getOpenCLOptions().enableSupportedCore(getLangOpts());
addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy); addImplicitTypedef("event_t", Context.OCLEventTy);
if (getLangOpts().OpenCLVersion >= 200) { if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) {
addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
addImplicitTypedef("queue_t", Context.OCLQueueTy); addImplicitTypedef("queue_t", Context.OCLQueueTy);
addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy); addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);

View File

@ -10622,16 +10622,16 @@ static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) {
// The below checks assume source is floating point. // The below checks assume source is floating point.
if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return;
// If source is floating point but target is not. // If source is floating point but target is an integer.
if (!ResultBT->isFloatingPoint()) if (ResultBT->isInteger())
return DiagnoseFloatingImpCast(S, E, E->getRHS()->getType(), DiagnoseImpCast(S, E, E->getRHS()->getType(), E->getLHS()->getType(),
E->getExprLoc()); E->getExprLoc(), diag::warn_impcast_float_integer);
// If both source and target are floating points. Builtin FP kinds are ordered
// If both source and target are floating points. // by increasing FP rank. FIXME: except _Float16, we currently emit a bogus
// Builtin FP kinds are ordered by increasing FP rank. // warning.
if (ResultBT->getKind() < RBT->getKind() && else if (ResultBT->isFloatingPoint() && ResultBT->getKind() < RBT->getKind() &&
// We don't want to warn for system macro. // We don't want to warn for system macro.
!S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) !S.SourceMgr.isInSystemMacro(E->getOperatorLoc()))
// warn about dropping FP rank. // warn about dropping FP rank.
DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(), DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(),
diag::warn_impcast_float_result_precision); diag::warn_impcast_float_result_precision);

View File

@ -646,7 +646,7 @@ bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc,
return StmtError(); return StmtError();
Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(), Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(),
/*IsImplicit*/ true); /*IsImplicit*/ true);
Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false); Suspend = ActOnFinishFullExpr(Suspend.get());
if (Suspend.isInvalid()) { if (Suspend.isInvalid()) {
Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
<< ((Name == "initial_suspend") ? 0 : 1); << ((Name == "initial_suspend") ? 0 : 1);
@ -867,7 +867,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
if (PC.isInvalid()) if (PC.isInvalid())
return StmtError(); return StmtError();
Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get(); Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit); Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
return Res; return Res;
@ -1236,7 +1236,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
ExprResult NewExpr = ExprResult NewExpr =
S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc); S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false); NewExpr = S.ActOnFinishFullExpr(NewExpr.get());
if (NewExpr.isInvalid()) if (NewExpr.isInvalid())
return false; return false;
@ -1262,8 +1262,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
ExprResult DeleteExpr = ExprResult DeleteExpr =
S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
DeleteExpr = DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get());
S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false);
if (DeleteExpr.isInvalid()) if (DeleteExpr.isInvalid())
return false; return false;
@ -1348,8 +1347,7 @@ bool CoroutineStmtBuilder::makeOnException() {
ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc, ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc,
"unhandled_exception", None); "unhandled_exception", None);
UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc, UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc);
/*DiscardedValue*/ false);
if (UnhandledException.isInvalid()) if (UnhandledException.isInvalid())
return false; return false;
@ -1402,8 +1400,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
"get_return_object type must no longer be dependent"); "get_return_object type must no longer be dependent");
if (FnRetType->isVoidType()) { if (FnRetType->isVoidType()) {
ExprResult Res = ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc);
S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false);
if (Res.isInvalid()) if (Res.isInvalid())
return false; return false;
@ -1435,7 +1432,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
if (Res.isInvalid()) if (Res.isInvalid())
return false; return false;
Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false); Res = S.ActOnFinishFullExpr(Res.get());
if (Res.isInvalid()) if (Res.isInvalid())
return false; return false;

View File

@ -11200,9 +11200,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// struct T { S a, b; } t = { Temp(), Temp() } // struct T { S a, b; } t = { Temp(), Temp() }
// //
// we should destroy the first Temp before constructing the second. // we should destroy the first Temp before constructing the second.
ExprResult Result = ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(),
ActOnFinishFullExpr(Init, VDecl->getLocation(), false,
/*DiscardedValue*/ false, VDecl->isConstexpr()); VDecl->isConstexpr());
if (Result.isInvalid()) { if (Result.isInvalid()) {
VDecl->setInvalidDecl(); VDecl->setInvalidDecl();
return; return;

View File

@ -5116,11 +5116,22 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D,
static void handleObjCDesignatedInitializer(Sema &S, Decl *D, static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
const ParsedAttr &AL) { const ParsedAttr &AL) {
DeclContext *Ctx = D->getDeclContext();
// This attribute can only be applied to methods in interfaces or class
// extensions.
if (!isa<ObjCInterfaceDecl>(Ctx) &&
!(isa<ObjCCategoryDecl>(Ctx) &&
cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) {
S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
return;
}
ObjCInterfaceDecl *IFace; ObjCInterfaceDecl *IFace;
if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(D->getDeclContext())) if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx))
IFace = CatDecl->getClassInterface(); IFace = CatDecl->getClassInterface();
else else
IFace = cast<ObjCInterfaceDecl>(D->getDeclContext()); IFace = cast<ObjCInterfaceDecl>(Ctx);
if (!IFace) if (!IFace)
return; return;
@ -5577,6 +5588,51 @@ static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
handleSimpleAttribute<AVRSignalAttr>(S, D, AL); handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
} }
static void handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'import_module'" << ExpectedFunction;
return;
}
auto *FD = cast<FunctionDecl>(D);
if (FD->isThisDeclarationADefinition()) {
S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
return;
}
StringRef Str;
SourceLocation ArgLoc;
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
return;
FD->addAttr(::new (S.Context) WebAssemblyImportModuleAttr(
AL.getRange(), S.Context, Str,
AL.getAttributeSpellingListIndex()));
}
static void handleWebAssemblyImportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'import_name'" << ExpectedFunction;
return;
}
auto *FD = cast<FunctionDecl>(D);
if (FD->isThisDeclarationADefinition()) {
S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
return;
}
StringRef Str;
SourceLocation ArgLoc;
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
return;
FD->addAttr(::new (S.Context) WebAssemblyImportNameAttr(
AL.getRange(), S.Context, Str,
AL.getAttributeSpellingListIndex()));
}
static void handleRISCVInterruptAttr(Sema &S, Decl *D, static void handleRISCVInterruptAttr(Sema &S, Decl *D,
const ParsedAttr &AL) { const ParsedAttr &AL) {
@ -6330,6 +6386,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_AVRSignal: case ParsedAttr::AT_AVRSignal:
handleAVRSignalAttr(S, D, AL); handleAVRSignalAttr(S, D, AL);
break; break;
case ParsedAttr::AT_WebAssemblyImportModule:
handleWebAssemblyImportModuleAttr(S, D, AL);
break;
case ParsedAttr::AT_WebAssemblyImportName:
handleWebAssemblyImportNameAttr(S, D, AL);
break;
case ParsedAttr::AT_IBAction: case ParsedAttr::AT_IBAction:
handleSimpleAttribute<IBActionAttr>(S, D, AL); handleSimpleAttribute<IBActionAttr>(S, D, AL);
break; break;
@ -7016,6 +7078,17 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
} }
} }
} }
// Do this check after processing D's attributes because the attribute
// objc_method_family can change whether the given method is in the init
// family, and it can be applied after objc_designated_initializer. This is a
// bit of a hack, but we need it to be compatible with versions of clang that
// processed the attribute list in the wrong order.
if (D->hasAttr<ObjCDesignatedInitializerAttr>() &&
cast<ObjCMethodDecl>(D)->getMethodFamily() != OMF_init) {
Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
D->dropAttr<ObjCDesignatedInitializerAttr>();
}
} }
// Helper for delayed processing TransparentUnion attribute. // Helper for delayed processing TransparentUnion attribute.

View File

@ -1205,7 +1205,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
E = Seq.Perform(S, Entity, Kind, Init); E = Seq.Perform(S, Entity, Kind, Init);
if (E.isInvalid()) if (E.isInvalid())
return true; return true;
E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false); E = S.ActOnFinishFullExpr(E.get(), Loc);
if (E.isInvalid()) if (E.isInvalid())
return true; return true;
RefVD->setInit(E.get()); RefVD->setInit(E.get());
@ -3686,7 +3686,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
// C++11 [class.base.init]p7: // C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a // The initialization of each base and member constitutes a
// full-expression. // full-expression.
Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false); Init = ActOnFinishFullExpr(Init.get(), InitLoc);
if (Init.isInvalid()) { if (Init.isInvalid()) {
FD->setInvalidDecl(); FD->setInvalidDecl();
return; return;
@ -4044,8 +4044,7 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
// C++11 [class.base.init]p7: // C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a // The initialization of each base and member constitutes a
// full-expression. // full-expression.
MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(), MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin());
/*DiscardedValue*/ false);
if (MemberInit.isInvalid()) if (MemberInit.isInvalid())
return true; return true;
@ -4100,8 +4099,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
// C++11 [class.base.init]p7: // C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a // The initialization of each base and member constitutes a
// full-expression. // full-expression.
DelegationInit = ActOnFinishFullExpr( DelegationInit = ActOnFinishFullExpr(DelegationInit.get(),
DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false); InitRange.getBegin());
if (DelegationInit.isInvalid()) if (DelegationInit.isInvalid())
return true; return true;
@ -4230,8 +4229,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
// C++11 [class.base.init]p7: // C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a // The initialization of each base and member constitutes a
// full-expression. // full-expression.
BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(), BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin());
/*DiscardedValue*/ false);
if (BaseInit.isInvalid()) if (BaseInit.isInvalid())
return true; return true;

View File

@ -4723,9 +4723,8 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
if (Result.isInvalid()) if (Result.isInvalid())
return true; return true;
Result = Result = ActOnFinishFullExpr(Result.getAs<Expr>(),
ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(), Param->getOuterLocStart());
/*DiscardedValue*/ false);
if (Result.isInvalid()) if (Result.isInvalid())
return true; return true;

View File

@ -7815,8 +7815,6 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
FullExpr = IgnoredValueConversions(FullExpr.get()); FullExpr = IgnoredValueConversions(FullExpr.get());
if (FullExpr.isInvalid()) if (FullExpr.isInvalid())
return ExprError(); return ExprError();
DiagnoseUnusedExprResult(FullExpr.get());
} }
FullExpr = CorrectDelayedTyposInExpr(FullExpr.get()); FullExpr = CorrectDelayedTyposInExpr(FullExpr.get());

View File

@ -1724,7 +1724,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
/*NRVO=*/false), /*NRVO=*/false),
CurrentLocation, Src); CurrentLocation, Src);
if (!Init.isInvalid()) if (!Init.isInvalid())
Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); Init = ActOnFinishFullExpr(Init.get());
if (Init.isInvalid()) if (Init.isInvalid())
return ExprError(); return ExprError();

View File

@ -5367,7 +5367,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
LastIteration.get(), UB.get()); LastIteration.get(), UB.get());
EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
CondOp.get()); CondOp.get());
EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false); EUB = SemaRef.ActOnFinishFullExpr(EUB.get());
// If we have a combined directive that combines 'distribute', 'for' or // If we have a combined directive that combines 'distribute', 'for' or
// 'simd' we need to be able to access the bounds of the schedule of the // 'simd' we need to be able to access the bounds of the schedule of the
@ -5396,8 +5396,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
LastIteration.get(), CombUB.get()); LastIteration.get(), CombUB.get());
CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
CombCondOp.get()); CombCondOp.get());
CombEUB = CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get());
SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl(); const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
// We expect to have at least 2 more parameters than the 'parallel' // We expect to have at least 2 more parameters than the 'parallel'
@ -5431,7 +5430,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
? LB.get() ? LB.get()
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); Init = SemaRef.ActOnFinishFullExpr(Init.get());
if (isOpenMPLoopBoundSharingDirective(DKind)) { if (isOpenMPLoopBoundSharingDirective(DKind)) {
Expr *CombRHS = Expr *CombRHS =
@ -5442,8 +5441,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
CombInit = CombInit =
SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
CombInit = CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get());
SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
} }
} }
@ -5475,7 +5473,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
if (!Inc.isUsable()) if (!Inc.isUsable())
return 0; return 0;
Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false); Inc = SemaRef.ActOnFinishFullExpr(Inc.get());
if (!Inc.isUsable()) if (!Inc.isUsable())
return 0; return 0;
@ -5493,8 +5491,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// LB = LB + ST // LB = LB + ST
NextLB = NextLB =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
NextLB = NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get());
SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
if (!NextLB.isUsable()) if (!NextLB.isUsable())
return 0; return 0;
// UB + ST // UB + ST
@ -5504,8 +5501,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// UB = UB + ST // UB = UB + ST
NextUB = NextUB =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
NextUB = NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get());
SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
if (!NextUB.isUsable()) if (!NextUB.isUsable())
return 0; return 0;
if (isOpenMPLoopBoundSharingDirective(DKind)) { if (isOpenMPLoopBoundSharingDirective(DKind)) {
@ -5516,8 +5512,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// LB = LB + ST // LB = LB + ST
CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
CombNextLB.get()); CombNextLB.get());
CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get());
/*DiscardedValue*/ false);
if (!CombNextLB.isUsable()) if (!CombNextLB.isUsable())
return 0; return 0;
// UB + ST // UB + ST
@ -5528,8 +5523,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// UB = UB + ST // UB = UB + ST
CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
CombNextUB.get()); CombNextUB.get());
CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get());
/*DiscardedValue*/ false);
if (!CombNextUB.isUsable()) if (!CombNextUB.isUsable())
return 0; return 0;
} }
@ -5550,8 +5544,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
assert(DistInc.isUsable() && "distribute inc expr was not built"); assert(DistInc.isUsable() && "distribute inc expr was not built");
DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
DistInc.get()); DistInc.get());
DistInc = DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get());
SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
assert(DistInc.isUsable() && "distribute inc expr was not built"); assert(DistInc.isUsable() && "distribute inc expr was not built");
// Build expression: UB = min(UB, prevUB) for #for in composite or combined // Build expression: UB = min(UB, prevUB) for #for in composite or combined
@ -5563,8 +5556,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get()); DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get());
PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
CondOp.get()); CondOp.get());
PrevEUB = PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get());
SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
// Build IV <= PrevUB to be used in parallel for is in combination with // Build IV <= PrevUB to be used in parallel for is in combination with
// a distribute directive with schedule(static, 1) // a distribute directive with schedule(static, 1)
@ -5680,10 +5672,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Built.IterationVarRef = IV.get(); Built.IterationVarRef = IV.get();
Built.LastIteration = LastIteration.get(); Built.LastIteration = LastIteration.get();
Built.NumIterations = NumIterations.get(); Built.NumIterations = NumIterations.get();
Built.CalcLastIteration = SemaRef Built.CalcLastIteration =
.ActOnFinishFullExpr(CalcLastIteration.get(), SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get();
/*DiscardedValue*/ false)
.get();
Built.PreCond = PreCond.get(); Built.PreCond = PreCond.get();
Built.PreInits = buildPreInits(C, Captures); Built.PreInits = buildPreInits(C, Captures);
Built.Cond = Cond.get(); Built.Cond = Cond.get();
@ -10358,8 +10348,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
PseudoDstExpr, PseudoSrcExpr); PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid()) if (AssignmentOp.isInvalid())
continue; continue;
AssignmentOp = AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); /*DiscardedValue=*/true);
if (AssignmentOp.isInvalid()) if (AssignmentOp.isInvalid())
continue; continue;
@ -11357,8 +11347,7 @@ static bool actOnOMPReductionKindClause(
BO_Assign, LHSDRE, ConditionalOp); BO_Assign, LHSDRE, ConditionalOp);
} }
if (ReductionOp.isUsable()) if (ReductionOp.isUsable())
ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get());
/*DiscardedValue*/ false);
} }
if (!ReductionOp.isUsable()) if (!ReductionOp.isUsable())
continue; continue;
@ -11688,7 +11677,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
ExprResult CalcStep = ExprResult CalcStep =
BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false); CalcStep = ActOnFinishFullExpr(CalcStep.get());
// Warn about zero linear step (it would be probably better specified as // Warn about zero linear step (it would be probably better specified as
// making corresponding variables 'const'). // making corresponding variables 'const').
@ -11776,7 +11765,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
else else
Update = *CurPrivate; Update = *CurPrivate;
Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
/*DiscardedValue*/ false); /*DiscardedValue=*/true);
// Build final: Var = InitExpr + NumIterations * Step // Build final: Var = InitExpr + NumIterations * Step
ExprResult Final; ExprResult Final;
@ -11787,7 +11776,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
else else
Final = *CurPrivate; Final = *CurPrivate;
Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
/*DiscardedValue*/ false); /*DiscardedValue=*/true);
if (!Update.isUsable() || !Final.isUsable()) { if (!Update.isUsable() || !Final.isUsable()) {
Updates.push_back(nullptr); Updates.push_back(nullptr);
@ -11955,7 +11944,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
if (AssignmentOp.isInvalid()) if (AssignmentOp.isInvalid())
continue; continue;
AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
/*DiscardedValue*/ false); /*DiscardedValue=*/true);
if (AssignmentOp.isInvalid()) if (AssignmentOp.isInvalid())
continue; continue;
@ -12063,8 +12052,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid()) if (AssignmentOp.isInvalid())
continue; continue;
AssignmentOp = AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); /*DiscardedValue=*/true);
if (AssignmentOp.isInvalid()) if (AssignmentOp.isInvalid())
continue; continue;

View File

@ -42,11 +42,12 @@
using namespace clang; using namespace clang;
using namespace sema; using namespace sema;
StmtResult Sema::ActOnExprStmt(ExprResult FE, bool DiscardedValue) { StmtResult Sema::ActOnExprStmt(ExprResult FE) {
if (FE.isInvalid()) if (FE.isInvalid())
return StmtError(); return StmtError();
FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), DiscardedValue); FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(),
/*DiscardedValue*/ true);
if (FE.isInvalid()) if (FE.isInvalid())
return StmtError(); return StmtError();
@ -347,10 +348,6 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const {
return getCurFunction()->CompoundScopes.back(); return getCurFunction()->CompoundScopes.back();
} }
bool Sema::isCurCompoundStmtAStmtExpr() const {
return getCurCompoundScope().IsStmtExpr;
}
StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
ArrayRef<Stmt *> Elts, bool isStmtExpr) { ArrayRef<Stmt *> Elts, bool isStmtExpr) {
const unsigned NumElts = Elts.size(); const unsigned NumElts = Elts.size();
@ -373,6 +370,14 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
Diag(D->getLocation(), diag::ext_mixed_decls_code); Diag(D->getLocation(), diag::ext_mixed_decls_code);
} }
} }
// Warn about unused expressions in statements.
for (unsigned i = 0; i != NumElts; ++i) {
// Ignore statements that are last in a statement expression.
if (isStmtExpr && i == NumElts - 1)
continue;
DiagnoseUnusedExprResult(Elts[i]);
}
// Check for suspicious empty body (null statement) in `for' and `while' // Check for suspicious empty body (null statement) in `for' and `while'
// statements. Don't do anything for template instantiations, this just adds // statements. Don't do anything for template instantiations, this just adds
@ -464,12 +469,15 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal,
/// ActOnCaseStmtBody - This installs a statement as the body of a case. /// ActOnCaseStmtBody - This installs a statement as the body of a case.
void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) { void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) {
DiagnoseUnusedExprResult(SubStmt);
cast<CaseStmt>(S)->setSubStmt(SubStmt); cast<CaseStmt>(S)->setSubStmt(SubStmt);
} }
StmtResult StmtResult
Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
Stmt *SubStmt, Scope *CurScope) { Stmt *SubStmt, Scope *CurScope) {
DiagnoseUnusedExprResult(SubStmt);
if (getCurFunction()->SwitchStack.empty()) { if (getCurFunction()->SwitchStack.empty()) {
Diag(DefaultLoc, diag::err_default_not_in_switch); Diag(DefaultLoc, diag::err_default_not_in_switch);
return SubStmt; return SubStmt;
@ -563,6 +571,9 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second)) if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second))
setFunctionHasBranchProtectedScope(); setFunctionHasBranchProtectedScope();
DiagnoseUnusedExprResult(thenStmt);
DiagnoseUnusedExprResult(elseStmt);
return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first,
Cond.get().second, thenStmt, ElseLoc, elseStmt); Cond.get().second, thenStmt, ElseLoc, elseStmt);
} }
@ -1290,6 +1301,8 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
!Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc()))
CommaVisitor(*this).Visit(CondVal.second); CommaVisitor(*this).Visit(CondVal.second);
DiagnoseUnusedExprResult(Body);
if (isa<NullStmt>(Body)) if (isa<NullStmt>(Body))
getCurCompoundScope().setHasEmptyLoopBodies(); getCurCompoundScope().setHasEmptyLoopBodies();
@ -1309,7 +1322,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
return StmtError(); return StmtError();
Cond = CondResult.get(); Cond = CondResult.get();
CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false); CondResult = ActOnFinishFullExpr(Cond, DoLoc);
if (CondResult.isInvalid()) if (CondResult.isInvalid())
return StmtError(); return StmtError();
Cond = CondResult.get(); Cond = CondResult.get();
@ -1319,6 +1332,8 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
!Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc())) !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc()))
CommaVisitor(*this).Visit(Cond); CommaVisitor(*this).Visit(Cond);
DiagnoseUnusedExprResult(Body);
return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen);
} }
@ -1763,6 +1778,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
CommaVisitor(*this).Visit(Second.get().second); CommaVisitor(*this).Visit(Second.get().second);
Expr *Third = third.release().getAs<Expr>(); Expr *Third = third.release().getAs<Expr>();
DiagnoseUnusedExprResult(First);
DiagnoseUnusedExprResult(Third);
DiagnoseUnusedExprResult(Body);
if (isa<NullStmt>(Body)) if (isa<NullStmt>(Body))
getCurCompoundScope().setHasEmptyLoopBodies(); getCurCompoundScope().setHasEmptyLoopBodies();
@ -1782,7 +1802,7 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
if (result.isInvalid()) return StmtError(); if (result.isInvalid()) return StmtError();
E = result.get(); E = result.get();
ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); ExprResult FullExpr = ActOnFinishFullExpr(E);
if (FullExpr.isInvalid()) if (FullExpr.isInvalid())
return StmtError(); return StmtError();
return StmtResult(static_cast<Stmt*>(FullExpr.get())); return StmtResult(static_cast<Stmt*>(FullExpr.get()));
@ -1936,8 +1956,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
if (CollectionExprResult.isInvalid()) if (CollectionExprResult.isInvalid())
return StmtError(); return StmtError();
CollectionExprResult = CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get());
ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false);
if (CollectionExprResult.isInvalid()) if (CollectionExprResult.isInvalid())
return StmtError(); return StmtError();
@ -2574,8 +2593,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
if (!NotEqExpr.isInvalid()) if (!NotEqExpr.isInvalid())
NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get()); NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get());
if (!NotEqExpr.isInvalid()) if (!NotEqExpr.isInvalid())
NotEqExpr = NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get());
ActOnFinishFullExpr(NotEqExpr.get(), /*DiscardedValue*/ false);
if (NotEqExpr.isInvalid()) { if (NotEqExpr.isInvalid()) {
Diag(RangeLoc, diag::note_for_range_invalid_iterator) Diag(RangeLoc, diag::note_for_range_invalid_iterator)
<< RangeLoc << 0 << BeginRangeRef.get()->getType(); << RangeLoc << 0 << BeginRangeRef.get()->getType();
@ -2598,7 +2616,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
// co_await during the initial parse. // co_await during the initial parse.
IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get()); IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
if (!IncrExpr.isInvalid()) if (!IncrExpr.isInvalid())
IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false); IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
if (IncrExpr.isInvalid()) { if (IncrExpr.isInvalid()) {
Diag(RangeLoc, diag::note_for_range_invalid_iterator) Diag(RangeLoc, diag::note_for_range_invalid_iterator)
<< RangeLoc << 2 << BeginRangeRef.get()->getType() ; << RangeLoc << 2 << BeginRangeRef.get()->getType() ;
@ -2853,7 +2871,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
return StmtError(); return StmtError();
} }
ExprResult ExprRes = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); ExprResult ExprRes = ActOnFinishFullExpr(E);
if (ExprRes.isInvalid()) if (ExprRes.isInvalid())
return StmtError(); return StmtError();
E = ExprRes.get(); E = ExprRes.get();
@ -3203,8 +3221,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
ExpressionEvaluationContext::DiscardedStatement && ExpressionEvaluationContext::DiscardedStatement &&
(HasDeducedReturnType || CurCap->HasImplicitReturnType)) { (HasDeducedReturnType || CurCap->HasImplicitReturnType)) {
if (RetValExp) { if (RetValExp) {
ExprResult ER = ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid()) if (ER.isInvalid())
return StmtError(); return StmtError();
RetValExp = ER.get(); RetValExp = ER.get();
@ -3331,8 +3348,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
} }
if (RetValExp) { if (RetValExp) {
ExprResult ER = ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid()) if (ER.isInvalid())
return StmtError(); return StmtError();
RetValExp = ER.get(); RetValExp = ER.get();
@ -3562,8 +3578,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
ExpressionEvaluationContext::DiscardedStatement && ExpressionEvaluationContext::DiscardedStatement &&
FnRetType->getContainedAutoType()) { FnRetType->getContainedAutoType()) {
if (RetValExp) { if (RetValExp) {
ExprResult ER = ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid()) if (ER.isInvalid())
return StmtError(); return StmtError();
RetValExp = ER.get(); RetValExp = ER.get();
@ -3657,8 +3672,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
} }
if (RetValExp) { if (RetValExp) {
ExprResult ER = ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid()) if (ER.isInvalid())
return StmtError(); return StmtError();
RetValExp = ER.get(); RetValExp = ER.get();
@ -3737,8 +3751,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
} }
if (RetValExp) { if (RetValExp) {
ExprResult ER = ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc);
ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
if (ER.isInvalid()) if (ER.isInvalid())
return StmtError(); return StmtError();
RetValExp = ER.get(); RetValExp = ER.get();
@ -3791,7 +3804,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
if (Result.isInvalid()) if (Result.isInvalid())
return StmtError(); return StmtError();
Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); Result = ActOnFinishFullExpr(Result.get());
if (Result.isInvalid()) if (Result.isInvalid())
return StmtError(); return StmtError();
Throw = Result.get(); Throw = Result.get();
@ -3863,7 +3876,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) {
} }
// The operand to @synchronized is a full-expression. // The operand to @synchronized is a full-expression.
return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); return ActOnFinishFullExpr(operand);
} }
StmtResult StmtResult

View File

@ -328,7 +328,7 @@ class TreeTransform {
/// other mechanism. /// other mechanism.
/// ///
/// \returns the transformed statement. /// \returns the transformed statement.
StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false); StmtResult TransformStmt(Stmt *S);
/// Transform the given statement. /// Transform the given statement.
/// ///
@ -3269,8 +3269,8 @@ class TreeTransform {
bool DeducibleTSTContext); bool DeducibleTSTContext);
}; };
template <typename Derived> template<typename Derived>
StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) { StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
if (!S) if (!S)
return S; return S;
@ -3294,7 +3294,7 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) {
if (E.isInvalid()) if (E.isInvalid())
return StmtError(); return StmtError();
return getSema().ActOnExprStmt(E, DiscardedValue); return getSema().ActOnExprStmt(E);
} }
} }
@ -4715,8 +4715,7 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
} }
if (SizeResult.isInvalid()) if (SizeResult.isInvalid())
return QualType(); return QualType();
SizeResult = SizeResult = SemaRef.ActOnFinishFullExpr(SizeResult.get());
SemaRef.ActOnFinishFullExpr(SizeResult.get(), /*DiscardedValue*/ false);
if (SizeResult.isInvalid()) if (SizeResult.isInvalid())
return QualType(); return QualType();
@ -6521,9 +6520,7 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
bool SubStmtChanged = false; bool SubStmtChanged = false;
SmallVector<Stmt*, 8> Statements; SmallVector<Stmt*, 8> Statements;
for (auto *B : S->body()) { for (auto *B : S->body()) {
StmtResult Result = StmtResult Result = getDerived().TransformStmt(B);
getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back());
if (Result.isInvalid()) { if (Result.isInvalid()) {
// Immediately fail if this was a DeclStmt, since it's very // Immediately fail if this was a DeclStmt, since it's very
// likely that this will cause problems for future statements. // likely that this will cause problems for future statements.

View File

@ -154,6 +154,32 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
return E; return E;
} }
/// Comparing internal representations of symbolic values (via
/// SVal::operator==()) is a valid way to check if the value was updated,
/// unless it's a LazyCompoundVal that may have a different internal
/// representation every time it is loaded from the state. In this function we
/// do an approximate comparison for lazy compound values, checking that they
/// are the immediate snapshots of the tracked region's bindings within the
/// node's respective states but not really checking that these snapshots
/// actually contain the same set of bindings.
bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal,
const ExplodedNode *RightNode, SVal RightVal) {
if (LeftVal == RightVal)
return true;
const auto LLCV = LeftVal.getAs<nonloc::LazyCompoundVal>();
if (!LLCV)
return false;
const auto RLCV = RightVal.getAs<nonloc::LazyCompoundVal>();
if (!RLCV)
return false;
return LLCV->getRegion() == RLCV->getRegion() &&
LLCV->getStore() == LeftNode->getState()->getStore() &&
RLCV->getStore() == RightNode->getState()->getStore();
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Definitions for bug reporter visitors. // Definitions for bug reporter visitors.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1188,7 +1214,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
if (Succ->getState()->getSVal(R) != V) if (Succ->getState()->getSVal(R) != V)
return nullptr; return nullptr;
if (Pred->getState()->getSVal(R) == V) { if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) {
Optional<PostStore> PS = Succ->getLocationAs<PostStore>(); Optional<PostStore> PS = Succ->getLocationAs<PostStore>();
if (!PS || PS->getLocationValue() != R) if (!PS || PS->getLocationValue() != R)
return nullptr; return nullptr;
@ -1209,6 +1235,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
// UndefinedVal.) // UndefinedVal.)
if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) { if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
if (const auto *VR = dyn_cast<VarRegion>(R)) { if (const auto *VR = dyn_cast<VarRegion>(R)) {
const auto *Param = cast<ParmVarDecl>(VR->getDecl()); const auto *Param = cast<ParmVarDecl>(VR->getDecl());
ProgramStateManager &StateMgr = BRC.getStateManager(); ProgramStateManager &StateMgr = BRC.getStateManager();

View File

@ -288,18 +288,24 @@ static void pdbMakeAbsolute(SmallVectorImpl<char> &FileName) {
// It's not absolute in any path syntax. Relative paths necessarily refer to // It's not absolute in any path syntax. Relative paths necessarily refer to
// the local file system, so we can make it native without ending up with a // the local file system, so we can make it native without ending up with a
// nonsensical path. // nonsensical path.
sys::path::native(FileName);
if (Config->PDBSourcePath.empty()) { if (Config->PDBSourcePath.empty()) {
sys::path::native(FileName);
sys::fs::make_absolute(FileName); sys::fs::make_absolute(FileName);
return; return;
} }
// Only apply native and dot removal to the relative file path. We want to
// leave the path the user specified untouched since we assume they specified
// it for a reason.
sys::path::remove_dots(FileName, /*remove_dot_dots=*/true);
// Try to guess whether /PDBSOURCEPATH is a unix path or a windows path.
// Since PDB's are more of a Windows thing, we make this conservative and only
// decide that it's a unix path if we're fairly certain. Specifically, if
// it starts with a forward slash.
SmallString<128> AbsoluteFileName = Config->PDBSourcePath; SmallString<128> AbsoluteFileName = Config->PDBSourcePath;
sys::path::append(AbsoluteFileName, FileName); sys::path::Style GuessedStyle = AbsoluteFileName.startswith("/")
? sys::path::Style::posix
: sys::path::Style::windows;
sys::path::append(AbsoluteFileName, GuessedStyle, FileName);
sys::path::native(AbsoluteFileName, GuessedStyle);
sys::path::remove_dots(AbsoluteFileName, true, GuessedStyle);
FileName = std::move(AbsoluteFileName); FileName = std::move(AbsoluteFileName);
} }

View File

@ -130,7 +130,7 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {
.Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS})
.Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS})
.Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) .Case("elf32lriscv", {ELF32LEKind, EM_RISCV})
.Case("elf32ppc", {ELF32BEKind, EM_PPC}) .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC})
.Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
.Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
.Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) .Case("elf64lriscv", {ELF64LEKind, EM_RISCV})

View File

@ -392,10 +392,11 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef S) {
.Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64})
.Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64})
.Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64})
.Case("elf32-powerpc", {ELF32BEKind, EM_PPC})
.Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64})
.Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64})
.Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64})
.Case("elf32-tradbigmips", {ELF32BEKind, EM_MIPS}) .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS})
.Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS}) .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS})
.Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS}) .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS})
.Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS}) .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS})

View File

@ -13,10 +13,12 @@ lld 8.0.0 Release Notes
Introduction Introduction
============ ============
This document contains the release notes for the lld linker, release 8.0.0. lld is a high-performance linker that supports ELF (Unix), COFF (Windows),
Here we describe the status of lld, including major improvements Mach-O (macOS), MinGW and WebAssembly. lld is command-line-compatible with
from the previous release. All lld releases may be downloaded GNU linkers and Microsoft link.exe and is significantly faster than the
from the `LLVM releases web site <https://llvm.org/releases/>`_. system default linkers.
nlld 8.0.0 has lots of feature improvements and bug fixes.
Non-comprehensive list of changes in this release Non-comprehensive list of changes in this release
================================================= =================================================
@ -33,27 +35,66 @@ ELF Improvements
non-superpages to a superpage if they are aligned to the superpage non-superpages to a superpage if they are aligned to the superpage
size. (`r342746 <https://reviews.llvm.org/rL342746>`_) size. (`r342746 <https://reviews.llvm.org/rL342746>`_)
* lld now attempts to place a ``.note`` segment in the first page of a
generated file, so that you can find some important information
(``.note.gnu.build-id`` in particular) in a core file even if a core
file is truncated by ulimit.
(`r349524 <https://reviews.llvm.org/rL349524>`_)
* lld now reports an error if ``_GLOBAL_OFFSET_TABLE_`` symbol is
defined by an input object file, as the symbol is supposed to be
synthesized by the linker.
(`r347854 <https://reviews.llvm.org/rL347854>`_)
* lld/Hexagon can now link Linux kernel and musl libc for Qualcomm * lld/Hexagon can now link Linux kernel and musl libc for Qualcomm
Hexagon ISA. Hexagon ISA.
* Initial MSP430 ISA support has landed. * Initial MSP430 ISA support has landed.
* The following flags have been added: ``-z interpose``, ``-z global``
* lld now uses the ``sigrie`` instruction as a trap instruction for * lld now uses the ``sigrie`` instruction as a trap instruction for
MIPS targets. MIPS targets.
* lld now creates a TLS segment for AArch64 with a slightly larger
alignment requirement, so that the loader makes a few bytes room
before each TLS segment at runtime. The aim of this change is to
make room to accomodate nonstandard Android TLS slots while keeping
the compatibility with the standard AArch64 ABI.
(`r350681 <https://reviews.llvm.org/rL350681>`_)
* The following flags have been added: ``--call-graph-profile``,
``--no-call-graph-profile``, ``--warn-ifunc-textrel``,
``-z interpose``, ``-z global``, ``-z nodefaultlib``
COFF Improvements COFF Improvements
----------------- -----------------
* PDB GUID is set to hash of PDB contents instead to a random byte * PDB GUID is set to hash of PDB contents instead to a random byte
sequence for build reproducibility. sequence for build reproducibility.
* ``/pdbsourcepath:`` is now also used to make ``"cwd"``, ``"exe"``, ``"pdb"``
in the env block of PDB outputs absolute if they are relative, and to make
paths to obj files referenced in PDB outputs absolute if they are relative.
Together with the previous item, this makes it possible to generate
executables and PDBs that are fully deterministic and independent of the
absolute path to the build directory, so that different machines building
the same code in different directories can produce exactly the same output.
* The following flags have been added: ``/force:multiple`` * The following flags have been added: ``/force:multiple``
* lld now can link against import libraries produced by GNU tools. * lld now can link against import libraries produced by GNU tools.
* lld can create thunks for ARM, to allow linking images over 16 MB. * lld can create thunks for ARM and ARM64, to allow linking larger images
(over 16 MB for ARM and over 128 MB for ARM64)
* Several speed and memory usage improvements.
* lld now creates debug info for typedefs.
* lld can now link obj files produced by ``cl.exe /Z7 /Yc``.
* lld now understands ``%_PDB%`` and ``%_EXT%`` in ``/pdbaltpath:``.
* Undefined symbols are now printed in demangled form in addition to raw form.
MinGW Improvements MinGW Improvements
------------------ ------------------
@ -76,11 +117,6 @@ MinGW Improvements
Previously, the ``--build-id`` option did not actually generate a build id Previously, the ``--build-id`` option did not actually generate a build id
unless ``--pdb`` was specified. unless ``--pdb`` was specified.
MachO Improvements
------------------
* Item 1.
WebAssembly Improvements WebAssembly Improvements
------------------------ ------------------------

View File

@ -173,4 +173,5 @@ document soon.
AtomLLD AtomLLD
WebAssembly WebAssembly
windows_support windows_support
missingkeyfunction
ReleaseNotes ReleaseNotes

View File

@ -1,5 +1,5 @@
Missing Key Method Missing Key Function
================== ====================
If your build failed with a linker error something like this:: If your build failed with a linker error something like this::

View File

@ -1,3 +1,3 @@
/* $FreeBSD$ */ /* $FreeBSD$ */
#define FREEBSD_CC_VERSION 1300002 #define FREEBSD_CC_VERSION 1300003

View File

@ -8,4 +8,4 @@
#define CLANG_VENDOR "FreeBSD " #define CLANG_VENDOR "FreeBSD "
#define SVN_REVISION "353167" #define SVN_REVISION "354130"

View File

@ -7,4 +7,4 @@
#define LLD_REPOSITORY_STRING "FreeBSD" #define LLD_REPOSITORY_STRING "FreeBSD"
// <Upstream revision at import>-<Local identifier in __FreeBSD_version style> // <Upstream revision at import>-<Local identifier in __FreeBSD_version style>
#define LLD_REVISION_STRING "353167-1300002" #define LLD_REVISION_STRING "354130-1300002"

View File

@ -1,2 +1,2 @@
/* $FreeBSD$ */ /* $FreeBSD$ */
#define LLVM_REVISION "svn-r353167" #define LLVM_REVISION "svn-r354130"