From 99ea5e489fa5765bf0eb50ca4261ab5cc20abeeb Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 22 May 2017 19:43:56 +0000 Subject: [PATCH 01/22] Vendor import of compiler-rt trunk r303571: https://llvm.org/svn/llvm-project/compiler-rt/trunk@303571 --- include/xray/xray_interface.h | 4 ++ lib/asan/asan_flags.cc | 4 -- lib/asan/tests/asan_str_test.cc | 21 --------- lib/lsan/lsan_common_mac.cc | 3 +- lib/msan/msan_interceptors.cc | 36 +++++++++++++--- lib/msan/tests/msan_test.cc | 6 +-- lib/sanitizer_common/sanitizer_common.cc | 4 +- lib/sanitizer_common/sanitizer_common.h | 8 ++-- .../sanitizer_common_interceptors.inc | 43 ------------------- lib/sanitizer_common/sanitizer_flag_parser.h | 24 +++++++++-- lib/sanitizer_common/sanitizer_flags.h | 5 +++ lib/sanitizer_common/sanitizer_flags.inc | 27 ++++++------ lib/sanitizer_common/sanitizer_linux.cc | 22 ++++++---- .../sanitizer_linux_libcdep.cc | 4 +- lib/sanitizer_common/sanitizer_mac.cc | 24 ++++++----- .../sanitizer_platform_interceptors.h | 14 ------ .../sanitizer_procmaps_common.cc | 2 +- .../sanitizer_procmaps_mac.cc | 2 +- lib/sanitizer_common/sanitizer_win.cc | 2 +- lib/sanitizer_common/tests/CMakeLists.txt | 9 ++++ .../tests/sanitizer_flags_test.cc | 30 +++++++++++++ .../tests/sanitizer_test_utils.h | 6 --- lib/scudo/scudo_flags.cpp | 4 +- lib/xray/xray_interface.cc | 14 +++++- test/asan/TestCases/Posix/asan-sigbus.cpp | 2 +- test/asan/TestCases/Posix/strndup_oob_test.cc | 27 ------------ test/msan/strndup.cc | 28 ------------ .../TestCases/Linux/custom-event-logging.cc | 2 +- test/xray/TestCases/Linux/func-id-utils.cc | 16 ++----- 29 files changed, 174 insertions(+), 219 deletions(-) delete mode 100644 test/asan/TestCases/Posix/strndup_oob_test.cc delete mode 100644 test/msan/strndup.cc diff --git a/include/xray/xray_interface.h b/include/xray/xray_interface.h index c3833f0be357..dc0c277aa841 100644 --- a/include/xray/xray_interface.h +++ b/include/xray/xray_interface.h @@ -69,6 +69,10 @@ extern int __xray_remove_handler_arg1(); /// Provide a function to invoke when XRay encounters a custom event. extern int __xray_set_customevent_handler(void (*entry)(void*, std::size_t)); +/// This removes whatever the currently provided custom event handler is. +/// Returns 1 on success, 0 on error. +extern int __xray_remove_customevent_handler(); + enum XRayPatchingStatus { NOT_INITIALIZED = 0, SUCCESS = 1, diff --git a/lib/asan/asan_flags.cc b/lib/asan/asan_flags.cc index 6be0d6e94b9a..c8ae3faed7c2 100644 --- a/lib/asan/asan_flags.cc +++ b/lib/asan/asan_flags.cc @@ -194,10 +194,6 @@ void InitializeFlags() { Report("WARNING: strchr* interceptors are enabled even though " "replace_str=0. Use intercept_strchr=0 to disable them."); } - if (!f->replace_str && common_flags()->intercept_strndup) { - Report("WARNING: strndup* interceptors are enabled even though " - "replace_str=0. Use intercept_strndup=0 to disable them."); - } } } // namespace __asan diff --git a/lib/asan/tests/asan_str_test.cc b/lib/asan/tests/asan_str_test.cc index 8f4911fd9ff8..c790088f8f9e 100644 --- a/lib/asan/tests/asan_str_test.cc +++ b/lib/asan/tests/asan_str_test.cc @@ -154,27 +154,6 @@ TEST(AddressSanitizer, MAYBE_StrDupOOBTest) { free(str); } -#if SANITIZER_TEST_HAS_STRNDUP -TEST(AddressSanitizer, MAYBE_StrNDupOOBTest) { - size_t size = Ident(42); - char *str = MallocAndMemsetString(size); - char *new_str; - // Normal strndup calls. - str[size - 1] = '\0'; - new_str = strndup(str, size - 13); - free(new_str); - new_str = strndup(str + size - 1, 13); - free(new_str); - // Argument points to not allocated memory. - EXPECT_DEATH(Ident(strndup(str - 1, 13)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strndup(str + size, 13)), RightOOBReadMessage(0)); - // Overwrite the terminating '\0' and hit unallocated memory. - str[size - 1] = 'z'; - EXPECT_DEATH(Ident(strndup(str, size + 13)), RightOOBReadMessage(0)); - free(str); -} -#endif // SANITIZER_TEST_HAS_STRNDUP - TEST(AddressSanitizer, StrCpyOOBTest) { size_t to_size = Ident(30); size_t from_size = Ident(6); // less than to_size diff --git a/lib/lsan/lsan_common_mac.cc b/lib/lsan/lsan_common_mac.cc index 5ee1e228691a..ae10955439c8 100644 --- a/lib/lsan/lsan_common_mac.cc +++ b/lib/lsan/lsan_common_mac.cc @@ -110,7 +110,8 @@ void ProcessGlobalRegions(Frontier *frontier) { for (const __sanitizer::LoadedModule::AddressRange &range : modules[i].ranges()) { - if (range.executable || !range.readable) continue; + // Sections storing global variables are writable and non-executable + if (range.executable || !range.writable) continue; ScanGlobalRange(range.beg, range.end, frontier); } diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index 0f50693441be..15543bd912d6 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -341,6 +341,33 @@ INTERCEPTOR(char *, __strdup, char *src) { #define MSAN_MAYBE_INTERCEPT___STRDUP #endif +INTERCEPTOR(char *, strndup, char *src, SIZE_T n) { + ENSURE_MSAN_INITED(); + GET_STORE_STACK_TRACE; + // On FreeBSD strndup() leverages strnlen(). + InterceptorScope interceptor_scope; + SIZE_T copy_size = REAL(strnlen)(src, n); + char *res = REAL(strndup)(src, n); + CopyShadowAndOrigin(res, src, copy_size, &stack); + __msan_unpoison(res + copy_size, 1); // \0 + return res; +} + +#if !SANITIZER_FREEBSD +INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) { + ENSURE_MSAN_INITED(); + GET_STORE_STACK_TRACE; + SIZE_T copy_size = REAL(strnlen)(src, n); + char *res = REAL(__strndup)(src, n); + CopyShadowAndOrigin(res, src, copy_size, &stack); + __msan_unpoison(res + copy_size, 1); // \0 + return res; +} +#define MSAN_MAYBE_INTERCEPT___STRNDUP INTERCEPT_FUNCTION(__strndup) +#else +#define MSAN_MAYBE_INTERCEPT___STRNDUP +#endif + INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) { ENSURE_MSAN_INITED(); char *res = REAL(gcvt)(number, ndigit, buf); @@ -1344,13 +1371,6 @@ int OnExit() { return __msan_memcpy(to, from, size); \ } -#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \ - do { \ - GET_STORE_STACK_TRACE; \ - CopyShadowAndOrigin(to, from, size, &stack); \ - __msan_unpoison(to + size, 1); \ - } while (false) - #include "sanitizer_common/sanitizer_platform_interceptors.h" #include "sanitizer_common/sanitizer_common_interceptors.inc" @@ -1518,6 +1538,8 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(stpcpy); // NOLINT INTERCEPT_FUNCTION(strdup); MSAN_MAYBE_INTERCEPT___STRDUP; + INTERCEPT_FUNCTION(strndup); + MSAN_MAYBE_INTERCEPT___STRNDUP; INTERCEPT_FUNCTION(strncpy); // NOLINT INTERCEPT_FUNCTION(gcvt); INTERCEPT_FUNCTION(strcat); // NOLINT diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc index 58f695e69e12..c7c91324aa0b 100644 --- a/lib/msan/tests/msan_test.cc +++ b/lib/msan/tests/msan_test.cc @@ -1581,8 +1581,7 @@ TEST(MemorySanitizer, strdup) { TEST(MemorySanitizer, strndup) { char buf[4] = "abc"; __msan_poison(buf + 2, sizeof(*buf)); - char *x; - EXPECT_UMR(x = strndup(buf, 3)); + char *x = strndup(buf, 3); EXPECT_NOT_POISONED(x[0]); EXPECT_NOT_POISONED(x[1]); EXPECT_POISONED(x[2]); @@ -1594,8 +1593,7 @@ TEST(MemorySanitizer, strndup_short) { char buf[4] = "abc"; __msan_poison(buf + 1, sizeof(*buf)); __msan_poison(buf + 2, sizeof(*buf)); - char *x; - EXPECT_UMR(x = strndup(buf, 2)); + char *x = strndup(buf, 2); EXPECT_NOT_POISONED(x[0]); EXPECT_POISONED(x[1]); EXPECT_NOT_POISONED(x[2]); diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 471c3ded2115..7e6f8fce76d2 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -285,9 +285,9 @@ void LoadedModule::clear() { } void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable, - bool readable) { + bool writable) { void *mem = InternalAlloc(sizeof(AddressRange)); - AddressRange *r = new(mem) AddressRange(beg, end, executable, readable); + AddressRange *r = new(mem) AddressRange(beg, end, executable, writable); ranges_.push_back(r); if (executable && end > max_executable_address_) max_executable_address_ = end; diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index bbe7aebf3279..33e652e6c3df 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -717,7 +717,7 @@ class LoadedModule { void set(const char *module_name, uptr base_address, ModuleArch arch, u8 uuid[kModuleUUIDSize], bool instrumented); void clear(); - void addAddressRange(uptr beg, uptr end, bool executable, bool readable); + void addAddressRange(uptr beg, uptr end, bool executable, bool writable); bool containsAddress(uptr address) const; const char *full_name() const { return full_name_; } @@ -732,14 +732,14 @@ class LoadedModule { uptr beg; uptr end; bool executable; - bool readable; + bool writable; - AddressRange(uptr beg, uptr end, bool executable, bool readable) + AddressRange(uptr beg, uptr end, bool executable, bool writable) : next(nullptr), beg(beg), end(end), executable(executable), - readable(readable) {} + writable(writable) {} }; const IntrusiveList &ranges() const { return ranges_; } diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index 3c69726d7c91..53204b48e300 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -34,8 +34,6 @@ // COMMON_INTERCEPTOR_MEMSET_IMPL // COMMON_INTERCEPTOR_MEMMOVE_IMPL // COMMON_INTERCEPTOR_MEMCPY_IMPL -// COMMON_INTERCEPTOR_COPY_STRING -// COMMON_INTERCEPTOR_STRNDUP_IMPL //===----------------------------------------------------------------------===// #include "interception/interception.h" @@ -219,25 +217,6 @@ bool PlatformHasDifferentMemcpyAndMemmove(); } #endif -#ifndef COMMON_INTERCEPTOR_COPY_STRING -#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {} -#endif - -#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL -#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \ - COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \ - uptr from_length = internal_strnlen(s, size); \ - uptr copy_length = Min(size, from_length); \ - char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \ - if (common_flags()->intercept_strndup) { \ - COMMON_INTERCEPTOR_READ_RANGE(ctx, s, copy_length + 1); \ - } \ - COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \ - internal_memcpy(new_mem, s, copy_length); \ - new_mem[copy_length] = '\0'; \ - return new_mem; -#endif - struct FileMetadata { // For open_memstream(). char **addr; @@ -321,26 +300,6 @@ INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) { #define INIT_STRNLEN #endif -#if SANITIZER_INTERCEPT_STRNDUP -INTERCEPTOR(char*, strndup, const char *s, uptr size) { - void *ctx; - COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size); -} -#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup) -#else -#define INIT_STRNDUP -#endif // SANITIZER_INTERCEPT_STRNDUP - -#if SANITIZER_INTERCEPT___STRNDUP -INTERCEPTOR(char*, __strndup, const char *s, uptr size) { - void *ctx; - COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size); -} -#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup) -#else -#define INIT___STRNDUP -#endif // SANITIZER_INTERCEPT___STRNDUP - #if SANITIZER_INTERCEPT_TEXTDOMAIN INTERCEPTOR(char*, textdomain, const char *domainname) { void *ctx; @@ -6204,8 +6163,6 @@ static void InitializeCommonInterceptors() { INIT_TEXTDOMAIN; INIT_STRLEN; INIT_STRNLEN; - INIT_STRNDUP; - INIT___STRNDUP; INIT_STRCMP; INIT_STRNCMP; INIT_STRCASECMP; diff --git a/lib/sanitizer_common/sanitizer_flag_parser.h b/lib/sanitizer_common/sanitizer_flag_parser.h index 2477aeddba5f..b6ae307fc93e 100644 --- a/lib/sanitizer_common/sanitizer_flag_parser.h +++ b/lib/sanitizer_common/sanitizer_flag_parser.h @@ -34,24 +34,40 @@ class FlagHandler : public FlagHandlerBase { bool Parse(const char *value) final; }; -template <> -inline bool FlagHandler::Parse(const char *value) { +inline bool ParseBool(const char *value, bool *b) { if (internal_strcmp(value, "0") == 0 || internal_strcmp(value, "no") == 0 || internal_strcmp(value, "false") == 0) { - *t_ = false; + *b = false; return true; } if (internal_strcmp(value, "1") == 0 || internal_strcmp(value, "yes") == 0 || internal_strcmp(value, "true") == 0) { - *t_ = true; + *b = true; return true; } + return false; +} + +template <> +inline bool FlagHandler::Parse(const char *value) { + if (ParseBool(value, t_)) return true; Printf("ERROR: Invalid value for bool option: '%s'\n", value); return false; } +template <> +inline bool FlagHandler::Parse(const char *value) { + bool b; + if (ParseBool(value, &b)) { + *t_ = b ? kHandleSignalYes : kHandleSignalNo; + return true; + } + Printf("ERROR: Invalid value for signal handler option: '%s'\n", value); + return false; +} + template <> inline bool FlagHandler::Parse(const char *value) { *t_ = internal_strdup(value); diff --git a/lib/sanitizer_common/sanitizer_flags.h b/lib/sanitizer_common/sanitizer_flags.h index 503126bbe256..f22593395ed5 100644 --- a/lib/sanitizer_common/sanitizer_flags.h +++ b/lib/sanitizer_common/sanitizer_flags.h @@ -18,6 +18,11 @@ namespace __sanitizer { +enum HandleSignalMode { + kHandleSignalNo, + kHandleSignalYes, +}; + struct CommonFlags { #define COMMON_FLAG(Type, Name, DefaultValue, Description) Type Name; #include "sanitizer_flags.inc" diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index 67a0a5810a28..c5aaf411fcc2 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -78,16 +78,20 @@ COMMON_FLAG(int, print_module_map, 0, "OS X only. 0 = don't print, 1 = print only once before process " "exits, 2 = print after each report.") COMMON_FLAG(bool, check_printf, true, "Check printf arguments.") -COMMON_FLAG(bool, handle_segv, true, - "If set, registers the tool's custom SIGSEGV handler.") -COMMON_FLAG(bool, handle_sigbus, true, - "If set, registers the tool's custom SIGBUS handler.") -COMMON_FLAG(bool, handle_abort, false, - "If set, registers the tool's custom SIGABRT handler.") -COMMON_FLAG(bool, handle_sigill, false, - "If set, registers the tool's custom SIGILL handler.") -COMMON_FLAG(bool, handle_sigfpe, true, - "If set, registers the tool's custom SIGFPE handler.") +#define COMMON_FLAG_HANDLE_SIGNAL_HELP(signal) \ + "Controls custom tool's " #signal " handler (0 - do not registers the " \ + "handler, 1 - register the handler). " +COMMON_FLAG(HandleSignalMode, handle_segv, kHandleSignalYes, + COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGSEGV)) +COMMON_FLAG(HandleSignalMode, handle_sigbus, kHandleSignalYes, + COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGBUS)) +COMMON_FLAG(HandleSignalMode, handle_abort, kHandleSignalNo, + COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGABRT)) +COMMON_FLAG(HandleSignalMode, handle_sigill, kHandleSignalNo, + COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGILL)) +COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes, + COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGFPE)) +#undef COMMON_FLAG_HANDLE_SIGNAL_HELP COMMON_FLAG(bool, allow_user_segv_handler, false, "If set, allows user to register a SEGV handler even if the tool " "registers one.") @@ -195,9 +199,6 @@ COMMON_FLAG(bool, intercept_strpbrk, true, COMMON_FLAG(bool, intercept_strlen, true, "If set, uses custom wrappers for strlen and strnlen functions " "to find more errors.") -COMMON_FLAG(bool, intercept_strndup, true, - "If set, uses custom wrappers for strndup functions " - "to find more errors.") COMMON_FLAG(bool, intercept_strchr, true, "If set, uses custom wrappers for strchr, strchrnul, and strrchr " "functions to find more errors.") diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index fce78fe590d5..87f32c44d71a 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -1395,15 +1395,19 @@ AndroidApiLevel AndroidGetApiLevel() { #endif bool IsHandledDeadlySignal(int signum) { - if (common_flags()->handle_abort && signum == SIGABRT) - return true; - if (common_flags()->handle_sigill && signum == SIGILL) - return true; - if (common_flags()->handle_sigfpe && signum == SIGFPE) - return true; - if (common_flags()->handle_segv && signum == SIGSEGV) - return true; - return common_flags()->handle_sigbus && signum == SIGBUS; + switch (signum) { + case SIGABRT: + return common_flags()->handle_abort; + case SIGILL: + return common_flags()->handle_sigill; + case SIGFPE: + return common_flags()->handle_sigfpe; + case SIGSEGV: + return common_flags()->handle_segv; + case SIGBUS: + return common_flags()->handle_sigbus; + } + return false; } #if !SANITIZER_GO diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 25f1e12c0374..a15b5858af40 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -447,9 +447,9 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; uptr cur_end = cur_beg + phdr->p_memsz; bool executable = phdr->p_flags & PF_X; - bool readable = phdr->p_flags & PF_R; + bool writable = phdr->p_flags & PF_W; cur_module.addAddressRange(cur_beg, cur_end, executable, - readable); + writable); } } data->modules->push_back(cur_module); diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 2f990b805ff9..f1a6bf91635c 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -394,18 +394,22 @@ void ListOfModules::init() { } bool IsHandledDeadlySignal(int signum) { + // Handling fatal signals on watchOS and tvOS devices is disallowed. if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM)) - // Handling fatal signals on watchOS and tvOS devices is disallowed. return false; - if (common_flags()->handle_abort && signum == SIGABRT) - return true; - if (common_flags()->handle_sigill && signum == SIGILL) - return true; - if (common_flags()->handle_sigfpe && signum == SIGFPE) - return true; - if (common_flags()->handle_segv && signum == SIGSEGV) - return true; - return common_flags()->handle_sigbus && signum == SIGBUS; + switch (signum) { + case SIGABRT: + return common_flags()->handle_abort; + case SIGILL: + return common_flags()->handle_sigill; + case SIGFPE: + return common_flags()->handle_sigfpe; + case SIGSEGV: + return common_flags()->handle_segv; + case SIGBUS: + return common_flags()->handle_sigbus; + } + return false; } MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED; diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h index a95497467d61..e5644ef25e83 100644 --- a/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -25,12 +25,6 @@ # define SI_NOT_WINDOWS 0 #endif -#if SANITIZER_POSIX -# define SI_POSIX 1 -#else -# define SI_POSIX 0 -#endif - #if SANITIZER_LINUX && !SANITIZER_ANDROID # define SI_LINUX_NOT_ANDROID 1 #else @@ -75,12 +69,6 @@ # define SI_UNIX_NOT_MAC 0 #endif -#if SANITIZER_LINUX && !SANITIZER_FREEBSD -# define SI_LINUX_NOT_FREEBSD 1 -# else -# define SI_LINUX_NOT_FREEBSD 0 -#endif - #define SANITIZER_INTERCEPT_STRLEN 1 #define SANITIZER_INTERCEPT_STRNLEN SI_NOT_MAC #define SANITIZER_INTERCEPT_STRCMP 1 @@ -98,8 +86,6 @@ #define SANITIZER_INTERCEPT_MEMMOVE 1 #define SANITIZER_INTERCEPT_MEMCPY 1 #define SANITIZER_INTERCEPT_MEMCMP 1 -#define SANITIZER_INTERCEPT_STRNDUP SI_POSIX -#define SANITIZER_INTERCEPT___STRNDUP SI_LINUX_NOT_FREEBSD #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 # define SI_MAC_DEPLOYMENT_BELOW_10_7 1 diff --git a/lib/sanitizer_common/sanitizer_procmaps_common.cc b/lib/sanitizer_common/sanitizer_procmaps_common.cc index 67a659010aaf..c583f42f25d8 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_common.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_common.cc @@ -142,7 +142,7 @@ void MemoryMappingLayout::DumpListOfModules( LoadedModule cur_module; cur_module.set(cur_name, base_address); cur_module.addAddressRange(cur_beg, cur_end, prot & kProtectionExecute, - prot & kProtectionRead); + prot & kProtectionWrite); modules->push_back(cur_module); } } diff --git a/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/lib/sanitizer_common/sanitizer_procmaps_mac.cc index 0b4171a90f60..131017458d4c 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_mac.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_mac.cc @@ -336,7 +336,7 @@ void MemoryMappingLayout::DumpListOfModules( current_instrumented_); } cur_module->addAddressRange(cur_beg, cur_end, prot & kProtectionExecute, - prot & kProtectionRead); + prot & kProtectionWrite); } } diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index 1a454ba42c8e..d0a5c078cd68 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -554,7 +554,7 @@ void ListOfModules::init() { cur_module.set(module_name, adjusted_base); // We add the whole module as one single address range. cur_module.addAddressRange(base_address, end_address, /*executable*/ true, - /*readable*/ true); + /*writable*/ true); modules_.push_back(cur_module); } UnmapOrDie(hmodules, modules_buffer_size); diff --git a/lib/sanitizer_common/tests/CMakeLists.txt b/lib/sanitizer_common/tests/CMakeLists.txt index b310f93743ac..2acedd0ef56a 100644 --- a/lib/sanitizer_common/tests/CMakeLists.txt +++ b/lib/sanitizer_common/tests/CMakeLists.txt @@ -146,6 +146,15 @@ set_target_properties(SanitizerUnitTests PROPERTIES FOLDER "Compiler-RT Tests") # Adds sanitizer tests for architecture. macro(add_sanitizer_tests_for_arch arch) get_target_flags_for_arch(${arch} TARGET_FLAGS) + + # If the sanitizer library was built with _FILE_OFFSET_BITS=64 we need + # to ensure that the library and tests agree on the layout of certain + # structures such as 'struct stat'. + if( CMAKE_SIZEOF_VOID_P EQUAL 4 ) + list(APPEND TARGET_FLAGS "-D_LARGEFILE_SOURCE") + list(APPEND TARGET_FLAGS "-D_FILE_OFFSET_BITS=64") + endif() + set(SANITIZER_TEST_SOURCES ${SANITIZER_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE}) set(SANITIZER_TEST_COMPILE_DEPS ${SANITIZER_TEST_HEADERS}) diff --git a/lib/sanitizer_common/tests/sanitizer_flags_test.cc b/lib/sanitizer_common/tests/sanitizer_flags_test.cc index 24a3f3d3c7eb..34d7067f85ff 100644 --- a/lib/sanitizer_common/tests/sanitizer_flags_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_flags_test.cc @@ -59,6 +59,36 @@ TEST(SanitizerCommon, BooleanFlags) { TestFlag(true, "flag_name=0", false); TestFlag(true, "flag_name=no", false); TestFlag(true, "flag_name=false", false); + + EXPECT_DEATH(TestFlag(false, "flag_name", true), "expected '='"); + EXPECT_DEATH(TestFlag(false, "flag_name=", true), + "Invalid value for bool option: ''"); + EXPECT_DEATH(TestFlag(false, "flag_name=2", true), + "Invalid value for bool option: '2'"); + EXPECT_DEATH(TestFlag(false, "flag_name=-1", true), + "Invalid value for bool option: '-1'"); + EXPECT_DEATH(TestFlag(false, "flag_name=on", true), + "Invalid value for bool option: 'on'"); +} + +TEST(SanitizerCommon, HandleSignalMode) { + TestFlag(kHandleSignalNo, "flag_name=1", kHandleSignalYes); + TestFlag(kHandleSignalNo, "flag_name=yes", kHandleSignalYes); + TestFlag(kHandleSignalNo, "flag_name=true", kHandleSignalYes); + TestFlag(kHandleSignalYes, "flag_name=0", kHandleSignalNo); + TestFlag(kHandleSignalYes, "flag_name=no", kHandleSignalNo); + TestFlag(kHandleSignalYes, "flag_name=false", kHandleSignalNo); + + EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name", kHandleSignalNo), + "expected '='"); + EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=", kHandleSignalNo), + "Invalid value for signal handler option: ''"); + EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=2", kHandleSignalNo), + "Invalid value for signal handler option: '2'"); + EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=-1", kHandleSignalNo), + "Invalid value for signal handler option: '-1'"); + EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=on", kHandleSignalNo), + "Invalid value for signal handler option: 'on'"); } TEST(SanitizerCommon, IntFlags) { diff --git a/lib/sanitizer_common/tests/sanitizer_test_utils.h b/lib/sanitizer_common/tests/sanitizer_test_utils.h index b7728d9ea25e..9c162a66f547 100644 --- a/lib/sanitizer_common/tests/sanitizer_test_utils.h +++ b/lib/sanitizer_common/tests/sanitizer_test_utils.h @@ -124,10 +124,4 @@ static inline uint32_t my_rand() { # define SANITIZER_TEST_HAS_PRINTF_L 0 #endif -#if !defined(_MSC_VER) -# define SANITIZER_TEST_HAS_STRNDUP 1 -#else -# define SANITIZER_TEST_HAS_STRNDUP 0 -#endif - #endif // SANITIZER_TEST_UTILS_H diff --git a/lib/scudo/scudo_flags.cpp b/lib/scudo/scudo_flags.cpp index 64da1d9d8ec1..90f0cbf4bb86 100644 --- a/lib/scudo/scudo_flags.cpp +++ b/lib/scudo/scudo_flags.cpp @@ -68,7 +68,7 @@ void initFlags() { // Sanity checks and default settings for the Quarantine parameters. if (f->QuarantineSizeMb < 0) { - const int DefaultQuarantineSizeMb = FIRST_32_SECOND_64(16, 64); + const int DefaultQuarantineSizeMb = FIRST_32_SECOND_64(4, 16); f->QuarantineSizeMb = DefaultQuarantineSizeMb; } // We enforce an upper limit for the quarantine size of 4Gb. @@ -77,7 +77,7 @@ void initFlags() { } if (f->ThreadLocalQuarantineSizeKb < 0) { const int DefaultThreadLocalQuarantineSizeKb = - FIRST_32_SECOND_64(256, 1024); + FIRST_32_SECOND_64(64, 256); f->ThreadLocalQuarantineSizeKb = DefaultThreadLocalQuarantineSizeKb; } // And an upper limit of 128Mb for the thread quarantine cache. diff --git a/lib/xray/xray_interface.cc b/lib/xray/xray_interface.cc index c437a72e3f05..e912b6e478a3 100644 --- a/lib/xray/xray_interface.cc +++ b/lib/xray/xray_interface.cc @@ -119,10 +119,15 @@ int __xray_set_customevent_handler(void (*entry)(void *, size_t)) return 0; } + int __xray_remove_handler() XRAY_NEVER_INSTRUMENT { return __xray_set_handler(nullptr); } +int __xray_remove_customevent_handler() XRAY_NEVER_INSTRUMENT { + return __xray_set_customevent_handler(nullptr); +} + __sanitizer::atomic_uint8_t XRayPatching{0}; using namespace __xray; @@ -326,7 +331,14 @@ uintptr_t __xray_function_address(int32_t FuncId) XRAY_NEVER_INSTRUMENT { __sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex); if (FuncId <= 0 || static_cast(FuncId) > XRayInstrMap.Functions) return 0; - return XRayInstrMap.SledsIndex[FuncId - 1].Begin->Address; + return XRayInstrMap.SledsIndex[FuncId - 1].Begin->Address +// On PPC, function entries are always aligned to 16 bytes. The beginning of a +// sled might be a local entry, which is always +8 based on the global entry. +// Always return the global entry. +#ifdef __PPC__ + & ~0xf +#endif + ; } size_t __xray_max_function_id() XRAY_NEVER_INSTRUMENT { diff --git a/test/asan/TestCases/Posix/asan-sigbus.cpp b/test/asan/TestCases/Posix/asan-sigbus.cpp index a7d032acec03..d02ebbd9d8b0 100644 --- a/test/asan/TestCases/Posix/asan-sigbus.cpp +++ b/test/asan/TestCases/Posix/asan-sigbus.cpp @@ -2,7 +2,7 @@ // Defaults to true // RUN: %clangxx_asan -std=c++11 %s -o %t // RUN: not %run %t %T/file 2>&1 | FileCheck %s -check-prefix=CHECK-BUS -// RUN: %env_asan_opts=handle_sigbus=false not --crash %run %t %T/file 2>&1 | FileCheck %s +// RUN: %env_asan_opts=handle_sigbus=0 not --crash %run %t %T/file 2>&1 | FileCheck %s // UNSUPPORTED: ios diff --git a/test/asan/TestCases/Posix/strndup_oob_test.cc b/test/asan/TestCases/Posix/strndup_oob_test.cc deleted file mode 100644 index 7ea0b7a33400..000000000000 --- a/test/asan/TestCases/Posix/strndup_oob_test.cc +++ /dev/null @@ -1,27 +0,0 @@ -// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s - -// When built as C on Linux, strndup is transformed to __strndup. -// RUN: %clangxx_asan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck %s - -// Unwind problem on arm: "main" is missing from the allocation stack trace. -// UNSUPPORTED: win32,s390,armv7l-unknown-linux-gnueabihf - -#include - -char kString[] = "foo"; - -int main(int argc, char **argv) { - char *copy = strndup(kString, 2); - int x = copy[2 + argc]; // BOOM - // CHECK: AddressSanitizer: heap-buffer-overflow - // CHECK: #0 {{.*}}main {{.*}}strndup_oob_test.cc:[[@LINE-2]] - // CHECK-LABEL: allocated by thread T{{.*}} here: - // CHECK: #{{[01]}} {{.*}}strndup - // CHECK: #{{.*}}main {{.*}}strndup_oob_test.cc:[[@LINE-6]] - // CHECK-LABEL: SUMMARY - // CHECK: strndup_oob_test.cc:[[@LINE-7]] - return x; -} diff --git a/test/msan/strndup.cc b/test/msan/strndup.cc deleted file mode 100644 index d4b9af1a9a6e..000000000000 --- a/test/msan/strndup.cc +++ /dev/null @@ -1,28 +0,0 @@ -// RUN: %clangxx_msan %s -o %t && not %run %t 2>&1 | FileCheck --check-prefix=ON %s -// RUN: %clangxx_msan %s -o %t && MSAN_OPTIONS=intercept_strndup=0 %run %t 2>&1 | FileCheck --check-prefix=OFF --allow-empty %s - -// When built as C on Linux, strndup is transformed to __strndup. -// RUN: %clangxx_msan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck --check-prefix=ON %s - -// UNSUPPORTED: win32 - -#include -#include -#include -#include - -int main(int argc, char **argv) { - char kString[4] = "abc"; - __msan_poison(kString + 2, 1); - char *copy = strndup(kString, 4); // BOOM - assert(__msan_test_shadow(copy, 4) == 2); // Poisoning is preserved. - free(copy); - return 0; - // ON: Uninitialized bytes in __interceptor_{{(__)?}}strndup at offset 2 inside [{{.*}}, 4) - // ON: MemorySanitizer: use-of-uninitialized-value - // ON: #0 {{.*}}main {{.*}}strndup.cc:[[@LINE-6]] - // ON-LABEL: SUMMARY - // ON: {{.*}}strndup.cc:[[@LINE-8]] - // OFF-NOT: MemorySanitizer -} - diff --git a/test/xray/TestCases/Linux/custom-event-logging.cc b/test/xray/TestCases/Linux/custom-event-logging.cc index b1a766d46045..9bb5d44e1111 100644 --- a/test/xray/TestCases/Linux/custom-event-logging.cc +++ b/test/xray/TestCases/Linux/custom-event-logging.cc @@ -33,7 +33,7 @@ int main() { // CHECK-NEXT: after calling the custom logging... printf("removing custom event handler...\n"); // CHECK-NEXT: removing custom event handler... - __xray_set_customevent_handler(nullptr); + __xray_remove_customevent_handler(); foo(); // CHECK-NEXT: before calling the custom logging... // CHECK-NEXT: after calling the custom logging... diff --git a/test/xray/TestCases/Linux/func-id-utils.cc b/test/xray/TestCases/Linux/func-id-utils.cc index c9a2952c695d..17185c34c01e 100644 --- a/test/xray/TestCases/Linux/func-id-utils.cc +++ b/test/xray/TestCases/Linux/func-id-utils.cc @@ -31,18 +31,10 @@ "each function id must be assigned to a unique function"); std::set not_instrumented; - const auto comp = [](void *lhs, void *rhs) { -#ifdef __PPC__ - return reinterpret_cast(lhs) + 8 < - reinterpret_cast(rhs); -#else - return lhs < rhs; -#endif - }; - std::set_difference(must_be_instrumented.begin(), must_be_instrumented.end(), - all_instrumented.begin(), all_instrumented.end(), - std::inserter(not_instrumented, not_instrumented.begin()), - comp); + std::set_difference( + must_be_instrumented.begin(), must_be_instrumented.end(), + all_instrumented.begin(), all_instrumented.end(), + std::inserter(not_instrumented, not_instrumented.begin())); assert( not_instrumented.empty() && "we should see all explicitly instrumented functions with function ids"); From fb19dde5bfd42a03786ee50e6b300e47c45ace47 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 22 May 2017 19:44:21 +0000 Subject: [PATCH 02/22] Vendor import of lldb trunk r303571: https://llvm.org/svn/llvm-project/lldb/trunk@303571 --- include/lldb/Utility/Status.h | 20 ++++++------ .../Python/lldbsuite/test/configuration.py | 2 +- source/Core/IOHandler.cpp | 2 +- source/Utility/Status.cpp | 31 +++++++++++++++++++ unittests/Utility/StatusTest.cpp | 31 +++++++++++++++++++ 5 files changed, 74 insertions(+), 12 deletions(-) diff --git a/include/lldb/Utility/Status.h b/include/lldb/Utility/Status.h index 4ac191b1f613..d8fd41707f8c 100644 --- a/include/lldb/Utility/Status.h +++ b/include/lldb/Utility/Status.h @@ -1,5 +1,4 @@ -//===-- Status.h -------------------------------------------------*- C++ -//-*-===// +//===-- Status.h ------------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -8,22 +7,20 @@ // //===----------------------------------------------------------------------===// -#ifndef __DCError_h__ -#define __DCError_h__ -#if defined(__cplusplus) +#ifndef LLDB_UTILITY_STATUS_H +#define LLDB_UTILITY_STATUS_H #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" // for ErrorType, ErrorType... #include "llvm/ADT/StringRef.h" // for StringRef +#include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" - #include +#include // for uint32_t #include #include // for error_code #include // for forward -#include // for uint32_t - namespace llvm { class raw_ostream; } @@ -106,6 +103,10 @@ class Status { ~Status(); + // llvm::Error support + explicit Status(llvm::Error error); + llvm::Error ToError() const; + //------------------------------------------------------------------ /// Get the error string associated with the current error. // @@ -274,5 +275,4 @@ template <> struct format_provider { }; } -#endif // #if defined(__cplusplus) -#endif // #ifndef __DCError_h__ +#endif // #ifndef LLDB_UTILITY_STATUS_H diff --git a/packages/Python/lldbsuite/test/configuration.py b/packages/Python/lldbsuite/test/configuration.py index 120f8247c695..a49948c02050 100644 --- a/packages/Python/lldbsuite/test/configuration.py +++ b/packages/Python/lldbsuite/test/configuration.py @@ -44,7 +44,7 @@ def setupCrashInfoHook(): if not os.path.isfile(dylib_dst) or os.path.getmtime( dylib_dst) < os.path.getmtime(dylib_src): # we need to compile - cmd = "SDKROOT= xcrun clang %s -o %s -framework Python -Xlinker -dylib -iframework /System/Library/Frameworks/ -Xlinker -F /System/Library/Frameworks/" % ( + cmd = "SDKROOT= xcrun clang %s -o %s -framework Python -Xlinker -dylib" % ( dylib_src, dylib_dst) if subprocess.call( cmd, shell=True) != 0 or not os.path.isfile(dylib_dst): diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp index e5fe490991f9..3cb1ffab3a0e 100644 --- a/source/Core/IOHandler.cpp +++ b/source/Core/IOHandler.cpp @@ -4640,7 +4640,7 @@ void IOHandlerCursesGUI::Activate() { WindowSP threads_window_sp( main_window_sp->CreateSubWindow("Threads", threads_bounds, false)); WindowSP status_window_sp( - main_window_sp->CreateSubWindow("Error", status_bounds, false)); + main_window_sp->CreateSubWindow("Status", status_bounds, false)); status_window_sp->SetCanBeActive( false); // Don't let the status bar become the active window main_window_sp->SetDelegate( diff --git a/source/Utility/Status.cpp b/source/Utility/Status.cpp index 5996be1e4e05..ba87d3e5144f 100644 --- a/source/Utility/Status.cpp +++ b/source/Utility/Status.cpp @@ -56,6 +56,37 @@ Status::Status(const char *format, ...) va_end(args); } +Status::Status(llvm::Error error) + : m_code(0), m_type(ErrorType::eErrorTypeGeneric) { + if (!error) + return; + + // if the error happens to be a errno error, preserve the error code + error = llvm::handleErrors( + std::move(error), [&](std::unique_ptr e) -> llvm::Error { + std::error_code ec = e->convertToErrorCode(); + if (ec.category() == std::generic_category()) { + m_code = ec.value(); + m_type = ErrorType::eErrorTypePOSIX; + return llvm::Error::success(); + } + return llvm::Error(std::move(e)); + }); + + // Otherwise, just preserve the message + if (error) + SetErrorString(llvm::toString(std::move(error))); +} + +llvm::Error Status::ToError() const { + if (Success()) + return llvm::Error::success(); + if (m_type == ErrorType::eErrorTypePOSIX) + return llvm::errorCodeToError(std::error_code(m_code, std::generic_category())); + return llvm::make_error(AsCString(), + llvm::inconvertibleErrorCode()); +} + //---------------------------------------------------------------------- // Assignment operator //---------------------------------------------------------------------- diff --git a/unittests/Utility/StatusTest.cpp b/unittests/Utility/StatusTest.cpp index 9655610e4aa3..03e2368c7b1b 100644 --- a/unittests/Utility/StatusTest.cpp +++ b/unittests/Utility/StatusTest.cpp @@ -11,9 +11,40 @@ #include "gtest/gtest.h" using namespace lldb_private; +using namespace lldb; TEST(StatusTest, Formatv) { EXPECT_EQ("", llvm::formatv("{0}", Status()).str()); EXPECT_EQ("Hello Status", llvm::formatv("{0}", Status("Hello Status")).str()); EXPECT_EQ("Hello", llvm::formatv("{0:5}", Status("Hello Error")).str()); } + +TEST(StatusTest, ErrorConstructor) { + EXPECT_TRUE(Status(llvm::Error::success()).Success()); + + Status eagain( + llvm::errorCodeToError(std::error_code(EAGAIN, std::generic_category()))); + EXPECT_TRUE(eagain.Fail()); + EXPECT_EQ(eErrorTypePOSIX, eagain.GetType()); + EXPECT_EQ(Status::ValueType(EAGAIN), eagain.GetError()); + + Status foo(llvm::make_error( + "foo", llvm::inconvertibleErrorCode())); + EXPECT_TRUE(foo.Fail()); + EXPECT_EQ(eErrorTypeGeneric, foo.GetType()); + EXPECT_STREQ("foo", foo.AsCString()); +} + +TEST(StatusTest, ErrorConversion) { + EXPECT_FALSE(bool(Status().ToError())); + + llvm::Error eagain = Status(EAGAIN, ErrorType::eErrorTypePOSIX).ToError(); + EXPECT_TRUE(bool(eagain)); + std::error_code ec = llvm::errorToErrorCode(std::move(eagain)); + EXPECT_EQ(EAGAIN, ec.value()); + EXPECT_EQ(std::generic_category(), ec.category()); + + llvm::Error foo = Status("foo").ToError(); + EXPECT_TRUE(bool(foo)); + EXPECT_EQ("foo", llvm::toString(std::move(foo))); +} From 224c1c721b03784d0da2af00884ea8d4eb7a1650 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 29 May 2017 16:25:57 +0000 Subject: [PATCH 03/22] Vendor import of compiler-rt trunk r304149: https://llvm.org/svn/llvm-project/compiler-rt/trunk@304149 --- cmake/base-config-ix.cmake | 4 +- cmake/builtin-config-ix.cmake | 2 +- lib/asan/asan_interceptors.cc | 12 +- lib/asan/asan_win.cc | 2 +- lib/asan/scripts/asan_device_setup | 5 - lib/asan/tests/asan_interface_test.cc | 4 - lib/asan/tests/asan_noinst_test.cc | 9 -- lib/asan/tests/asan_test.cc | 21 ++-- lib/builtins/CMakeLists.txt | 6 +- lib/builtins/README.txt | 4 +- lib/builtins/arm/aeabi_cdcmp.S | 11 ++ lib/builtins/arm/aeabi_cfcmp.S | 11 ++ lib/builtins/arm/eqdf2vfp.S | 1 + lib/builtins/arm/eqsf2vfp.S | 1 + lib/builtins/arm/gedf2vfp.S | 1 + lib/builtins/arm/gesf2vfp.S | 1 + lib/builtins/arm/gtdf2vfp.S | 1 + lib/builtins/arm/gtsf2vfp.S | 1 + lib/builtins/arm/ledf2vfp.S | 1 + lib/builtins/arm/lesf2vfp.S | 1 + lib/builtins/arm/ltdf2vfp.S | 1 + lib/builtins/arm/ltsf2vfp.S | 1 + lib/builtins/arm/nedf2vfp.S | 1 + lib/builtins/arm/nesf2vfp.S | 1 + lib/builtins/arm/unorddf2vfp.S | 1 + lib/builtins/arm/unordsf2vfp.S | 1 + lib/builtins/assembly.h | 2 + lib/builtins/bswapdi2.c | 27 +++++ lib/builtins/bswapsi2.c | 23 ++++ lib/lsan/lsan_common.cc | 28 ++--- lib/lsan/lsan_common_mac.cc | 7 +- lib/lsan/lsan_flags.inc | 2 +- .../sanitizer_allocator_primary32.h | 2 - lib/sanitizer_common/sanitizer_common.h | 2 +- lib/sanitizer_common/sanitizer_flag_parser.h | 5 + lib/sanitizer_common/sanitizer_flags.h | 1 + lib/sanitizer_common/sanitizer_flags.inc | 10 +- lib/sanitizer_common/sanitizer_linux.cc | 6 +- lib/sanitizer_common/sanitizer_linux_s390.cc | 7 ++ lib/sanitizer_common/sanitizer_mac.cc | 31 +++++- .../sanitizer_posix_libcdep.cc | 25 ++++- lib/sanitizer_common/sanitizer_win.cc | 4 +- .../tests/sanitizer_flags_test.cc | 6 +- lib/scudo/scudo_tls_linux.cpp | 16 +-- lib/tsan/rtl/tsan_platform.h | 1 + lib/tsan/rtl/tsan_platform_linux.cc | 14 +++ lib/tsan/rtl/tsan_platform_mac.cc | 41 ++++++- lib/tsan/rtl/tsan_rtl_thread.cc | 14 +-- .../TestCases/Linux/preinstalled_signal.cc | 105 ++++++++++++++++++ .../Linux/sanbox_read_proc_self_maps_test.cc | 8 +- test/asan/TestCases/Posix/allow_user_segv.cc | 53 ++++++--- .../Posix/current_allocated_bytes.cc | 3 - test/asan/TestCases/Posix/wait.cc | 1 + test/asan/TestCases/Posix/wait3.cc | 2 +- test/asan/TestCases/Posix/wait4.cc | 1 + test/asan/TestCases/Posix/waitid.cc | 2 + test/builtins/Unit/bswapdi2_test.c | 37 +++--- test/builtins/Unit/bswapsi2_test.c | 37 +++--- test/lsan/TestCases/many_tls_keys.cc | 97 ++++++++++++++++ .../TestCases/Linux/sem_init_glibc.cc | 6 +- .../TestCases/Linux/signal_segv_handler.cc | 2 +- .../TestCases/Integer/negate-overflow.cpp | 6 +- 62 files changed, 552 insertions(+), 187 deletions(-) create mode 100644 lib/builtins/bswapdi2.c create mode 100644 lib/builtins/bswapsi2.c create mode 100644 test/asan/TestCases/Linux/preinstalled_signal.cc create mode 100644 test/lsan/TestCases/many_tls_keys.cc diff --git a/cmake/base-config-ix.cmake b/cmake/base-config-ix.cmake index 6f9f15139ad7..b38c6ca96fac 100644 --- a/cmake/base-config-ix.cmake +++ b/cmake/base-config-ix.cmake @@ -63,7 +63,9 @@ else() set(COMPILER_RT_TEST_COMPILER_ID GNU) endif() -string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR) +if(NOT DEFINED COMPILER_RT_OS_DIR) + string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR) +endif() set(COMPILER_RT_LIBRARY_OUTPUT_DIR ${COMPILER_RT_OUTPUT_DIR}/lib/${COMPILER_RT_OS_DIR}) set(COMPILER_RT_LIBRARY_INSTALL_DIR diff --git a/cmake/builtin-config-ix.cmake b/cmake/builtin-config-ix.cmake index dc2ec16943ac..20bc68476c7d 100644 --- a/cmake/builtin-config-ix.cmake +++ b/cmake/builtin-config-ix.cmake @@ -24,7 +24,7 @@ int foo(int x, int y) { set(ARM64 aarch64) -set(ARM32 arm armhf armv6m) +set(ARM32 arm armhf armv6m armv7m armv7em armv7 armv7s armv7k) set(X86 i386 i686) set(X86_64 x86_64) set(MIPS32 mips mipsel) diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index c6969c979a59..cb2214f966ea 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -357,28 +357,22 @@ DEFINE_REAL_PTHREAD_FUNCTIONS #if SANITIZER_ANDROID INTERCEPTOR(void*, bsd_signal, int signum, void *handler) { - if (!IsHandledDeadlySignal(signum) || - common_flags()->allow_user_segv_handler) { + if (GetHandleSignalMode(signum) != kHandleSignalExclusive) return REAL(bsd_signal)(signum, handler); - } return 0; } #endif INTERCEPTOR(void*, signal, int signum, void *handler) { - if (!IsHandledDeadlySignal(signum) || - common_flags()->allow_user_segv_handler) { + if (GetHandleSignalMode(signum) != kHandleSignalExclusive) return REAL(signal)(signum, handler); - } return nullptr; } INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) { - if (!IsHandledDeadlySignal(signum) || - common_flags()->allow_user_segv_handler) { + if (GetHandleSignalMode(signum) != kHandleSignalExclusive) return REAL(sigaction)(signum, act, oldact); - } return 0; } diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index 4ab535c42e5a..26db32465da8 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -80,7 +80,7 @@ static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) { INTERCEPTOR_WINAPI(LPTOP_LEVEL_EXCEPTION_FILTER, SetUnhandledExceptionFilter, LPTOP_LEVEL_EXCEPTION_FILTER ExceptionFilter) { CHECK(REAL(SetUnhandledExceptionFilter)); - if (ExceptionFilter == &SEHHandler || common_flags()->allow_user_segv_handler) + if (ExceptionFilter == &SEHHandler) return REAL(SetUnhandledExceptionFilter)(ExceptionFilter); // We record the user provided exception handler to be called for all the // exceptions unhandled by asan. diff --git a/lib/asan/scripts/asan_device_setup b/lib/asan/scripts/asan_device_setup index fdfc46f6e5b8..c807df3cd252 100755 --- a/lib/asan/scripts/asan_device_setup +++ b/lib/asan/scripts/asan_device_setup @@ -327,11 +327,6 @@ exec $_to \$@ EOF } -# On Android-L not allowing user segv handler breaks some applications. -if [[ PRE_L -eq 0 ]]; then - ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1" -fi - if [[ x$extra_options != x ]] ; then ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options" fi diff --git a/lib/asan/tests/asan_interface_test.cc b/lib/asan/tests/asan_interface_test.cc index d13962b8f505..7d3e520d81a4 100644 --- a/lib/asan/tests/asan_interface_test.cc +++ b/lib/asan/tests/asan_interface_test.cc @@ -102,9 +102,6 @@ TEST(AddressSanitizerInterface, GetHeapSizeTest) { } } -#ifndef __powerpc64__ -// FIXME: This has not reliably worked on powerpc since r279664. Re-enable -// this once the problem is tracked down and fixed. static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357}; static const size_t kManyThreadsIterations = 250; static const size_t kManyThreadsNumThreads = @@ -138,7 +135,6 @@ TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) { // so we can't check for equality here. EXPECT_LT(after_test, before_test + (1UL<<20)); } -#endif static void DoDoubleFree() { int *x = Ident(new int); diff --git a/lib/asan/tests/asan_noinst_test.cc b/lib/asan/tests/asan_noinst_test.cc index b3a235e478e3..65acb2839ba1 100644 --- a/lib/asan/tests/asan_noinst_test.cc +++ b/lib/asan/tests/asan_noinst_test.cc @@ -97,9 +97,6 @@ TEST(AddressSanitizer, NoInstMallocTest) { MallocStress(ASAN_LOW_MEMORY ? 300000 : 1000000); } -#ifndef __powerpc64__ -// FIXME: This has not reliably worked on powerpc since r279664. Re-enable -// this once the problem is tracked down and fixed. TEST(AddressSanitizer, ThreadedMallocStressTest) { const int kNumThreads = 4; const int kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000; @@ -112,7 +109,6 @@ TEST(AddressSanitizer, ThreadedMallocStressTest) { PTHREAD_JOIN(t[i], 0); } } -#endif static void PrintShadow(const char *tag, uptr ptr, size_t size) { fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size); @@ -210,10 +206,6 @@ void *ThreadedOneSizeMallocStress(void *unused) { return NULL; } -#ifndef __powerpc64__ -// FIXME: This has not reliably worked on powerpc since r279664. Re-enable -// this once the problem is tracked down and fixed. - TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) { const int kNumThreads = 4; pthread_t t[kNumThreads]; @@ -224,7 +216,6 @@ TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) { PTHREAD_JOIN(t[i], 0); } } -#endif TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) { using __asan::kHighMemEnd; diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc index 7ac72955f487..d0128e34de8d 100644 --- a/lib/asan/tests/asan_test.cc +++ b/lib/asan/tests/asan_test.cc @@ -251,7 +251,8 @@ TEST(AddressSanitizer, BitFieldNegativeTest) { namespace { const char kSEGVCrash[] = "AddressSanitizer: SEGV on unknown address"; -const char kOverriddenHandler[] = "ASan signal handler has been overridden\n"; +const char kOverriddenSigactionHandler[] = "Test sigaction handler\n"; +const char kOverriddenSignalHandler[] = "Test signal handler\n"; TEST(AddressSanitizer, WildAddressTest) { char *c = (char*)0x123; @@ -259,12 +260,12 @@ TEST(AddressSanitizer, WildAddressTest) { } void my_sigaction_sighandler(int, siginfo_t*, void*) { - fprintf(stderr, kOverriddenHandler); + fprintf(stderr, kOverriddenSigactionHandler); exit(1); } void my_signal_sighandler(int signum) { - fprintf(stderr, kOverriddenHandler); + fprintf(stderr, kOverriddenSignalHandler); exit(1); } @@ -273,16 +274,20 @@ TEST(AddressSanitizer, SignalTest) { memset(&sigact, 0, sizeof(sigact)); sigact.sa_sigaction = my_sigaction_sighandler; sigact.sa_flags = SA_SIGINFO; - // ASan should silently ignore sigaction()... + char *c = (char *)0x123; + + EXPECT_DEATH(*c = 0, kSEGVCrash); + + // ASan should allow to set sigaction()... EXPECT_EQ(0, sigaction(SIGSEGV, &sigact, 0)); #ifdef __APPLE__ EXPECT_EQ(0, sigaction(SIGBUS, &sigact, 0)); #endif - char *c = (char*)0x123; - EXPECT_DEATH(*c = 0, kSEGVCrash); + EXPECT_DEATH(*c = 0, kOverriddenSigactionHandler); + // ... and signal(). - EXPECT_EQ(0, signal(SIGSEGV, my_signal_sighandler)); - EXPECT_DEATH(*c = 0, kSEGVCrash); + EXPECT_NE(SIG_ERR, signal(SIGSEGV, my_signal_sighandler)); + EXPECT_DEATH(*c = 0, kOverriddenSignalHandler); } } // namespace #endif diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index df80a50444e5..6556e7ac6513 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -42,6 +42,8 @@ set(GENERIC_SOURCES ashlti3.c ashrdi3.c ashrti3.c + bswapdi2.c + bswapsi2.c clear_cache.c clzdi2.c clzsi2.c @@ -163,8 +165,7 @@ set(GENERIC_SOURCES udivti3.c umoddi3.c umodsi3.c - umodti3.c - emutls.c) + umodti3.c) set(GENERIC_TF_SOURCES comparetf2.c @@ -193,6 +194,7 @@ option(COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN if(NOT COMPILER_RT_BAREMETAL_BUILD) set(GENERIC_SOURCES ${GENERIC_SOURCES} + emutls.c enable_execute_stack.c) endif() diff --git a/lib/builtins/README.txt b/lib/builtins/README.txt index b3d083614ee0..e603dfa05356 100644 --- a/lib/builtins/README.txt +++ b/lib/builtins/README.txt @@ -57,8 +57,8 @@ si_int __popcountsi2(si_int a); // bit population si_int __popcountdi2(di_int a); // bit population si_int __popcountti2(ti_int a); // bit population -uint32_t __bswapsi2(uint32_t a); // a byteswapped, arm only -uint64_t __bswapdi2(uint64_t a); // a byteswapped, arm only +uint32_t __bswapsi2(uint32_t a); // a byteswapped +uint64_t __bswapdi2(uint64_t a); // a byteswapped // Integral arithmetic diff --git a/lib/builtins/arm/aeabi_cdcmp.S b/lib/builtins/arm/aeabi_cdcmp.S index b67814d9f20b..3e7a8b86b739 100644 --- a/lib/builtins/arm/aeabi_cdcmp.S +++ b/lib/builtins/arm/aeabi_cdcmp.S @@ -48,7 +48,12 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq) // NaN has been ruled out, so __aeabi_cdcmple can't trap bne __aeabi_cdcmple +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + mov ip, #APSR_C + msr APSR_nzcvq, ip +#else msr CPSR_f, #APSR_C +#endif JMP(lr) #endif END_COMPILERRT_FUNCTION(__aeabi_cdcmpeq) @@ -95,17 +100,23 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple) lsls r0, r0, #31 pop {r0-r3, pc} #else + ITT(eq) moveq ip, #0 beq 1f ldm sp, {r0-r3} bl __aeabi_dcmpeq cmp r0, #1 + ITE(eq) moveq ip, #(APSR_C | APSR_Z) movne ip, #(APSR_C) 1: +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + msr APSR_nzcvq, ip +#else msr CPSR_f, ip +#endif pop {r0-r3} POP_PC() #endif diff --git a/lib/builtins/arm/aeabi_cfcmp.S b/lib/builtins/arm/aeabi_cfcmp.S index e37aa3d06c4e..1f304ffd964c 100644 --- a/lib/builtins/arm/aeabi_cfcmp.S +++ b/lib/builtins/arm/aeabi_cfcmp.S @@ -48,7 +48,12 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmpeq) // NaN has been ruled out, so __aeabi_cfcmple can't trap bne __aeabi_cfcmple +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + mov ip, #APSR_C + msr APSR_nzcvq, ip +#else msr CPSR_f, #APSR_C +#endif JMP(lr) #endif END_COMPILERRT_FUNCTION(__aeabi_cfcmpeq) @@ -95,17 +100,23 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmple) lsls r0, r0, #31 pop {r0-r3, pc} #else + ITT(eq) moveq ip, #0 beq 1f ldm sp, {r0-r3} bl __aeabi_fcmpeq cmp r0, #1 + ITE(eq) moveq ip, #(APSR_C | APSR_Z) movne ip, #(APSR_C) 1: +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + msr APSR_nzcvq, ip +#else msr CPSR_f, ip +#endif pop {r0-r3} POP_PC() #endif diff --git a/lib/builtins/arm/eqdf2vfp.S b/lib/builtins/arm/eqdf2vfp.S index 8fa0b2debc77..d50706570916 100644 --- a/lib/builtins/arm/eqdf2vfp.S +++ b/lib/builtins/arm/eqdf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__eqdf2vfp) vcmp.f64 d6, d7 #endif vmrs apsr_nzcv, fpscr + ITE(eq) moveq r0, #1 // set result register to 1 if equal movne r0, #0 bx lr diff --git a/lib/builtins/arm/eqsf2vfp.S b/lib/builtins/arm/eqsf2vfp.S index 3776bf4874c2..fd72b2fdbdee 100644 --- a/lib/builtins/arm/eqsf2vfp.S +++ b/lib/builtins/arm/eqsf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__eqsf2vfp) vcmp.f32 s14, s15 #endif vmrs apsr_nzcv, fpscr + ITE(eq) moveq r0, #1 // set result register to 1 if equal movne r0, #0 bx lr diff --git a/lib/builtins/arm/gedf2vfp.S b/lib/builtins/arm/gedf2vfp.S index 14899f00aab6..364fc5b24cd1 100644 --- a/lib/builtins/arm/gedf2vfp.S +++ b/lib/builtins/arm/gedf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__gedf2vfp) vcmp.f64 d6, d7 #endif vmrs apsr_nzcv, fpscr + ITE(ge) movge r0, #1 // set result register to 1 if greater than or equal movlt r0, #0 bx lr diff --git a/lib/builtins/arm/gesf2vfp.S b/lib/builtins/arm/gesf2vfp.S index b49d04d1c239..346c3473ae4c 100644 --- a/lib/builtins/arm/gesf2vfp.S +++ b/lib/builtins/arm/gesf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__gesf2vfp) vcmp.f32 s14, s15 #endif vmrs apsr_nzcv, fpscr + ITE(ge) movge r0, #1 // set result register to 1 if greater than or equal movlt r0, #0 bx lr diff --git a/lib/builtins/arm/gtdf2vfp.S b/lib/builtins/arm/gtdf2vfp.S index 8166305e3af1..3389c3ad9737 100644 --- a/lib/builtins/arm/gtdf2vfp.S +++ b/lib/builtins/arm/gtdf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__gtdf2vfp) vcmp.f64 d6, d7 #endif vmrs apsr_nzcv, fpscr + ITE(gt) movgt r0, #1 // set result register to 1 if equal movle r0, #0 bx lr diff --git a/lib/builtins/arm/gtsf2vfp.S b/lib/builtins/arm/gtsf2vfp.S index d2d8a2380fc8..afdba8b018e2 100644 --- a/lib/builtins/arm/gtsf2vfp.S +++ b/lib/builtins/arm/gtsf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__gtsf2vfp) vcmp.f32 s14, s15 #endif vmrs apsr_nzcv, fpscr + ITE(gt) movgt r0, #1 // set result register to 1 if equal movle r0, #0 bx lr diff --git a/lib/builtins/arm/ledf2vfp.S b/lib/builtins/arm/ledf2vfp.S index a9dab77c1469..4bbe4c86837c 100644 --- a/lib/builtins/arm/ledf2vfp.S +++ b/lib/builtins/arm/ledf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__ledf2vfp) vcmp.f64 d6, d7 #endif vmrs apsr_nzcv, fpscr + ITE(ls) movls r0, #1 // set result register to 1 if equal movhi r0, #0 bx lr diff --git a/lib/builtins/arm/lesf2vfp.S b/lib/builtins/arm/lesf2vfp.S index 7e127f465cfd..51232bd8cedc 100644 --- a/lib/builtins/arm/lesf2vfp.S +++ b/lib/builtins/arm/lesf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__lesf2vfp) vcmp.f32 s14, s15 #endif vmrs apsr_nzcv, fpscr + ITE(ls) movls r0, #1 // set result register to 1 if equal movhi r0, #0 bx lr diff --git a/lib/builtins/arm/ltdf2vfp.S b/lib/builtins/arm/ltdf2vfp.S index 8b6f8e4cc8a4..8e2928c813d2 100644 --- a/lib/builtins/arm/ltdf2vfp.S +++ b/lib/builtins/arm/ltdf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__ltdf2vfp) vcmp.f64 d6, d7 #endif vmrs apsr_nzcv, fpscr + ITE(mi) movmi r0, #1 // set result register to 1 if equal movpl r0, #0 bx lr diff --git a/lib/builtins/arm/ltsf2vfp.S b/lib/builtins/arm/ltsf2vfp.S index c4ff812b49a3..59c00c6bab67 100644 --- a/lib/builtins/arm/ltsf2vfp.S +++ b/lib/builtins/arm/ltsf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__ltsf2vfp) vcmp.f32 s14, s15 #endif vmrs apsr_nzcv, fpscr + ITE(mi) movmi r0, #1 // set result register to 1 if equal movpl r0, #0 bx lr diff --git a/lib/builtins/arm/nedf2vfp.S b/lib/builtins/arm/nedf2vfp.S index 7d884e07204c..aef72eb00974 100644 --- a/lib/builtins/arm/nedf2vfp.S +++ b/lib/builtins/arm/nedf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__nedf2vfp) vcmp.f64 d6, d7 #endif vmrs apsr_nzcv, fpscr + ITE(ne) movne r0, #1 // set result register to 0 if unequal moveq r0, #0 bx lr diff --git a/lib/builtins/arm/nesf2vfp.S b/lib/builtins/arm/nesf2vfp.S index 97c764f63697..50d60f493005 100644 --- a/lib/builtins/arm/nesf2vfp.S +++ b/lib/builtins/arm/nesf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__nesf2vfp) vcmp.f32 s14, s15 #endif vmrs apsr_nzcv, fpscr + ITE(ne) movne r0, #1 // set result register to 1 if unequal moveq r0, #0 bx lr diff --git a/lib/builtins/arm/unorddf2vfp.S b/lib/builtins/arm/unorddf2vfp.S index 855637547003..6625fa8a3119 100644 --- a/lib/builtins/arm/unorddf2vfp.S +++ b/lib/builtins/arm/unorddf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__unorddf2vfp) vcmp.f64 d6, d7 #endif vmrs apsr_nzcv, fpscr + ITE(vs) movvs r0, #1 // set result register to 1 if "overflow" (any NaNs) movvc r0, #0 bx lr diff --git a/lib/builtins/arm/unordsf2vfp.S b/lib/builtins/arm/unordsf2vfp.S index 2b16b4905c48..0b5da2ba3e17 100644 --- a/lib/builtins/arm/unordsf2vfp.S +++ b/lib/builtins/arm/unordsf2vfp.S @@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__unordsf2vfp) vcmp.f32 s14, s15 #endif vmrs apsr_nzcv, fpscr + ITE(vs) movvs r0, #1 // set result register to 1 if "overflow" (any NaNs) movvc r0, #0 bx lr diff --git a/lib/builtins/assembly.h b/lib/builtins/assembly.h index 12c13c495509..b15da52345c8 100644 --- a/lib/builtins/assembly.h +++ b/lib/builtins/assembly.h @@ -96,9 +96,11 @@ #if __ARM_ARCH_ISA_THUMB == 2 #define IT(cond) it cond #define ITT(cond) itt cond +#define ITE(cond) ite cond #else #define IT(cond) #define ITT(cond) +#define ITE(cond) #endif #if __ARM_ARCH_ISA_THUMB == 2 diff --git a/lib/builtins/bswapdi2.c b/lib/builtins/bswapdi2.c new file mode 100644 index 000000000000..eb220007bb10 --- /dev/null +++ b/lib/builtins/bswapdi2.c @@ -0,0 +1,27 @@ +/* ===-- bswapdi2.c - Implement __bswapdi2 ---------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __bswapdi2 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +COMPILER_RT_ABI uint64_t __bswapdi2(uint64_t u) { + return ( + (((u)&0xff00000000000000ULL) >> 56) | + (((u)&0x00ff000000000000ULL) >> 40) | + (((u)&0x0000ff0000000000ULL) >> 24) | + (((u)&0x000000ff00000000ULL) >> 8) | + (((u)&0x00000000ff000000ULL) << 8) | + (((u)&0x0000000000ff0000ULL) << 24) | + (((u)&0x000000000000ff00ULL) << 40) | + (((u)&0x00000000000000ffULL) << 56)); +} diff --git a/lib/builtins/bswapsi2.c b/lib/builtins/bswapsi2.c new file mode 100644 index 000000000000..5d941e69f7c4 --- /dev/null +++ b/lib/builtins/bswapsi2.c @@ -0,0 +1,23 @@ +/* ===-- bswapsi2.c - Implement __bswapsi2 ---------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __bswapsi2 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +COMPILER_RT_ABI uint32_t __bswapsi2(uint32_t u) { + return ( + (((u)&0xff000000) >> 24) | + (((u)&0x00ff0000) >> 8) | + (((u)&0x0000ff00) << 8) | + (((u)&0x000000ff) << 24)); +} diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc index a6b3453f5a0b..a5ffc6835f5f 100644 --- a/lib/lsan/lsan_common.cc +++ b/lib/lsan/lsan_common.cc @@ -265,19 +265,21 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads, } if (flags()->use_tls) { - LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end); - if (cache_begin == cache_end) { - ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable); - } else { - // Because LSan should not be loaded with dlopen(), we can assume - // that allocator cache will be part of static TLS image. - CHECK_LE(tls_begin, cache_begin); - CHECK_GE(tls_end, cache_end); - if (tls_begin < cache_begin) - ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS", - kReachable); - if (tls_end > cache_end) - ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable); + if (tls_begin) { + LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end); + // If the tls and cache ranges don't overlap, scan full tls range, + // otherwise, only scan the non-overlapping portions + if (cache_begin == cache_end || tls_end < cache_begin || + tls_begin > cache_end) { + ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable); + } else { + if (tls_begin < cache_begin) + ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS", + kReachable); + if (tls_end > cache_end) + ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", + kReachable); + } } if (dtls && !DTLSInDestruction(dtls)) { for (uptr j = 0; j < dtls->dtv_size; ++j) { diff --git a/lib/lsan/lsan_common_mac.cc b/lib/lsan/lsan_common_mac.cc index ae10955439c8..114dd8c9019e 100644 --- a/lib/lsan/lsan_common_mac.cc +++ b/lib/lsan/lsan_common_mac.cc @@ -91,12 +91,7 @@ LoadedModule *GetLinker() { return nullptr; } // Required on Linux for initialization of TLS behavior, but should not be // required on Darwin. -void InitializePlatformSpecificModules() { - if (flags()->use_tls) { - Report("use_tls=1 is not supported on Darwin.\n"); - Die(); - } -} +void InitializePlatformSpecificModules() {} // Scans global variables for heap pointers. void ProcessGlobalRegions(Frontier *frontier) { diff --git a/lib/lsan/lsan_flags.inc b/lib/lsan/lsan_flags.inc index 8135bdcff01a..e390e2ae5a1b 100644 --- a/lib/lsan/lsan_flags.inc +++ b/lib/lsan/lsan_flags.inc @@ -30,7 +30,7 @@ LSAN_FLAG(bool, use_globals, true, "Root set: include global variables (.data and .bss)") LSAN_FLAG(bool, use_stacks, true, "Root set: include thread stacks") LSAN_FLAG(bool, use_registers, true, "Root set: include thread registers") -LSAN_FLAG(bool, use_tls, !SANITIZER_MAC, +LSAN_FLAG(bool, use_tls, true, "Root set: include TLS and thread-specific storage") LSAN_FLAG(bool, use_root_regions, true, "Root set: include regions added via __lsan_register_root_region().") diff --git a/lib/sanitizer_common/sanitizer_allocator_primary32.h b/lib/sanitizer_common/sanitizer_allocator_primary32.h index 0f6f4f7f8503..e13510ba33b9 100644 --- a/lib/sanitizer_common/sanitizer_allocator_primary32.h +++ b/lib/sanitizer_common/sanitizer_allocator_primary32.h @@ -319,5 +319,3 @@ class SizeClassAllocator32 { ByteMap possible_regions; SizeClassInfo size_class_info_array[kNumClasses]; }; - - diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 33e652e6c3df..a1c9c5a57a84 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -380,7 +380,7 @@ void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)); // Functions related to signal handling. typedef void (*SignalHandlerType)(int, void *, void *); -bool IsHandledDeadlySignal(int signum); +HandleSignalMode GetHandleSignalMode(int signum); void InstallDeadlySignalHandlers(SignalHandlerType handler); const char *DescribeSignalOrException(int signo); // Alternative signal stack (POSIX-only). diff --git a/lib/sanitizer_common/sanitizer_flag_parser.h b/lib/sanitizer_common/sanitizer_flag_parser.h index b6ae307fc93e..4988fbb7a86d 100644 --- a/lib/sanitizer_common/sanitizer_flag_parser.h +++ b/lib/sanitizer_common/sanitizer_flag_parser.h @@ -64,6 +64,11 @@ inline bool FlagHandler::Parse(const char *value) { *t_ = b ? kHandleSignalYes : kHandleSignalNo; return true; } + if (internal_strcmp(value, "2") == 0 || + internal_strcmp(value, "exclusive") == 0) { + *t_ = kHandleSignalExclusive; + return true; + } Printf("ERROR: Invalid value for signal handler option: '%s'\n", value); return false; } diff --git a/lib/sanitizer_common/sanitizer_flags.h b/lib/sanitizer_common/sanitizer_flags.h index f22593395ed5..c2ec29d1656e 100644 --- a/lib/sanitizer_common/sanitizer_flags.h +++ b/lib/sanitizer_common/sanitizer_flags.h @@ -21,6 +21,7 @@ namespace __sanitizer { enum HandleSignalMode { kHandleSignalNo, kHandleSignalYes, + kHandleSignalExclusive, }; struct CommonFlags { diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index c5aaf411fcc2..12c126fa707c 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -75,12 +75,13 @@ COMMON_FLAG(bool, print_summary, true, "If false, disable printing error summaries in addition to error " "reports.") COMMON_FLAG(int, print_module_map, 0, - "OS X only. 0 = don't print, 1 = print only once before process " - "exits, 2 = print after each report.") + "OS X only (0 - don't print, 1 - print only once before process " + "exits, 2 - print after each report).") COMMON_FLAG(bool, check_printf, true, "Check printf arguments.") #define COMMON_FLAG_HANDLE_SIGNAL_HELP(signal) \ "Controls custom tool's " #signal " handler (0 - do not registers the " \ - "handler, 1 - register the handler). " + "handler, 1 - register the handler and allow user to set own, " \ + "2 - registers the handler and block user from changing it). " COMMON_FLAG(HandleSignalMode, handle_segv, kHandleSignalYes, COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGSEGV)) COMMON_FLAG(HandleSignalMode, handle_sigbus, kHandleSignalYes, @@ -92,9 +93,6 @@ COMMON_FLAG(HandleSignalMode, handle_sigill, kHandleSignalNo, COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes, COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGFPE)) #undef COMMON_FLAG_HANDLE_SIGNAL_HELP -COMMON_FLAG(bool, allow_user_segv_handler, false, - "If set, allows user to register a SEGV handler even if the tool " - "registers one.") COMMON_FLAG(bool, use_sigaltstack, true, "If set, uses alternate stack for signal handling.") COMMON_FLAG(bool, detect_deadlocks, false, diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index 87f32c44d71a..3bda35655d9e 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -549,7 +549,7 @@ void BlockingMutex::Lock() { void BlockingMutex::Unlock() { atomic_uint32_t *m = reinterpret_cast(&opaque_storage_); - u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); + u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release); CHECK_NE(v, MtxUnlocked); if (v == MtxSleeping) { #if SANITIZER_FREEBSD @@ -1394,7 +1394,7 @@ AndroidApiLevel AndroidGetApiLevel() { #endif -bool IsHandledDeadlySignal(int signum) { +HandleSignalMode GetHandleSignalMode(int signum) { switch (signum) { case SIGABRT: return common_flags()->handle_abort; @@ -1407,7 +1407,7 @@ bool IsHandledDeadlySignal(int signum) { case SIGBUS: return common_flags()->handle_sigbus; } - return false; + return kHandleSignalNo; } #if !SANITIZER_GO diff --git a/lib/sanitizer_common/sanitizer_linux_s390.cc b/lib/sanitizer_common/sanitizer_linux_s390.cc index c2b03b27e66c..a6da82ecb1d2 100644 --- a/lib/sanitizer_common/sanitizer_linux_s390.cc +++ b/lib/sanitizer_common/sanitizer_linux_s390.cc @@ -178,6 +178,13 @@ static bool FixedCVE_2016_2143() { // 4.4.6+ is OK. if (minor == 4 && patch >= 6) return true; + if (minor == 4 && patch == 0 && ptr[0] == '-' && + internal_strstr(buf.version, "Ubuntu")) { + // Check Ubuntu 16.04 + int r1 = internal_simple_strtoll(ptr+1, &ptr, 10); + if (r1 >= 13) // 4.4.0-13 or later + return true; + } // Otherwise, OK if 4.5+. return minor >= 5; } else { diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index f1a6bf91635c..f1b9e5fda5c0 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -370,6 +370,27 @@ uptr GetTlsSize() { void InitTlsSize() { } +uptr TlsBaseAddr() { + uptr segbase = 0; +#if defined(__x86_64__) + asm("movq %%gs:0,%0" : "=r"(segbase)); +#elif defined(__i386__) + asm("movl %%gs:0,%0" : "=r"(segbase)); +#endif + return segbase; +} + +// The size of the tls on darwin does not appear to be well documented, +// however the vm memory map suggests that it is 1024 uptrs in size, +// with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386. +uptr TlsSize() { +#if defined(__x86_64__) || defined(__i386__) + return 1024 * sizeof(uptr); +#else + return 0; +#endif +} + void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, uptr *tls_addr, uptr *tls_size) { #if !SANITIZER_GO @@ -377,8 +398,8 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); *stk_addr = stack_bottom; *stk_size = stack_top - stack_bottom; - *tls_addr = 0; - *tls_size = 0; + *tls_addr = TlsBaseAddr(); + *tls_size = TlsSize(); #else *stk_addr = 0; *stk_size = 0; @@ -393,10 +414,10 @@ void ListOfModules::init() { memory_mapping.DumpListOfModules(&modules_); } -bool IsHandledDeadlySignal(int signum) { +HandleSignalMode GetHandleSignalMode(int signum) { // Handling fatal signals on watchOS and tvOS devices is disallowed. if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM)) - return false; + return kHandleSignalNo; switch (signum) { case SIGABRT: return common_flags()->handle_abort; @@ -409,7 +430,7 @@ bool IsHandledDeadlySignal(int signum) { case SIGBUS: return common_flags()->handle_sigbus; } - return false; + return kHandleSignalNo; } MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED; diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index 8d688f3778b5..791ff4481ca8 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -134,7 +134,8 @@ void SleepForMillis(int millis) { void Abort() { #if !SANITIZER_GO // If we are handling SIGABRT, unhandle it first. - if (IsHandledDeadlySignal(SIGABRT)) { + // TODO(vitalybuka): Check if handler belongs to sanitizer. + if (GetHandleSignalMode(SIGABRT) != kHandleSignalNo) { struct sigaction sigact; internal_memset(&sigact, 0, sizeof(sigact)); sigact.sa_sigaction = (sa_sigaction_t)SIG_DFL; @@ -188,8 +189,26 @@ void UnsetAlternateSignalStack() { static void MaybeInstallSigaction(int signum, SignalHandlerType handler) { - if (!IsHandledDeadlySignal(signum)) - return; + switch (GetHandleSignalMode(signum)) { + case kHandleSignalNo: + return; + case kHandleSignalYes: { + struct sigaction sigact; + internal_memset(&sigact, 0, sizeof(sigact)); + CHECK_EQ(0, internal_sigaction(signum, nullptr, &sigact)); + if (sigact.sa_flags & SA_SIGINFO) { + if (sigact.sa_sigaction) return; + } else { + if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && + sigact.sa_handler != SIG_ERR) + return; + } + break; + } + case kHandleSignalExclusive: + break; + } + struct sigaction sigact; internal_memset(&sigact, 0, sizeof(sigact)); sigact.sa_sigaction = (sa_sigaction_t)handler; diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index d0a5c078cd68..c912e8fa2aa3 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -832,9 +832,9 @@ void InstallDeadlySignalHandlers(SignalHandlerType handler) { // FIXME: Decide what to do on Windows. } -bool IsHandledDeadlySignal(int signum) { +HandleSignalMode GetHandleSignalMode(int signum) { // FIXME: Decide what to do on Windows. - return false; + return kHandleSignalNo; } // Check based on flags if we should handle this exception. diff --git a/lib/sanitizer_common/tests/sanitizer_flags_test.cc b/lib/sanitizer_common/tests/sanitizer_flags_test.cc index 34d7067f85ff..0af84a20b7f5 100644 --- a/lib/sanitizer_common/tests/sanitizer_flags_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_flags_test.cc @@ -78,13 +78,15 @@ TEST(SanitizerCommon, HandleSignalMode) { TestFlag(kHandleSignalYes, "flag_name=0", kHandleSignalNo); TestFlag(kHandleSignalYes, "flag_name=no", kHandleSignalNo); TestFlag(kHandleSignalYes, "flag_name=false", kHandleSignalNo); + TestFlag(kHandleSignalNo, "flag_name=2", kHandleSignalExclusive); + TestFlag(kHandleSignalYes, "flag_name=exclusive", kHandleSignalExclusive); EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name", kHandleSignalNo), "expected '='"); EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=", kHandleSignalNo), "Invalid value for signal handler option: ''"); - EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=2", kHandleSignalNo), - "Invalid value for signal handler option: '2'"); + EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=3", kHandleSignalNo), + "Invalid value for signal handler option: '3'"); EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=-1", kHandleSignalNo), "Invalid value for signal handler option: '-1'"); EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=on", kHandleSignalNo), diff --git a/lib/scudo/scudo_tls_linux.cpp b/lib/scudo/scudo_tls_linux.cpp index 5a9cc998bccf..1e38233f339c 100644 --- a/lib/scudo/scudo_tls_linux.cpp +++ b/lib/scudo/scudo_tls_linux.cpp @@ -18,7 +18,6 @@ #include "scudo_tls.h" -#include #include namespace __scudo { @@ -32,15 +31,17 @@ __attribute__((tls_model("initial-exec"))) THREADLOCAL ScudoThreadContext ThreadLocalContext; static void teardownThread(void *Ptr) { - uptr Iteration = reinterpret_cast(Ptr); + uptr I = reinterpret_cast(Ptr); // The glibc POSIX thread-local-storage deallocation routine calls user // provided destructors in a loop of PTHREAD_DESTRUCTOR_ITERATIONS. // We want to be called last since other destructors might call free and the // like, so we wait until PTHREAD_DESTRUCTOR_ITERATIONS before draining the // quarantine and swallowing the cache. - if (Iteration < PTHREAD_DESTRUCTOR_ITERATIONS) { - pthread_setspecific(PThreadKey, reinterpret_cast(Iteration + 1)); - return; + if (I > 1) { + // If pthread_setspecific fails, we will go ahead with the teardown. + if (LIKELY(pthread_setspecific(PThreadKey, + reinterpret_cast(I - 1)) == 0)) + return; } ThreadLocalContext.commitBack(); ScudoThreadState = ThreadTornDown; @@ -53,8 +54,9 @@ static void initOnce() { } void initThread() { - pthread_once(&GlobalInitialized, initOnce); - pthread_setspecific(PThreadKey, reinterpret_cast(1)); + CHECK_EQ(pthread_once(&GlobalInitialized, initOnce), 0); + CHECK_EQ(pthread_setspecific(PThreadKey, reinterpret_cast( + GetPthreadDestructorIterations())), 0); ThreadLocalContext.init(); ScudoThreadState = ThreadInitialized; } diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h index 1dd9d91d4c92..60d9b9d8c452 100644 --- a/lib/tsan/rtl/tsan_platform.h +++ b/lib/tsan/rtl/tsan_platform.h @@ -816,6 +816,7 @@ void FlushShadowMemory(); void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive); int ExtractResolvFDs(void *state, int *fds, int nfd); int ExtractRecvmsgFDs(void *msg, int *fds, int nfd); +void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size); int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, void *abstime), void *c, void *m, void *abstime, diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc index 2d488cadd4fe..d05c0e701e72 100644 --- a/lib/tsan/rtl/tsan_platform_linux.cc +++ b/lib/tsan/rtl/tsan_platform_linux.cc @@ -320,6 +320,20 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) { return res; } +void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) { + // Check that the thr object is in tls; + const uptr thr_beg = (uptr)thr; + const uptr thr_end = (uptr)thr + sizeof(*thr); + CHECK_GE(thr_beg, tls_addr); + CHECK_LE(thr_beg, tls_addr + tls_size); + CHECK_GE(thr_end, tls_addr); + CHECK_LE(thr_end, tls_addr + tls_size); + // Since the thr object is huge, skip it. + MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, thr_beg - tls_addr); + MemoryRangeImitateWrite(thr, /*pc=*/2, thr_end, + tls_addr + tls_size - thr_end); +} + // Note: this function runs with async signals enabled, // so it must not touch any tsan state. int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index b8d3d5528bb5..a82bcd01bbf4 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -75,12 +75,18 @@ static void *SignalSafeGetOrAllocate(uptr *dst, uptr size) { static uptr main_thread_identity = 0; ALIGNED(64) static char main_thread_state[sizeof(ThreadState)]; +ThreadState **cur_thread_location() { + ThreadState **thread_identity = (ThreadState **)pthread_self(); + return ((uptr)thread_identity == main_thread_identity) ? nullptr + : thread_identity; +} + ThreadState *cur_thread() { - uptr thread_identity = (uptr)pthread_self(); - if (thread_identity == main_thread_identity || main_thread_identity == 0) { + ThreadState **thr_state_loc = cur_thread_location(); + if (thr_state_loc == nullptr || main_thread_identity == 0) { return (ThreadState *)&main_thread_state; } - ThreadState **fake_tls = (ThreadState **)MemToShadow(thread_identity); + ThreadState **fake_tls = (ThreadState **)MemToShadow((uptr)thr_state_loc); ThreadState *thr = (ThreadState *)SignalSafeGetOrAllocate( (uptr *)fake_tls, sizeof(ThreadState)); return thr; @@ -90,13 +96,13 @@ ThreadState *cur_thread() { // munmap first and then clear `fake_tls`; if we receive a signal in between, // handler will try to access the unmapped ThreadState. void cur_thread_finalize() { - uptr thread_identity = (uptr)pthread_self(); - if (thread_identity == main_thread_identity) { + ThreadState **thr_state_loc = cur_thread_location(); + if (thr_state_loc == nullptr) { // Calling dispatch_main() or xpc_main() actually invokes pthread_exit to // exit the main thread. Let's keep the main thread's ThreadState. return; } - ThreadState **fake_tls = (ThreadState **)MemToShadow(thread_identity); + ThreadState **fake_tls = (ThreadState **)MemToShadow((uptr)thr_state_loc); internal_munmap(*fake_tls, sizeof(ThreadState)); *fake_tls = nullptr; } @@ -239,6 +245,29 @@ void InitializePlatform() { #endif } +#if !SANITIZER_GO +void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) { + // The pointer to the ThreadState object is stored in the shadow memory + // of the tls. + uptr tls_end = tls_addr + tls_size; + ThreadState **thr_state_loc = cur_thread_location(); + if (thr_state_loc == nullptr) { + MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, tls_size); + } else { + uptr thr_state_start = (uptr)thr_state_loc; + uptr thr_state_end = thr_state_start + sizeof(uptr); + CHECK_GE(thr_state_start, tls_addr); + CHECK_LE(thr_state_start, tls_addr + tls_size); + CHECK_GE(thr_state_end, tls_addr); + CHECK_LE(thr_state_end, tls_addr + tls_size); + MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, + thr_state_start - tls_addr); + MemoryRangeImitateWrite(thr, /*pc=*/2, thr_state_end, + tls_end - thr_state_end); + } +} +#endif + #if !SANITIZER_GO // Note: this function runs with async signals enabled, // so it must not touch any tsan state. diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc index 6a0943c49588..edb60980c76f 100644 --- a/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/lib/tsan/rtl/tsan_rtl_thread.cc @@ -248,19 +248,7 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id, bool workerthread) { if (stk_addr && stk_size) MemoryRangeImitateWrite(thr, /*pc=*/ 1, stk_addr, stk_size); - if (tls_addr && tls_size) { - // Check that the thr object is in tls; - const uptr thr_beg = (uptr)thr; - const uptr thr_end = (uptr)thr + sizeof(*thr); - CHECK_GE(thr_beg, tls_addr); - CHECK_LE(thr_beg, tls_addr + tls_size); - CHECK_GE(thr_end, tls_addr); - CHECK_LE(thr_end, tls_addr + tls_size); - // Since the thr object is huge, skip it. - MemoryRangeImitateWrite(thr, /*pc=*/ 2, tls_addr, thr_beg - tls_addr); - MemoryRangeImitateWrite(thr, /*pc=*/ 2, - thr_end, tls_addr + tls_size - thr_end); - } + if (tls_addr && tls_size) ImitateTlsWrite(thr, tls_addr, tls_size); } #endif diff --git a/test/asan/TestCases/Linux/preinstalled_signal.cc b/test/asan/TestCases/Linux/preinstalled_signal.cc new file mode 100644 index 000000000000..40dadf43dc4e --- /dev/null +++ b/test/asan/TestCases/Linux/preinstalled_signal.cc @@ -0,0 +1,105 @@ +// clang-format off +// RUN: %clangxx -std=c++11 %s -o %t +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s + +// RUN: %clangxx -std=c++11 -DTEST_INSTALL_SIG_HANDLER %s -o %t +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-HANDLER %s +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s + +// RUN: %clangxx -std=c++11 -DTEST_INSTALL_SIG_ACTION %s -o %t +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-ACTION %s +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s + +// REQUIRES: asan-dynamic-runtime + +// This way of setting LD_PRELOAD does not work with Android test runner. +// REQUIRES: not-android +// clang-format on + +#include +#include +#include +#include +#include +#include +#include + +const char *handler = nullptr; +void SigHandler(int signum) { handler = "TestSigHandler"; } +void SigAction(int, siginfo_t *, void *) { handler = "TestSigAction"; } + +struct KernelSigaction { + __sighandler_t handler; + unsigned long flags; + void (*restorer)(); + char unused[1024]; +}; + +#if defined(__x86_64__) +extern "C" void restorer(); +asm("restorer:mov $15,%rax\nsyscall"); +#endif + +int InternalSigaction(int sig, KernelSigaction *act, KernelSigaction *oact) { + if (act) { +#if defined(__x86_64__) + act->flags |= 0x04000000; + act->restorer = &restorer; +#endif + } + return syscall(__NR_rt_sigaction, sig, act, oact, NSIG / 8); +} + +struct KernelSigaction sigact = {}; + +static void Init() { + int res = InternalSigaction(SIGSEGV, nullptr, &sigact); + assert(res >= 0); + assert(sigact.handler == SIG_DFL || sigact.handler == SIG_IGN); +#if defined(TEST_INSTALL_SIG_HANDLER) + sigact = {}; + sigact.handler = &SigHandler; + res = InternalSigaction(SIGSEGV, &sigact, nullptr); + assert(res >= 0); +#elif defined(TEST_INSTALL_SIG_ACTION) + sigact = {}; + sigact.flags = SA_SIGINFO | SA_NODEFER; + sigact.handler = (__sighandler_t)&SigAction; + res = InternalSigaction(SIGSEGV, &sigact, nullptr); + assert(res >= 0); +#endif +} + +__attribute__((section(".preinit_array"), used)) +void (*__local_test_preinit)(void) = Init; + +bool ShouldAsanInstallHandlers() { +#if defined(TEST_INSTALL_SIG_HANDLER) || defined(TEST_INSTALL_SIG_ACTION) + return !strcmp(getenv("ASAN_OPTIONS"), "handle_segv=2"); +#endif + return true; +} + +int main(int argc, char *argv[]) { + KernelSigaction sigact_asan = {}; + InternalSigaction(SIGSEGV, nullptr, &sigact_asan); + + assert(sigact_asan.handler != SIG_DFL); + assert(sigact_asan.handler != SIG_IGN); + assert(ShouldAsanInstallHandlers() == + (sigact_asan.handler != sigact.handler)); + + raise(SIGSEGV); + printf("%s\n", handler); + return 1; +} + +// CHECK-NOT: TestSig +// CHECK: ASAN:DEADLYSIGNAL + +// CHECK-HANDLER-NOT: ASAN:DEADLYSIGNAL +// CHECK-HANDLER: TestSigHandler + +// CHECK-ACTION-NOT: ASAN:DEADLYSIGNAL +// CHECK-ACTION: TestSigAction diff --git a/test/asan/TestCases/Linux/sanbox_read_proc_self_maps_test.cc b/test/asan/TestCases/Linux/sanbox_read_proc_self_maps_test.cc index a845721d5982..d9099edffcac 100644 --- a/test/asan/TestCases/Linux/sanbox_read_proc_self_maps_test.cc +++ b/test/asan/TestCases/Linux/sanbox_read_proc_self_maps_test.cc @@ -14,17 +14,15 @@ int main() { if (unshare(CLONE_NEWUSER)) { printf("unshare failed\n"); - abort(); + return 1; } // remove access to /proc/self/maps if (chroot("/tmp")) { printf("chroot failed\n"); - abort(); + return 2; } *(volatile int*)0x42 = 0; -// CHECK: AddressSanitizer: SEGV on unknown address 0x000000000042 -// CHECK-NOT: AddressSanitizer CHECK failed -// CHECK: SUMMARY: AddressSanitizer: SEGV +// CHECK-NOT: CHECK failed } diff --git a/test/asan/TestCases/Posix/allow_user_segv.cc b/test/asan/TestCases/Posix/allow_user_segv.cc index 69c1df9a1d3f..52f4f046da9d 100644 --- a/test/asan/TestCases/Posix/allow_user_segv.cc +++ b/test/asan/TestCases/Posix/allow_user_segv.cc @@ -1,8 +1,14 @@ // Regression test for // https://code.google.com/p/address-sanitizer/issues/detail?id=180 -// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0 +// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0 + +// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 +// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 + +// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 +// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 #include #include @@ -22,10 +28,14 @@ void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) { printf("Invalid signum"); exit(1); } - if (original_sigaction.sa_flags | SA_SIGINFO) - original_sigaction.sa_sigaction(signum, siginfo, context); - else - original_sigaction.sa_handler(signum); + if (original_sigaction.sa_flags | SA_SIGINFO) { + if (original_sigaction.sa_sigaction) + original_sigaction.sa_sigaction(signum, siginfo, context); + } else { + if (original_sigaction.sa_handler) + original_sigaction.sa_handler(signum); + } + exit(1); } int DoSEGV() { @@ -33,27 +43,38 @@ int DoSEGV() { return *x; } -int InstallHandler(int signum, struct sigaction *original_sigaction) { +bool InstallHandler(int signum, struct sigaction *original_sigaction) { struct sigaction user_sigaction; user_sigaction.sa_sigaction = User_OnSIGSEGV; user_sigaction.sa_flags = SA_SIGINFO; if (sigaction(signum, &user_sigaction, original_sigaction)) { perror("sigaction"); - return 1; + return false; } - return 0; + return true; } int main() { // Let's install handlers for both SIGSEGV and SIGBUS, since pre-Yosemite // 32-bit Darwin triggers SIGBUS instead. - if (InstallHandler(SIGSEGV, &original_sigaction_sigsegv)) return 1; - if (InstallHandler(SIGBUS, &original_sigaction_sigbus)) return 1; - fprintf(stderr, "User sigaction installed\n"); + if (InstallHandler(SIGSEGV, &original_sigaction_sigsegv) && + InstallHandler(SIGBUS, &original_sigaction_sigbus)) { + fprintf(stderr, "User sigaction installed\n"); + } return DoSEGV(); } -// CHECK: User sigaction installed -// CHECK-NEXT: User sigaction called -// CHECK-NEXT: ASAN:DEADLYSIGNAL -// CHECK: AddressSanitizer: SEGV on unknown address +// CHECK0-NOT: ASAN:DEADLYSIGNAL +// CHECK0-NOT: AddressSanitizer: SEGV on unknown address +// CHECK0: User sigaction installed +// CHECK0-NEXT: User sigaction called + +// CHECK1: User sigaction installed +// CHECK1-NEXT: User sigaction called +// CHECK1-NEXT: ASAN:DEADLYSIGNAL +// CHECK1: AddressSanitizer: SEGV on unknown address + +// CHECK2-NOT: User sigaction called +// CHECK2: User sigaction installed +// CHECK2-NEXT: ASAN:DEADLYSIGNAL +// CHECK2: AddressSanitizer: SEGV on unknown address diff --git a/test/asan/TestCases/Posix/current_allocated_bytes.cc b/test/asan/TestCases/Posix/current_allocated_bytes.cc index 51630cfd8a6b..c49e433b1e8b 100644 --- a/test/asan/TestCases/Posix/current_allocated_bytes.cc +++ b/test/asan/TestCases/Posix/current_allocated_bytes.cc @@ -1,9 +1,6 @@ // RUN: %clangxx_asan -O0 %s -pthread -o %t && %run %t // RUN: %clangxx_asan -O2 %s -pthread -o %t && %run %t // REQUIRES: stable-runtime -// UNSUPPORTED: powerpc64le -// FIXME: This test occasionally fails on powerpc64 LE possibly starting with -// r279664. Re-enable the test once the problem(s) have been fixed. #include #include diff --git a/test/asan/TestCases/Posix/wait.cc b/test/asan/TestCases/Posix/wait.cc index ed6f326b57d6..85e819369c0d 100644 --- a/test/asan/TestCases/Posix/wait.cc +++ b/test/asan/TestCases/Posix/wait.cc @@ -4,6 +4,7 @@ // RUN: %clangxx_asan -DWAITPID -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -DWAITPID -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include #include diff --git a/test/asan/TestCases/Posix/wait3.cc b/test/asan/TestCases/Posix/wait3.cc index 2da816fed1aa..081a73e16f0b 100644 --- a/test/asan/TestCases/Posix/wait3.cc +++ b/test/asan/TestCases/Posix/wait3.cc @@ -4,7 +4,7 @@ // RUN: %clangxx_asan -DWAIT3_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -DWAIT3_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s -// UNSUPPORTED: android +// UNSUPPORTED: android,darwin #include #include diff --git a/test/asan/TestCases/Posix/wait4.cc b/test/asan/TestCases/Posix/wait4.cc index b95246efa0e4..aee5570b82e1 100644 --- a/test/asan/TestCases/Posix/wait4.cc +++ b/test/asan/TestCases/Posix/wait4.cc @@ -5,6 +5,7 @@ // RUN: %clangxx_asan -DWAIT4_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s // XFAIL: android +// UNSUPPORTED: darwin #include #include diff --git a/test/asan/TestCases/Posix/waitid.cc b/test/asan/TestCases/Posix/waitid.cc index 8b516dca9086..20fb0c694386 100644 --- a/test/asan/TestCases/Posix/waitid.cc +++ b/test/asan/TestCases/Posix/waitid.cc @@ -1,6 +1,8 @@ // RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin + #include #include #include diff --git a/test/builtins/Unit/bswapdi2_test.c b/test/builtins/Unit/bswapdi2_test.c index 6881c8092cbb..57ee38b786e1 100644 --- a/test/builtins/Unit/bswapdi2_test.c +++ b/test/builtins/Unit/bswapdi2_test.c @@ -13,34 +13,25 @@ // //===----------------------------------------------------------------------===// -#include +#include #include #include -#include - +#include extern uint64_t __bswapdi2(uint64_t); -#if __arm__ -int test__bswapdi2(uint64_t a, uint64_t expected) -{ - uint64_t actual = __bswapdi2(a); - if (actual != expected) - printf("error in test__bswapsi2(0x%0llX) = 0x%0llX, expected 0x%0llX\n", - a, actual, expected); - return actual != expected; +int test__bswapdi2(uint64_t a, uint64_t expected) { + uint64_t actual = __bswapdi2(a); + if (actual != expected) + printf("error in test__bswapsi2(0x%0llX) = 0x%0llX, expected 0x%0llX\n", a, + actual, expected); + return actual != expected; } -#endif -int main() -{ -#if __arm__ - if (test__bswapdi2(0x123456789ABCDEF0LL, 0xF0DEBC9A78563412LL)) - return 1; - if (test__bswapdi2(0x0000000100000002LL, 0x0200000001000000LL)) - return 1; -#else - printf("skipped\n"); -#endif - return 0; +int main() { + if (test__bswapdi2(0x123456789ABCDEF0LL, 0xF0DEBC9A78563412LL)) + return 1; + if (test__bswapdi2(0x0000000100000002LL, 0x0200000001000000LL)) + return 1; + return 0; } diff --git a/test/builtins/Unit/bswapsi2_test.c b/test/builtins/Unit/bswapsi2_test.c index c32cbb442199..899c251d9581 100644 --- a/test/builtins/Unit/bswapsi2_test.c +++ b/test/builtins/Unit/bswapsi2_test.c @@ -13,34 +13,25 @@ // //===----------------------------------------------------------------------===// -#include +#include #include #include -#include - +#include extern uint32_t __bswapsi2(uint32_t); -#if __arm__ -int test__bswapsi2(uint32_t a, uint32_t expected) -{ - uint32_t actual = __bswapsi2(a); - if (actual != expected) - printf("error in test__bswapsi2(0x%0X) = 0x%0X, expected 0x%0X\n", - a, actual, expected); - return actual != expected; +int test__bswapsi2(uint32_t a, uint32_t expected) { + uint32_t actual = __bswapsi2(a); + if (actual != expected) + printf("error in test__bswapsi2(0x%0X) = 0x%0X, expected 0x%0X\n", a, + actual, expected); + return actual != expected; } -#endif -int main() -{ -#if __arm__ - if (test__bswapsi2(0x12345678, 0x78563412)) - return 1; - if (test__bswapsi2(0x00000001, 0x01000000)) - return 1; -#else - printf("skipped\n"); -#endif - return 0; +int main() { + if (test__bswapsi2(0x12345678, 0x78563412)) + return 1; + if (test__bswapsi2(0x00000001, 0x01000000)) + return 1; + return 0; } diff --git a/test/lsan/TestCases/many_tls_keys.cc b/test/lsan/TestCases/many_tls_keys.cc new file mode 100644 index 000000000000..5b5d692a5901 --- /dev/null +++ b/test/lsan/TestCases/many_tls_keys.cc @@ -0,0 +1,97 @@ +// Test that lsan handles tls correctly for many threads +// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: %clangxx_lsan %s -DUSE_THREAD -o %t-thread +// RUN: %clangxx_lsan %s -DUSE_PTHREAD -o %t-pthread +// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t-thread 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t-thread 2>&1 +// RUN: %env_lsan_opts="" %run %t-thread 2>&1 +// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t-pthread 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t-pthread 2>&1 +// RUN: %env_lsan_opts="" %run %t-pthread 2>&1 + +// Patch r303906 did not fix all the problems. +// UNSUPPORTED: arm-linux,armhf-linux + +#include +#include +#include +#include +#include + +static const int NUM_THREADS = 10; + +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +int finished = 0; + +#if USE_THREAD +__thread void *ptr1; +__thread void *ptr2; +__thread void *ptr3; +__thread void *ptr4; +__thread void *ptr5; + +void alloc() { + ptr1 = malloc(1111); + ptr2 = malloc(2222); + ptr3 = malloc(3333); + ptr4 = malloc(4444); + ptr5 = malloc(5555); +} + +#elif USE_PTHREAD +// We won't be able to create the maximum number of keys, due to other users +// of the tls, but we'll use as many keys as we can before failing to create +// a new key. +pthread_key_t keys[PTHREAD_KEYS_MAX]; +static const int PTHREAD_KEY_INVALID = 0xffffffff; + +void alloc() { + for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) { + void *ptr = malloc(123); + if ((keys[i] == PTHREAD_KEY_INVALID) || pthread_setspecific(keys[i], ptr)) { + free(ptr); + break; + } + } +} + +void pthread_destructor(void *arg) { + assert(0 && "pthread destructors shouldn't be called"); +} +#endif + +void *thread_start(void *arg) { + alloc(); + + pthread_mutex_lock(&mutex); + finished++; + pthread_mutex_unlock(&mutex); + + // don't exit, to intentionally leak tls data + while (1) + sleep(100); +} + +int main() { +#if USE_PTHREAD + for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) { + if (pthread_key_create(&keys[i], pthread_destructor)) { + keys[i] = PTHREAD_KEY_INVALID; + break; + } + } +#endif + + pthread_t thread[NUM_THREADS]; + for (int i = 0; i < NUM_THREADS; ++i) { + assert(0 == pthread_create(&thread[i], 0, thread_start, 0)); + } + // spin until all threads have finished + while (finished < NUM_THREADS) + sleep(1); + exit(0); +} + +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: diff --git a/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc b/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc index 92557b7592cb..b7e8721a1b9e 100644 --- a/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc +++ b/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc @@ -8,8 +8,12 @@ #include #include +// On powerpc64be semval_t must be 64 bits even with "old" versions of glibc. +#if __PPC64__ && __BIG_ENDIAN__ +typedef uint64_t semval_t; + // This condition needs to correspond to __HAVE_64B_ATOMICS macro in glibc. -#if (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ +#elif (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ defined(__s390x__) || defined(__sparc64__) || defined(__alpha__) || \ defined(__ia64__) || defined(__m68k__)) && __GLIBC_PREREQ(2, 21) typedef uint64_t semval_t; diff --git a/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc index 643fb48ae773..51e8bdb6e95d 100644 --- a/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc +++ b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0 allow_user_segv_handler=1" %run %t 2>&1 | FileCheck %s +// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0" %run %t 2>&1 | FileCheck %s // JVM uses SEGV to preempt threads. All threads do a load from a known address // periodically. When runtime needs to preempt threads, it unmaps the page. diff --git a/test/ubsan/TestCases/Integer/negate-overflow.cpp b/test/ubsan/TestCases/Integer/negate-overflow.cpp index 628291eb4b95..72438d3fba7f 100644 --- a/test/ubsan/TestCases/Integer/negate-overflow.cpp +++ b/test/ubsan/TestCases/Integer/negate-overflow.cpp @@ -6,7 +6,9 @@ int main() { // CHECKU: negate-overflow.cpp:[[@LINE+2]]:3: runtime error: negation of 2147483648 cannot be represented in type 'unsigned int' // CHECKU-NOT: cast to an unsigned -unsigned(-0x7fffffff - 1); // ok - // CHECKS: negate-overflow.cpp:[[@LINE+2]]:10: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself + // CHECKS: negate-overflow.cpp:[[@LINE+2]]:3: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself // CHECKU-NOT: runtime error - return -(-0x7fffffff - 1); + -(-0x7fffffff - 1); + + return 0; } From 61b440f5005f0bf4e5864ba9cff4107ac56be404 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 29 May 2017 16:26:31 +0000 Subject: [PATCH 04/22] Vendor import of lldb trunk r304149: https://llvm.org/svn/llvm-project/lldb/trunk@304149 --- docs/lldb-gdb-remote.txt | 157 ++++++++++++ include/lldb/API/SBStructuredData.h | 61 ++++- include/lldb/API/SBTrace.h | 13 +- include/lldb/Core/StructuredData.h | 90 +++---- include/lldb/Core/StructuredDataImpl.h | 73 +++++- include/lldb/Core/TraceOptions.h | 5 +- include/lldb/Host/Editline.h | 12 +- .../lldb/Host/common/NativeProcessProtocol.h | 105 +++++++- include/lldb/Target/Process.h | 27 +- include/lldb/Utility/StringExtractor.h | 2 + include/lldb/lldb-enumerations.h | 12 + .../unwind_expression/TestUnwindExpression.py | 65 +++-- .../unwind_expression/main.cpp | 8 + .../thread/{ => num_threads}/Makefile | 2 +- .../{ => num_threads}/TestNumThreads.py | 0 .../thread/{ => num_threads}/main.cpp | 0 .../sbstructureddata/TestStructuredDataAPI.py | 206 +++++++++++++++ scripts/interface/SBStructuredData.i | 25 +- scripts/lldb.swig | 18 +- source/API/SBProcess.cpp | 5 +- source/API/SBStructuredData.cpp | 44 +++- source/API/SBThread.cpp | 11 +- source/API/SBTrace.cpp | 28 +- source/Commands/CommandObjectThread.cpp | 2 +- source/Core/FormatEntity.cpp | 12 +- source/Core/StructuredData.cpp | 4 +- source/Host/common/Editline.cpp | 8 +- .../RenderScriptx86ABIFixups.cpp | 7 +- .../Process/FreeBSD/ProcessMonitor.cpp | 4 + .../Process/NetBSD/NativeProcessNetBSD.cpp | 31 ++- .../Process/NetBSD/NativeProcessNetBSD.h | 2 + .../GDBRemoteCommunicationClient.cpp | 206 ++++++++++++++- .../gdb-remote/GDBRemoteCommunicationClient.h | 21 ++ .../GDBRemoteCommunicationServerLLGS.cpp | 241 ++++++++++++++++++ .../GDBRemoteCommunicationServerLLGS.h | 8 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 26 ++ .../Process/gdb-remote/ProcessGDBRemote.h | 16 ++ source/Target/Process.cpp | 137 +++++----- source/Target/Thread.cpp | 24 +- source/Utility/StringExtractor.cpp | 9 + source/Utility/StringExtractorGDBRemote.cpp | 10 + source/Utility/StringExtractorGDBRemote.h | 6 + .../GDBRemoteCommunicationClientTest.cpp | 226 ++++++++++++++++ .../Python/PythonDataObjectsTests.cpp | 9 +- 44 files changed, 1735 insertions(+), 243 deletions(-) rename packages/Python/lldbsuite/test/functionalities/thread/{ => num_threads}/Makefile (78%) rename packages/Python/lldbsuite/test/functionalities/thread/{ => num_threads}/TestNumThreads.py (100%) rename packages/Python/lldbsuite/test/functionalities/thread/{ => num_threads}/main.cpp (100%) create mode 100644 packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py diff --git a/docs/lldb-gdb-remote.txt b/docs/lldb-gdb-remote.txt index 80a44e866cab..a4427a70444d 100644 --- a/docs/lldb-gdb-remote.txt +++ b/docs/lldb-gdb-remote.txt @@ -208,6 +208,163 @@ This packet must be sent _prior_ to sending a "A" packet. send packet: QListThreadsInStopReply read packet: OK +//---------------------------------------------------------------------- +// jTraceStart: +// +// BRIEF +// Packet for starting trace of type lldb::TraceType. The following +// parameters should be appended to the packet formatted as a JSON +// dictionary, where the schematic for the JSON dictionary in terms of +// the recognized Keys is given below in the table. +// Different tracing types could require different custom parameters. +// Such custom tracing parameters if needed should be collectively +// specified in a JSON dictionary and the dictionary can be appended +// to this packet (as Value corresponding to "params"). Since sending +// JSON data over gdb-remote protocol has certain limitations, binary +// escaping convention should be used. +// +// Following is the list of parameters - +// +// Key Value (Integer) (O)Optional/ +// (except params which should be a (M)Mandatory +// JSON dictionary) +// ========== ==================================================== +// +// type The type of trace to start (see M +// lldb-enumerations for TraceType) +// +// buffersize The size of the buffer to allocate M +// for trace gathering. +// +// threadid The id of the thread to start tracing O +// on. +// +// metabuffersize The size of buffer to hold meta data O +// used for decoding the trace data. +// +// params Any parameters that are specific to O +// certain trace technologies should be +// collectively specified as a JSON +// dictionary +// ========== ==================================================== +// +// Each tracing instance is identified by a trace id which is returned +// as the reply to this packet. In case the tracing failed to begin an +// error code is returned instead. +//---------------------------------------------------------------------- + +send packet: jTraceStart:{"type":,"buffersize":}] +read packet: /E + +//---------------------------------------------------------------------- +// jTraceStop: +// +// BRIEF +// Stop tracing instance with trace id , of course trace +// needs to be started before. The following parameters should be +// formatted as a JSON dictionary to the packet. Since sending +// JSON data over gdb-remote protocol has certain limitations, binary +// escaping convention should be used. +// +// Following is the list of parameters - +// +// Key Value (Integer) (O)Optional/ +// (M)Mandatory +// ========== ==================================================== +// +// traceid The trace id of the tracing instance M +// +// threadid The id of the thread to stop tracing O +// on. Since could map to +// multiple trace instances (in case it +// maps to the complete process), the +// threadid of a particular thread could +// be appended as "threadid:;" +// to stop tracing on that thread. +// ========== ==================================================== +// +// An OK response is sent in case of success else an error code is +// returned. +//---------------------------------------------------------------------- + +send packet: jTraceStop:{"traceid":}] +read packet: /E + +//---------------------------------------------------------------------- +// jTraceBufferRead: +// +// BRIEF +// Packet for reading the trace for tracing instance , i.e the +// id obtained from StartTrace API. The following parameters should be +// formatted as a JSON dictionary to the packet. Since sending +// JSON data over gdb-remote protocol has certain limitations, binary +// escaping convention should be used. +// +// Following is the list of parameters - +// +// Key Value (Integer) (O)Optional/ +// (M)Mandatory +// ========== ==================================================== +// traceid The trace id of the tracing instance M +// +// offset The offset to start reading the data M +// from. +// +// buffersize The size of the data intended to read. M +// +// threadid The id of the thread to retrieve data O +// from. +// ========== ==================================================== +// +// The trace data is sent as raw binary data if the read was successful +// else an error code is sent. +//---------------------------------------------------------------------- + +send packet: jTraceBufferRead:{"traceid":,"offset":,"buffersize":}] +read packet: /E + +//---------------------------------------------------------------------- +// jTraceMetaRead: +// +// BRIEF +// Similar Packet as above except it reads meta data. +//---------------------------------------------------------------------- + +/---------------------------------------------------------------------- +// jTraceConfigRead: +// +// BRIEF +// Request the trace configuration for the tracing instance with id +// . +// +// Following is the list of parameters - +// +// Key Value (Integer) (O)Optional/ +// (M)Mandatory +// ========== ==================================================== +// traceid The trace id of the tracing instance M +// +// threadid The id of the thread to obtain trace O +// configuration from. Since +// could map to multiple trace instances +// (in case it maps to the complete +// process), the threadid of a particular +// thread could be appended as +// "threadid:;" to obtain the +// trace configuration of that thread. +// ========== ==================================================== +// +// In the response packet the trace configuration is sent as text, +// formatted as a JSON dictionary. Since sending JSON data over +// gdb-remote protocol has certain limitations, binary escaping +// convention is used. +// In case the trace instance with the was not found, an +// error code is returned. +//---------------------------------------------------------------------- + +send packet: jTraceConfigRead:{"traceid":} +read packet: {"conf1":,"conf2":,"params":{"paramName":paramValue}]}];/E + //---------------------------------------------------------------------- // "qRegisterInfo" // diff --git a/include/lldb/API/SBStructuredData.h b/include/lldb/API/SBStructuredData.h index 5fb5d3be65ad..f7a6469bb8de 100644 --- a/include/lldb/API/SBStructuredData.h +++ b/include/lldb/API/SBStructuredData.h @@ -37,11 +37,70 @@ class SBStructuredData { lldb::SBError GetDescription(lldb::SBStream &stream) const; + //------------------------------------------------------------------ + /// Return the type of data in this data structure + //------------------------------------------------------------------ + lldb::StructuredDataType GetType() const; + + //------------------------------------------------------------------ + /// Return the size (i.e. number of elements) in this data structure + /// if it is an array or dictionary type. For other types, 0 will be + // returned. + //------------------------------------------------------------------ + size_t GetSize() const; + + //------------------------------------------------------------------ + /// Return the value corresponding to a key if this data structure + /// is a dictionary type. + //------------------------------------------------------------------ + lldb::SBStructuredData GetValueForKey(const char *key) const; + + //------------------------------------------------------------------ + /// Return the value corresponding to an index if this data structure + /// is array. + //------------------------------------------------------------------ + lldb::SBStructuredData GetItemAtIndex(size_t idx) const; + + //------------------------------------------------------------------ + /// Return the integer value if this data structure is an integer type. + //------------------------------------------------------------------ + uint64_t GetIntegerValue(uint64_t fail_value = 0) const; + + //------------------------------------------------------------------ + /// Return the floating point value if this data structure is a floating + /// type. + //------------------------------------------------------------------ + double GetFloatValue(double fail_value = 0.0) const; + + //------------------------------------------------------------------ + /// Return the boolean value if this data structure is a boolean type. + //------------------------------------------------------------------ + bool GetBooleanValue(bool fail_value = false) const; + + //------------------------------------------------------------------ + /// Provides the string value if this data structure is a string type. + /// + /// @param[out] dst + /// pointer where the string value will be written. In case it is null, + /// nothing will be written at @dst. + /// + /// @param[in] dst_len + /// max number of characters that can be written at @dst. In case it is + /// zero, nothing will be written at @dst. If this length is not enough + /// to write the complete string value, (dst_len-1) bytes of the string + /// value will be written at @dst followed by a null character. + /// + /// @return + /// Returns the byte size needed to completely write the string value at + /// @dst in all cases. + //------------------------------------------------------------------ + size_t GetStringValue(char *dst, size_t dst_len) const; + protected: friend class SBTraceOptions; StructuredDataImplUP m_impl_up; }; -} +} // namespace lldb #endif /* SBStructuredData_h */ diff --git a/include/lldb/API/SBTrace.h b/include/lldb/API/SBTrace.h index e29a5db7cc46..244a01e5ce11 100644 --- a/include/lldb/API/SBTrace.h +++ b/include/lldb/API/SBTrace.h @@ -40,7 +40,7 @@ class LLDB_API SBTrace { /// /// @param[in] thread_id /// Tracing could be started for the complete process or a - /// single thread, in the first case the uid obtained would + /// single thread, in the first case the traceid obtained would /// map to all the threads existing within the process and the /// ones spawning later. The thread_id parameter can be used in /// such a scenario to select the trace data for a specific @@ -68,16 +68,17 @@ class LLDB_API SBTrace { /// An error explaining what went wrong. /// /// @param[in] thread_id - /// The user id could map to a tracing instance for a thread + /// The trace id could map to a tracing instance for a thread /// or could also map to a group of threads being traced with /// the same trace options. A thread_id is normally optional /// except in the case of tracing a complete process and tracing /// needs to switched off on a particular thread. /// A situation could occur where initially a thread (lets say - /// thread A) is being individually traced with a particular uid - /// and then tracing is started on the complete process, in this - /// case thread A will continue without any change. All newly - /// spawned threads would be traced with the uid of the process. + /// thread A) is being individually traced with a particular + /// trace id and then tracing is started on the complete + /// process, in this case thread A will continue without any + /// change. All newly spawned threads would be traced with the + /// trace id of the process. /// Now if the StopTrace API is called for the whole process, /// thread A will not be stopped and must be stopped separately. //------------------------------------------------------------------ diff --git a/include/lldb/Core/StructuredData.h b/include/lldb/Core/StructuredData.h index 6cb78dc48ab5..39c2f04bb382 100644 --- a/include/lldb/Core/StructuredData.h +++ b/include/lldb/Core/StructuredData.h @@ -13,7 +13,8 @@ #include "llvm/ADT/StringRef.h" #include "lldb/Utility/ConstString.h" -#include "lldb/Utility/FileSpec.h" // for FileSpec +#include "lldb/Utility/FileSpec.h" // for FileSpec +#include "lldb/lldb-enumerations.h" // for StructuredDataType #include #include @@ -71,46 +72,38 @@ class StructuredData { typedef std::shared_ptr DictionarySP; typedef std::shared_ptr GenericSP; - enum class Type { - eTypeInvalid = -1, - eTypeNull = 0, - eTypeGeneric, - eTypeArray, - eTypeInteger, - eTypeFloat, - eTypeBoolean, - eTypeString, - eTypeDictionary - }; - class Object : public std::enable_shared_from_this { public: - Object(Type t = Type::eTypeInvalid) : m_type(t) {} + Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid) + : m_type(t) {} virtual ~Object() = default; virtual bool IsValid() const { return true; } - virtual void Clear() { m_type = Type::eTypeInvalid; } + virtual void Clear() { m_type = lldb::eStructuredDataTypeInvalid; } - Type GetType() const { return m_type; } + lldb::StructuredDataType GetType() const { return m_type; } - void SetType(Type t) { m_type = t; } + void SetType(lldb::StructuredDataType t) { m_type = t; } Array *GetAsArray() { - return ((m_type == Type::eTypeArray) ? static_cast(this) - : nullptr); - } - - Dictionary *GetAsDictionary() { - return ((m_type == Type::eTypeDictionary) - ? static_cast(this) + return ((m_type == lldb::eStructuredDataTypeArray) + ? static_cast(this) : nullptr); } + Dictionary *GetAsDictionary() { + return ( + (m_type == lldb::eStructuredDataTypeDictionary) + ? static_cast(this) + : nullptr); + } + Integer *GetAsInteger() { - return ((m_type == Type::eTypeInteger) ? static_cast(this) - : nullptr); + return ((m_type == lldb::eStructuredDataTypeInteger) + ? static_cast(this) + : nullptr); } uint64_t GetIntegerValue(uint64_t fail_value = 0) { @@ -119,8 +112,9 @@ class StructuredData { } Float *GetAsFloat() { - return ((m_type == Type::eTypeFloat) ? static_cast(this) - : nullptr); + return ((m_type == lldb::eStructuredDataTypeFloat) + ? static_cast(this) + : nullptr); } double GetFloatValue(double fail_value = 0.0) { @@ -129,8 +123,9 @@ class StructuredData { } Boolean *GetAsBoolean() { - return ((m_type == Type::eTypeBoolean) ? static_cast(this) - : nullptr); + return ((m_type == lldb::eStructuredDataTypeBoolean) + ? static_cast(this) + : nullptr); } bool GetBooleanValue(bool fail_value = false) { @@ -139,8 +134,9 @@ class StructuredData { } String *GetAsString() { - return ((m_type == Type::eTypeString) ? static_cast(this) - : nullptr); + return ((m_type == lldb::eStructuredDataTypeString) + ? static_cast(this) + : nullptr); } llvm::StringRef GetStringValue(const char *fail_value = nullptr) { @@ -152,8 +148,9 @@ class StructuredData { } Generic *GetAsGeneric() { - return ((m_type == Type::eTypeGeneric) ? static_cast(this) - : nullptr); + return ((m_type == lldb::eStructuredDataTypeGeneric) + ? static_cast(this) + : nullptr); } ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path); @@ -163,12 +160,12 @@ class StructuredData { virtual void Dump(Stream &s, bool pretty_print = true) const = 0; private: - Type m_type; + lldb::StructuredDataType m_type; }; class Array : public Object { public: - Array() : Object(Type::eTypeArray) {} + Array() : Object(lldb::eStructuredDataTypeArray) {} ~Array() override = default; @@ -288,7 +285,8 @@ class StructuredData { class Integer : public Object { public: - Integer(uint64_t i = 0) : Object(Type::eTypeInteger), m_value(i) {} + Integer(uint64_t i = 0) + : Object(lldb::eStructuredDataTypeInteger), m_value(i) {} ~Integer() override = default; @@ -304,7 +302,8 @@ class StructuredData { class Float : public Object { public: - Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {} + Float(double d = 0.0) : Object(lldb::eStructuredDataTypeFloat), + m_value(d) {} ~Float() override = default; @@ -320,7 +319,8 @@ class StructuredData { class Boolean : public Object { public: - Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {} + Boolean(bool b = false) : Object(lldb::eStructuredDataTypeBoolean), + m_value(b) {} ~Boolean() override = default; @@ -336,9 +336,10 @@ class StructuredData { class String : public Object { public: - String() : Object(Type::eTypeString) {} + String() : Object(lldb::eStructuredDataTypeString) {} explicit String(llvm::StringRef S) - : Object(Type::eTypeString), m_value(S) {} + : Object(lldb::eStructuredDataTypeString), + m_value(S) {} void SetValue(llvm::StringRef S) { m_value = S; } @@ -352,7 +353,8 @@ class StructuredData { class Dictionary : public Object { public: - Dictionary() : Object(Type::eTypeDictionary), m_dict() {} + Dictionary() : Object(lldb::eStructuredDataTypeDictionary), + m_dict() {} ~Dictionary() override = default; @@ -522,7 +524,7 @@ class StructuredData { class Null : public Object { public: - Null() : Object(Type::eTypeNull) {} + Null() : Object(lldb::eStructuredDataTypeNull) {} ~Null() override = default; @@ -534,7 +536,7 @@ class StructuredData { class Generic : public Object { public: explicit Generic(void *object = nullptr) - : Object(Type::eTypeGeneric), m_object(object) {} + : Object(lldb::eStructuredDataTypeGeneric), m_object(object) {} void SetValue(void *value) { m_object = value; } diff --git a/include/lldb/Core/StructuredDataImpl.h b/include/lldb/Core/StructuredDataImpl.h index 81d59f83ac3d..92f0417b354a 100644 --- a/include/lldb/Core/StructuredDataImpl.h +++ b/include/lldb/Core/StructuredDataImpl.h @@ -15,7 +15,9 @@ #include "lldb/Target/StructuredDataPlugin.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" +#include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" +#include "llvm/ADT/StringRef.h" #pragma mark-- #pragma mark StructuredDataImpl @@ -78,18 +80,77 @@ class StructuredDataImpl { return plugin_sp->GetDescription(m_data_sp, stream); } - StructuredData::ObjectSP GetObjectSP() { - return m_data_sp; + StructuredData::ObjectSP GetObjectSP() { return m_data_sp; } + + void SetObjectSP(const StructuredData::ObjectSP &obj) { m_data_sp = obj; } + + lldb::StructuredDataType GetType() const { + return (m_data_sp ? m_data_sp->GetType() : + lldb::eStructuredDataTypeInvalid); } - void SetObjectSP(const StructuredData::ObjectSP &obj) { - m_data_sp = obj; + size_t GetSize() const { + if (!m_data_sp) + return 0; + + if (m_data_sp->GetType() == lldb::eStructuredDataTypeDictionary) { + auto dict = m_data_sp->GetAsDictionary(); + return (dict->GetSize()); + } else if (m_data_sp->GetType() == lldb::eStructuredDataTypeArray) { + auto array = m_data_sp->GetAsArray(); + return (array->GetSize()); + } else + return 0; + } + + StructuredData::ObjectSP GetValueForKey(const char *key) const { + if (m_data_sp) { + auto dict = m_data_sp->GetAsDictionary(); + if (dict) + return dict->GetValueForKey(llvm::StringRef(key)); + } + return StructuredData::ObjectSP(); + } + + StructuredData::ObjectSP GetItemAtIndex(size_t idx) const { + if (m_data_sp) { + auto array = m_data_sp->GetAsArray(); + if (array) + return array->GetItemAtIndex(idx); + } + return StructuredData::ObjectSP(); + } + + uint64_t GetIntegerValue(uint64_t fail_value = 0) const { + return (m_data_sp ? m_data_sp->GetIntegerValue(fail_value) : fail_value); + } + + double GetFloatValue(double fail_value = 0.0) const { + return (m_data_sp ? m_data_sp->GetFloatValue(fail_value) : fail_value); + } + + bool GetBooleanValue(bool fail_value = false) const { + return (m_data_sp ? m_data_sp->GetBooleanValue(fail_value) : fail_value); + } + + size_t GetStringValue(char *dst, size_t dst_len) const { + if (!m_data_sp) + return 0; + + llvm::StringRef result = m_data_sp->GetStringValue(); + if (result.empty()) + return 0; + + if (!dst || !dst_len) { + char s[1]; + return (::snprintf(s, 1, "%s", result.data())); + } + return (::snprintf(dst, dst_len, "%s", result.data())); } private: - lldb::StructuredDataPluginWP m_plugin_wp; StructuredData::ObjectSP m_data_sp; }; -} +} // namespace lldb_private #endif diff --git a/include/lldb/Core/TraceOptions.h b/include/lldb/Core/TraceOptions.h index e875a531e870..91f48915c94b 100644 --- a/include/lldb/Core/TraceOptions.h +++ b/include/lldb/Core/TraceOptions.h @@ -18,8 +18,7 @@ namespace lldb_private { class TraceOptions { public: - TraceOptions() - : m_trace_params(new StructuredData::Dictionary()) {} + TraceOptions() : m_trace_params(new StructuredData::Dictionary()) {} const StructuredData::DictionarySP &getTraceParams() const { return m_trace_params; @@ -43,7 +42,7 @@ class TraceOptions { void setThreadID(lldb::tid_t thread_id) { m_thread_id = thread_id; } - lldb::tid_t getThreadID() { return m_thread_id; } + lldb::tid_t getThreadID() const { return m_thread_id; } private: lldb::TraceType m_type; diff --git a/include/lldb/Host/Editline.h b/include/lldb/Host/Editline.h index 2b1a8e047261..0b75e9c923ca 100644 --- a/include/lldb/Host/Editline.h +++ b/include/lldb/Host/Editline.h @@ -82,8 +82,14 @@ using EditLineStringStreamType = std::stringstream; using EditLineCharType = char; #endif +#ifdef EL_CLIENTDATA /* editline with wide support + wide char read function */ +using EditLineGetCharType = wchar_t; +#else +using EditLineGetCharType = char; +#endif + typedef int (*EditlineGetCharCallbackType)(::EditLine *editline, - EditLineCharType *c); + EditLineGetCharType *c); typedef unsigned char (*EditlineCommandCallbackType)(::EditLine *editline, int ch); typedef const char *(*EditlinePromptCallbackType)(::EditLine *editline); @@ -270,7 +276,7 @@ class Editline { /// Character reading implementation for EditLine that supports our multi-line /// editing trickery. - int GetCharacter(EditLineCharType *c); + int GetCharacter(EditLineGetCharType *c); /// Prompt implementation for EditLine. const char *Prompt(); @@ -323,7 +329,7 @@ class Editline { /// single or multi-line editing. void ConfigureEditor(bool multiline); - bool CompleteCharacter(char ch, EditLineCharType &out); + bool CompleteCharacter(char ch, EditLineGetCharType &out); private: #if LLDB_EDITLINE_USE_WCHAR diff --git a/include/lldb/Host/common/NativeProcessProtocol.h b/include/lldb/Host/common/NativeProcessProtocol.h index 388edef0578d..55eca0fa0b65 100644 --- a/include/lldb/Host/common/NativeProcessProtocol.h +++ b/include/lldb/Host/common/NativeProcessProtocol.h @@ -10,6 +10,7 @@ #ifndef liblldb_NativeProcessProtocol_h_ #define liblldb_NativeProcessProtocol_h_ +#include "lldb/Core/TraceOptions.h" #include "lldb/Host/MainLoop.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-private-forward.h" @@ -308,6 +309,108 @@ class NativeProcessProtocol static Status Attach(lldb::pid_t pid, NativeDelegate &native_delegate, MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + //------------------------------------------------------------------ + /// StartTracing API for starting a tracing instance with the + /// TraceOptions on a specific thread or process. + /// + /// @param[in] config + /// The configuration to use when starting tracing. + /// + /// @param[out] error + /// Status indicates what went wrong. + /// + /// @return + /// The API returns a user_id which can be used to get trace + /// data, trace configuration or stopping the trace instance. + /// The user_id is a key to identify and operate with a tracing + /// instance. It may refer to the complete process or a single + /// thread. + //------------------------------------------------------------------ + virtual lldb::user_id_t StartTrace(const TraceOptions &config, + Status &error) { + error.SetErrorString("Not implemented"); + return LLDB_INVALID_UID; + } + + //------------------------------------------------------------------ + /// StopTracing API as the name suggests stops a tracing instance. + /// + /// @param[in] uid + /// The user id of the trace intended to be stopped. Now a + /// user_id may map to multiple threads in which case this API + /// could be used to stop the tracing for a specific thread by + /// supplying its thread id. + /// + /// @param[in] thread + /// Thread is needed when the complete process is being traced + /// and the user wishes to stop tracing on a particular thread. + /// + /// @return + /// Status indicating what went wrong. + //------------------------------------------------------------------ + virtual Status StopTrace(lldb::user_id_t uid, + lldb::tid_t thread = LLDB_INVALID_THREAD_ID) { + return Status("Not implemented"); + } + + //------------------------------------------------------------------ + /// This API provides the trace data collected in the form of raw + /// data. + /// + /// @param[in] uid thread + /// The uid and thread provide the context for the trace + /// instance. + /// + /// @param[in] buffer + /// The buffer provides the destination buffer where the trace + /// data would be read to. The buffer should be truncated to the + /// filled length by this function. + /// + /// @param[in] offset + /// There is possibility to read partially the trace data from + /// a specified offset where in such cases the buffer provided + /// may be smaller than the internal trace collection container. + /// + /// @return + /// The size of the data actually read. + //------------------------------------------------------------------ + virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread, + llvm::MutableArrayRef &buffer, + size_t offset = 0) { + return Status("Not implemented"); + } + + //------------------------------------------------------------------ + /// Similar API as above except it aims to provide any extra data + /// useful for decoding the actual trace data. + //------------------------------------------------------------------ + virtual Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread, + llvm::MutableArrayRef &buffer, + size_t offset = 0) { + return Status("Not implemented"); + } + + //------------------------------------------------------------------ + /// API to query the TraceOptions for a given user id + /// + /// @param[in] uid + /// The user id of the tracing instance. + /// + /// @param[in] config + /// The thread id of the tracing instance, in case configuration + /// for a specific thread is needed should be specified in the + /// config. + /// + /// @param[out] error + /// Status indicates what went wrong. + /// + /// @param[out] config + /// The actual configuration being used for tracing. + //------------------------------------------------------------------ + virtual Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &config) { + return Status("Not implemented"); + } + protected: lldb::pid_t m_pid; @@ -381,6 +484,6 @@ class NativeProcessProtocol private: void SynchronouslyNotifyProcessStateChanged(lldb::StateType state); }; -} +} // namespace lldb_private #endif // #ifndef liblldb_NativeProcessProtocol_h_ diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index d2ab85d1652a..dbf6cba09f43 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -2781,7 +2781,7 @@ class Process : public std::enable_shared_from_this, /// GetTraceConfig should supply the actual used trace /// configuration. //------------------------------------------------------------------ - virtual lldb::user_id_t StartTrace(lldb::TraceOptionsSP &options, + virtual lldb::user_id_t StartTrace(const TraceOptions &options, Status &error) { error.SetErrorString("Not implemented"); return LLDB_INVALID_UID; @@ -2796,9 +2796,8 @@ class Process : public std::enable_shared_from_this, /// In the other case that tracing on an individual thread needs /// to be stopped a thread_id can be supplied. //------------------------------------------------------------------ - virtual void StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id, - Status &error) { - error.SetErrorString("Not implemented"); + virtual Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) { + return Status("Not implemented"); } //------------------------------------------------------------------ @@ -2809,21 +2808,19 @@ class Process : public std::enable_shared_from_this, /// may not. The thread_id should be used to select a particular /// thread for trace extraction. //------------------------------------------------------------------ - virtual size_t GetData(lldb::user_id_t uid, lldb::tid_t thread_id, - Status &error, void *buf, size_t size, + virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, size_t offset = 0) { - error.SetErrorString("Not implemented"); - return 0; + return Status("Not implemented"); } //------------------------------------------------------------------ /// Similar API as above except for obtaining meta data //------------------------------------------------------------------ - virtual size_t GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, - Status &error, void *buf, size_t size, + virtual Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, size_t offset = 0) { - error.SetErrorString("Not implemented"); - return 0; + return Status("Not implemented"); } //------------------------------------------------------------------ @@ -2835,10 +2832,8 @@ class Process : public std::enable_shared_from_this, /// configuration used by a specific thread. The thread_id specified /// should also match the uid otherwise an error will be returned. //------------------------------------------------------------------ - virtual void GetTraceConfig(lldb::user_id_t uid, Status &error, - lldb::TraceOptionsSP &options) { - error.SetErrorString("Not implemented"); - return; + virtual Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) { + return Status("Not implemented"); } protected: diff --git a/include/lldb/Utility/StringExtractor.h b/include/lldb/Utility/StringExtractor.h index 40c1ef79cffb..311cec87e695 100644 --- a/include/lldb/Utility/StringExtractor.h +++ b/include/lldb/Utility/StringExtractor.h @@ -111,6 +111,8 @@ class StringExtractor { size_t GetHexByteStringTerminatedBy(std::string &str, char terminator); + bool ConsumeFront(const llvm::StringRef &str); + const char *Peek() { if (m_index < m_packet.size()) return m_packet.c_str() + m_index; diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h index ad10bbba1a57..f62b3cc0b19b 100644 --- a/include/lldb/lldb-enumerations.h +++ b/include/lldb/lldb-enumerations.h @@ -725,6 +725,18 @@ enum TraceType { eTraceTypeProcessorTrace }; +enum StructuredDataType { + eStructuredDataTypeInvalid = -1, + eStructuredDataTypeNull = 0, + eStructuredDataTypeGeneric, + eStructuredDataTypeArray, + eStructuredDataTypeInteger, + eStructuredDataTypeFloat, + eStructuredDataTypeBoolean, + eStructuredDataTypeString, + eStructuredDataTypeDictionary +}; + FLAGS_ENUM(TypeClass){ eTypeClassInvalid = (0u), eTypeClassArray = (1u << 0), eTypeClassBlockPointer = (1u << 1), eTypeClassBuiltin = (1u << 2), diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py index bfd6f4642c6c..9cc585b75aa1 100644 --- a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py +++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py @@ -18,15 +18,9 @@ class UnwindFromExpressionTest(TestBase): mydir = TestBase.compute_mydir(__file__) + main_spec = lldb.SBFileSpec("main.cpp", False) - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - - @add_test_categories(['pyapi']) - @expectedFailureAll(oslist=["windows"]) - def test_unwind_expression(self): - """Test unwinding from an expression.""" + def build_and_run_to_bkpt(self): self.build() exe = os.path.join(os.getcwd(), "a.out") @@ -35,9 +29,8 @@ def test_unwind_expression(self): self.assertTrue(target, VALID_TARGET) # Create the breakpoint. - main_spec = lldb.SBFileSpec("main.cpp", False) breakpoint = target.BreakpointCreateBySourceRegex( - "// Set a breakpoint here to get started", main_spec) + "// Set a breakpoint here to get started", self.main_spec) self.assertTrue(breakpoint, VALID_BREAKPOINT) # Launch the process, and do not stop at the entry point. @@ -52,24 +45,60 @@ def test_unwind_expression(self): "instead the actual state is: '%s'" % lldbutil.state_type_to_str(process.GetState())) - thread = lldbutil.get_one_thread_stopped_at_breakpoint( + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint( process, breakpoint) self.assertIsNotNone( - thread, "Expected one thread to be stopped at the breakpoint") + self.thread, "Expected one thread to be stopped at the breakpoint") + # Next set a breakpoint in this function, set up Expression options to stop on + # breakpoint hits, and call the function. + self.fun_bkpt = self.target().BreakpointCreateBySourceRegex( + "// Stop inside the function here.", self.main_spec) + self.assertTrue(self.fun_bkpt, VALID_BREAKPOINT) + + + @no_debug_info_test + @expectedFailureAll(bugnumber="llvm.org/pr33164") + def test_conditional_bktp(self): + """ + Test conditional breakpoint handling in the IgnoreBreakpoints = False case + """ + self.build_and_run_to_bkpt() + + self.fun_bkpt.SetCondition("0") # Should not get hit + options = lldb.SBExpressionOptions() + options.SetIgnoreBreakpoints(False) + options.SetUnwindOnError(False) + + main_frame = self.thread.GetFrameAtIndex(0) + val = main_frame.EvaluateExpression("second_function(47)", options) + self.assertTrue( + val.GetError().Success(), + "We did complete the execution.") + self.assertEquals(47, val.GetValueAsSigned()) + + + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"]) + def test_unwind_expression(self): + """Test unwinding from an expression.""" + self.build_and_run_to_bkpt() + + # Run test with varying one thread timeouts to also test the halting + # logic in the IgnoreBreakpoints = False case + self.do_unwind_test(self.thread, self.fun_bkpt, 1000) + self.do_unwind_test(self.thread, self.fun_bkpt, 100000) + + def do_unwind_test(self, thread, bkpt, timeout): # # Use Python API to evaluate expressions while stopped in a stack frame. # main_frame = thread.GetFrameAtIndex(0) - # Next set a breakpoint in this function, set up Expression options to stop on - # breakpoint hits, and call the function. - fun_bkpt = target.BreakpointCreateBySourceRegex( - "// Stop inside the function here.", main_spec) - self.assertTrue(fun_bkpt, VALID_BREAKPOINT) options = lldb.SBExpressionOptions() options.SetIgnoreBreakpoints(False) options.SetUnwindOnError(False) + options.SetOneThreadTimeoutInMicroSeconds(timeout) val = main_frame.EvaluateExpression("a_function_to_call()", options) @@ -82,7 +111,7 @@ def test_unwind_expression(self): "And the reason was right.") thread = lldbutil.get_one_thread_stopped_at_breakpoint( - process, fun_bkpt) + self.process(), bkpt) self.assertTrue( thread.IsValid(), "We are indeed stopped at our breakpoint") diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp b/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp index e93c34a30b03..56b06f31ecca 100644 --- a/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp +++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp @@ -7,8 +7,16 @@ a_function_to_call() return static_value; } +int second_function(int x){ + for(int i=0; i<10; ++i) { + a_function_to_call(); + } + return x; +} + int main (int argc, char const *argv[]) { a_function_to_call(); // Set a breakpoint here to get started + second_function(1); return 0; } diff --git a/packages/Python/lldbsuite/test/functionalities/thread/Makefile b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile similarity index 78% rename from packages/Python/lldbsuite/test/functionalities/thread/Makefile rename to packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile index 644e2971a2c1..67aa16625bff 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/Makefile +++ b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile @@ -1,4 +1,4 @@ -LEVEL = ../../make +LEVEL = ../../../make CXX_SOURCES := main.cpp ENABLE_THREADS := YES diff --git a/packages/Python/lldbsuite/test/functionalities/thread/TestNumThreads.py b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py similarity index 100% rename from packages/Python/lldbsuite/test/functionalities/thread/TestNumThreads.py rename to packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py diff --git a/packages/Python/lldbsuite/test/functionalities/thread/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp similarity index 100% rename from packages/Python/lldbsuite/test/functionalities/thread/main.cpp rename to packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp diff --git a/packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py b/packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py new file mode 100644 index 000000000000..f19d01d5e695 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py @@ -0,0 +1,206 @@ +""" +Test some SBStructuredData API. +""" + +from __future__ import print_function + +import os +import re +import time + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestStructuredDataAPI(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def test(self): + self.structured_data_api_test() + + def setUp(self): + TestBase.setUp(self) + + @add_test_categories(['pyapi']) + def structured_data_api_test(self): + error = lldb.SBError() + s = lldb.SBStream() + s.Print( + "{\"key_dict\":{\"key_string\":\"STRING\",\"key_int\":3,\"key_float\":2.99,\"key_bool\":true,\"key_array\":[\"23\",\"arr\"]}}") + example = lldb.SBStructuredData() + + # Check SetFromJSON API for dictionaries, integers, floating point + # values, strings and arrays + error = example.SetFromJSON(s) + if not error.Success(): + self.fail("FAILED: " + error.GetCString()) + + # Tests for invalid data type + self.invalid_struct_test(example) + + dict_struct = lldb.SBStructuredData() + dict_struct = example.GetValueForKey("key_dict") + + # Tests for dictionary data type + self.dictionary_struct_test(example) + + # Tests for string data type + self.string_struct_test(dict_struct) + + # Tests for integer data type + self.int_struct_test(dict_struct) + + # Tests for floating point data type + self.double_struct_test(dict_struct) + + # Tests for boolean data type + self.bool_struct_test(dict_struct) + + # Tests for array data type + self.array_struct_test(dict_struct) + + def invalid_struct_test(self, example): + invalid_struct = lldb.SBStructuredData() + invalid_struct = example.GetValueForKey("invalid_key") + if invalid_struct.IsValid(): + self.fail("An invalid object should have been returned") + + # Check Type API + if not invalid_struct.GetType() == lldb.eStructuredDataTypeInvalid: + self.fail("Wrong type returned: " + str(invalid_struct.GetType())) + + def dictionary_struct_test(self, example): + # Check API returning a valid SBStructuredData of 'dictionary' type + dict_struct = lldb.SBStructuredData() + dict_struct = example.GetValueForKey("key_dict") + if not dict_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not dict_struct.GetType() == lldb.eStructuredDataTypeDictionary: + self.fail("Wrong type returned: " + str(dict_struct.GetType())) + + # Check Size API for 'dictionary' type + if not dict_struct.GetSize() == 5: + self.fail("Wrong no of elements returned: " + + str(dict_struct.GetSize())) + + def string_struct_test(self, dict_struct): + string_struct = lldb.SBStructuredData() + string_struct = dict_struct.GetValueForKey("key_string") + if not string_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not string_struct.GetType() == lldb.eStructuredDataTypeString: + self.fail("Wrong type returned: " + str(string_struct.GetType())) + + # Check API returning 'string' value + output = string_struct.GetStringValue(25) + if not "STRING" in output: + self.fail("wrong output: " + output) + + # Calling wrong API on a SBStructuredData + # (e.g. getting an integer from a string type structure) + output = string_struct.GetIntegerValue() + if output: + self.fail( + "Valid integer value " + + str(output) + + " returned for a string object") + + def int_struct_test(self, dict_struct): + # Check a valid SBStructuredData containing an 'integer' by + int_struct = lldb.SBStructuredData() + int_struct = dict_struct.GetValueForKey("key_int") + if not int_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not int_struct.GetType() == lldb.eStructuredDataTypeInteger: + self.fail("Wrong type returned: " + str(int_struct.GetType())) + + # Check API returning 'integer' value + output = int_struct.GetIntegerValue() + if not output == 3: + self.fail("wrong output: " + str(output)) + + # Calling wrong API on a SBStructuredData + # (e.g. getting a string value from an integer type structure) + output = int_struct.GetStringValue(25) + if output: + self.fail( + "Valid string " + + output + + " returned for an integer object") + + def double_struct_test(self, dict_struct): + floating_point_struct = lldb.SBStructuredData() + floating_point_struct = dict_struct.GetValueForKey("key_float") + if not floating_point_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not floating_point_struct.GetType() == lldb.eStructuredDataTypeFloat: + self.fail("Wrong type returned: " + + str(floating_point_struct.GetType())) + + # Check API returning 'double' value + output = floating_point_struct.GetFloatValue() + if not output == 2.99: + self.fail("wrong output: " + str(output)) + + def bool_struct_test(self, dict_struct): + bool_struct = lldb.SBStructuredData() + bool_struct = dict_struct.GetValueForKey("key_bool") + if not bool_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not bool_struct.GetType() == lldb.eStructuredDataTypeBoolean: + self.fail("Wrong type returned: " + str(bool_struct.GetType())) + + # Check API returning 'bool' value + output = bool_struct.GetBooleanValue() + if not output: + self.fail("wrong output: " + str(output)) + + def array_struct_test(self, dict_struct): + # Check API returning a valid SBStructuredData of 'array' type + array_struct = lldb.SBStructuredData() + array_struct = dict_struct.GetValueForKey("key_array") + if not array_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not array_struct.GetType() == lldb.eStructuredDataTypeArray: + self.fail("Wrong type returned: " + str(array_struct.GetType())) + + # Check Size API for 'array' type + if not array_struct.GetSize() == 2: + self.fail("Wrong no of elements returned: " + + str(array_struct.GetSize())) + + # Check API returning a valid SBStructuredData for different 'array' + # indices + string_struct = array_struct.GetItemAtIndex(0) + if not string_struct.IsValid(): + self.fail("A valid object should have been returned") + if not string_struct.GetType() == lldb.eStructuredDataTypeString: + self.fail("Wrong type returned: " + str(string_struct.GetType())) + output = string_struct.GetStringValue(5) + if not output == "23": + self.fail("wrong output: " + str(output)) + + string_struct = array_struct.GetItemAtIndex(1) + if not string_struct.IsValid(): + self.fail("A valid object should have been returned") + if not string_struct.GetType() == lldb.eStructuredDataTypeString: + self.fail("Wrong type returned: " + str(string_struct.GetType())) + output = string_struct.GetStringValue(5) + if not output == "arr": + self.fail("wrong output: " + str(output)) diff --git a/scripts/interface/SBStructuredData.i b/scripts/interface/SBStructuredData.i index 1c55bacd31be..4e54cdd7b405 100644 --- a/scripts/interface/SBStructuredData.i +++ b/scripts/interface/SBStructuredData.i @@ -18,21 +18,38 @@ namespace lldb { class SBStructuredData { public: - SBStructuredData(); - + SBStructuredData(const lldb::SBStructuredData &rhs); SBStructuredData(const lldb::EventSP &event_sp); ~SBStructuredData(); - + bool IsValid() const; - + void Clear(); + lldb::SBStructuredData &operator=(const lldb::SBStructuredData &rhs); + + lldb::StructuredDataType GetType() const; + + size_t GetSize() const; + + lldb::SBStructuredData GetValueForKey(const char *key) const; + + lldb::SBStructuredData GetItemAtIndex(size_t idx) const; + + uint64_t GetIntegerValue(uint64_t fail_value = 0) const; + + double GetFloatValue(double fail_value = 0.0) const; + + bool GetBooleanValue(bool fail_value = false) const; + + size_t GetStringValue(char *dst, size_t dst_len) const; + lldb::SBError GetAsJSON(lldb::SBStream &stream) const; diff --git a/scripts/lldb.swig b/scripts/lldb.swig index b0325e611d70..8f1b59c32d4d 100644 --- a/scripts/lldb.swig +++ b/scripts/lldb.swig @@ -31,8 +31,24 @@ o SBLineEntry: Specifies an association with a contiguous range of instructions and a source file location. SBCompileUnit contains SBLineEntry(s)." %enddef +/* +Since version 3.0.9, swig's logic for importing the native module has changed in +a way that is incompatible with our usage of the python module as __init__.py +(See swig bug #769). Fortunately, since version 3.0.11, swig provides a way for +us to override the module import logic to suit our needs. This does that. + +Older swig versions will simply ignore this setting. +*/ +%define MODULEIMPORT +"from . import $module" +%enddef +// These versions will not generate working python modules, so error out early. +#if SWIG_VERSION >= 0x030009 && SWIG_VERSION < 0x030011 +#error Swig versions 3.0.9 and 3.0.10 are incompatible with lldb. +#endif + // The name of the module to be created. -%module(docstring=DOCSTRING) lldb +%module(docstring=DOCSTRING, moduleimport=MODULEIMPORT) lldb // Parameter types will be used in the autodoc string. %feature("autodoc", "1"); diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp index 8b79e521a371..caf07dbe3ce8 100644 --- a/source/API/SBProcess.cpp +++ b/source/API/SBProcess.cpp @@ -363,10 +363,9 @@ lldb::SBTrace SBProcess::StartTrace(SBTraceOptions &options, if (!process_sp) { error.SetErrorString("invalid process"); } else { - - uid = process_sp->StartTrace(options.m_traceoptions_sp, error.ref()); + uid = process_sp->StartTrace(*(options.m_traceoptions_sp), error.ref()); trace_instance.SetTraceUID(uid); - LLDB_LOG(log, "SBProcess::returned uid - %" PRIx64, uid); + LLDB_LOG(log, "SBProcess::returned uid - {0}", uid); } return trace_instance; } diff --git a/source/API/SBStructuredData.cpp b/source/API/SBStructuredData.cpp index 971c4ab2295d..54022390b80f 100644 --- a/source/API/SBStructuredData.cpp +++ b/source/API/SBStructuredData.cpp @@ -46,7 +46,7 @@ lldb::SBError SBStructuredData::SetFromJSON(lldb::SBStream &stream) { StructuredData::ObjectSP json_obj = StructuredData::ParseJSON(json_str); m_impl_up->SetObjectSP(json_obj); - if (!json_obj || json_obj->GetType() != StructuredData::Type::eTypeDictionary) + if (!json_obj || json_obj->GetType() != eStructuredDataTypeDictionary) error.SetErrorString("Invalid Syntax"); return error; } @@ -67,3 +67,45 @@ lldb::SBError SBStructuredData::GetDescription(lldb::SBStream &stream) const { sb_error.SetError(error); return sb_error; } + +StructuredDataType SBStructuredData::GetType() const { + return (m_impl_up ? m_impl_up->GetType() : eStructuredDataTypeInvalid); +} + +size_t SBStructuredData::GetSize() const { + return (m_impl_up ? m_impl_up->GetSize() : 0); +} + +lldb::SBStructuredData SBStructuredData::GetValueForKey(const char *key) const { + if (!m_impl_up) + return SBStructuredData(); + + SBStructuredData result; + result.m_impl_up->SetObjectSP(m_impl_up->GetValueForKey(key)); + return result; +} + +lldb::SBStructuredData SBStructuredData::GetItemAtIndex(size_t idx) const { + if (!m_impl_up) + return SBStructuredData(); + + SBStructuredData result; + result.m_impl_up->SetObjectSP(m_impl_up->GetItemAtIndex(idx)); + return result; +} + +uint64_t SBStructuredData::GetIntegerValue(uint64_t fail_value) const { + return (m_impl_up ? m_impl_up->GetIntegerValue(fail_value) : fail_value); +} + +double SBStructuredData::GetFloatValue(double fail_value) const { + return (m_impl_up ? m_impl_up->GetFloatValue(fail_value) : fail_value); +} + +bool SBStructuredData::GetBooleanValue(bool fail_value) const { + return (m_impl_up ? m_impl_up->GetBooleanValue(fail_value) : fail_value); +} + +size_t SBStructuredData::GetStringValue(char *dst, size_t dst_len) const { + return (m_impl_up ? m_impl_up->GetStringValue(dst, dst_len) : 0); +} diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp index 2c82bc3bcdcf..65ccb465c8da 100644 --- a/source/API/SBThread.cpp +++ b/source/API/SBThread.cpp @@ -43,6 +43,7 @@ #include "lldb/API/SBThreadCollection.h" #include "lldb/API/SBThreadPlan.h" #include "lldb/API/SBValue.h" +#include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; @@ -561,26 +562,26 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) { StructuredData::ObjectSP node = info_root_sp->GetObjectForDotSeparatedPath(path); if (node) { - if (node->GetType() == StructuredData::Type::eTypeString) { + if (node->GetType() == eStructuredDataTypeString) { strm.Printf("%s", node->GetAsString()->GetValue().str().c_str()); success = true; } - if (node->GetType() == StructuredData::Type::eTypeInteger) { + if (node->GetType() == eStructuredDataTypeInteger) { strm.Printf("0x%" PRIx64, node->GetAsInteger()->GetValue()); success = true; } - if (node->GetType() == StructuredData::Type::eTypeFloat) { + if (node->GetType() == eStructuredDataTypeFloat) { strm.Printf("0x%f", node->GetAsFloat()->GetValue()); success = true; } - if (node->GetType() == StructuredData::Type::eTypeBoolean) { + if (node->GetType() == eStructuredDataTypeBoolean) { if (node->GetAsBoolean()->GetValue() == true) strm.Printf("true"); else strm.Printf("false"); success = true; } - if (node->GetType() == StructuredData::Type::eTypeNull) { + if (node->GetType() == eStructuredDataTypeNull) { strm.Printf("null"); success = true; } diff --git a/source/API/SBTrace.cpp b/source/API/SBTrace.cpp index 18f7d36e7759..9a5fa4ed4f46 100644 --- a/source/API/SBTrace.cpp +++ b/source/API/SBTrace.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Utility/Log.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/Log.h" #include "lldb/API/SBTrace.h" #include "lldb/API/SBTraceOptions.h" @@ -25,37 +25,37 @@ lldb::ProcessSP SBTrace::GetSP() const { return m_opaque_wp.lock(); } size_t SBTrace::GetTraceData(SBError &error, void *buf, size_t size, size_t offset, lldb::tid_t thread_id) { - size_t bytes_read = 0; ProcessSP process_sp(GetSP()); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + llvm::MutableArrayRef buffer(static_cast(buf), size); error.Clear(); if (!process_sp) { error.SetErrorString("invalid process"); } else { - bytes_read = process_sp->GetData(GetTraceUID(), thread_id, error.ref(), buf, - size, offset); - LLDB_LOG(log, "SBTrace::bytes_read - %" PRIx64, bytes_read); + error.SetError( + process_sp->GetData(GetTraceUID(), thread_id, buffer, offset)); + LLDB_LOG(log, "SBTrace::bytes_read - {0}", buffer.size()); } - return bytes_read; + return buffer.size(); } size_t SBTrace::GetMetaData(SBError &error, void *buf, size_t size, size_t offset, lldb::tid_t thread_id) { - size_t bytes_read = 0; ProcessSP process_sp(GetSP()); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + llvm::MutableArrayRef buffer(static_cast(buf), size); error.Clear(); if (!process_sp) { error.SetErrorString("invalid process"); } else { - bytes_read = process_sp->GetMetaData(GetTraceUID(), thread_id, error.ref(), - buf, size, offset); - LLDB_LOG(log, "SBTrace::bytes_read - %" PRIx64, bytes_read); + error.SetError( + process_sp->GetMetaData(GetTraceUID(), thread_id, buffer, offset)); + LLDB_LOG(log, "SBTrace::bytes_read - {0}", buffer.size()); } - return bytes_read; + return buffer.size(); } void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) { @@ -66,7 +66,7 @@ void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) { error.SetErrorString("invalid process"); return; } - process_sp->StopTrace(GetTraceUID(), thread_id, error.ref()); + error.SetError(process_sp->StopTrace(GetTraceUID(), thread_id)); } void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) { @@ -76,8 +76,8 @@ void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) { if (!process_sp) { error.SetErrorString("invalid process"); } else { - process_sp->GetTraceConfig(GetTraceUID(), error.ref(), - options.m_traceoptions_sp); + error.SetError(process_sp->GetTraceConfig(GetTraceUID(), + *(options.m_traceoptions_sp))); } } diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index 6b0f1b455bc1..b585ef9ef8ad 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -649,7 +649,7 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { new_plan_sp->SetOkayToDiscard(false); if (m_options.m_step_count > 1) { - if (new_plan_sp->SetIterationCount(m_options.m_step_count)) { + if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) { result.AppendWarning( "step operation does not support iteration count."); } diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp index 9fb294aad2fb..e3c346f79d6b 100644 --- a/source/Core/FormatEntity.cpp +++ b/source/Core/FormatEntity.cpp @@ -1040,24 +1040,24 @@ static bool FormatThreadExtendedInfoRecurse( thread_info_dictionary->GetObjectForDotSeparatedPath(path); if (value) { - if (value->GetType() == StructuredData::Type::eTypeInteger) { + if (value->GetType() == eStructuredDataTypeInteger) { const char *token_format = "0x%4.4" PRIx64; if (!entry.printf_format.empty()) token_format = entry.printf_format.c_str(); s.Printf(token_format, value->GetAsInteger()->GetValue()); return true; - } else if (value->GetType() == StructuredData::Type::eTypeFloat) { + } else if (value->GetType() == eStructuredDataTypeFloat) { s.Printf("%f", value->GetAsFloat()->GetValue()); return true; - } else if (value->GetType() == StructuredData::Type::eTypeString) { + } else if (value->GetType() == eStructuredDataTypeString) { s.Format("{0}", value->GetAsString()->GetValue()); return true; - } else if (value->GetType() == StructuredData::Type::eTypeArray) { + } else if (value->GetType() == eStructuredDataTypeArray) { if (value->GetAsArray()->GetSize() > 0) { s.Printf("%zu", value->GetAsArray()->GetSize()); return true; } - } else if (value->GetType() == StructuredData::Type::eTypeDictionary) { + } else if (value->GetType() == eStructuredDataTypeDictionary) { s.Printf("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); return true; @@ -1346,7 +1346,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, if (thread) { StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); if (object_sp && - object_sp->GetType() == StructuredData::Type::eTypeDictionary) { + object_sp->GetType() == eStructuredDataTypeDictionary) { if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s)) return true; } diff --git a/source/Core/StructuredData.cpp b/source/Core/StructuredData.cpp index d52b7730cc65..b03665ed3485 100644 --- a/source/Core/StructuredData.cpp +++ b/source/Core/StructuredData.cpp @@ -184,7 +184,7 @@ StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) { StructuredData::ObjectSP StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) { - if (this->GetType() == Type::eTypeDictionary) { + if (this->GetType() == lldb::eStructuredDataTypeDictionary) { std::pair match = path.split('.'); std::string key = match.first.str(); ObjectSP value = this->GetAsDictionary()->GetValueForKey(key); @@ -200,7 +200,7 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) { return ObjectSP(); } - if (this->GetType() == Type::eTypeArray) { + if (this->GetType() == lldb::eStructuredDataTypeArray) { std::pair match = path.split('['); if (match.second.size() == 0) { return this->shared_from_this(); diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index 7d4b398a171d..7b580dde656a 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -474,7 +474,7 @@ unsigned char Editline::RecallHistory(bool earlier) { return CC_NEWLINE; } -int Editline::GetCharacter(EditLineCharType *c) { +int Editline::GetCharacter(EditLineGetCharType *c) { const LineInfoW *info = el_wline(m_editline); // Paint a faint version of the desired prompt over the version libedit draws @@ -969,7 +969,7 @@ void Editline::ConfigureEditor(bool multiline) { })); el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([]( - EditLine *editline, EditLineCharType *c) { + EditLine *editline, EditLineGetCharType *c) { return Editline::InstanceFor(editline)->GetCharacter(c); })); @@ -1360,12 +1360,12 @@ void Editline::PrintAsync(Stream *stream, const char *s, size_t len) { } } -bool Editline::CompleteCharacter(char ch, EditLineCharType &out) { +bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) { #if !LLDB_EDITLINE_USE_WCHAR if (ch == (char)EOF) return false; - out = ch; + out = (unsigned char)ch; return true; #else std::codecvt_utf8 cvt; diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp index 3ceda5ff67e9..439d372fadeb 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp @@ -254,11 +254,12 @@ bool fixupRSAllocationStructByValCalls(llvm::Module &module) { llvm::AttributeList call_attribs = call_inst->getAttributes(); // iterate over the argument attributes - for (size_t i = 1; i <= call_attribs.getNumSlots(); ++i) { + for (unsigned I = call_attribs.index_begin(); I != call_attribs.index_end(); + I++) { // if this argument is passed by val - if (call_attribs.hasAttribute(i, llvm::Attribute::ByVal)) { + if (call_attribs.hasAttribute(I, llvm::Attribute::ByVal)) { // strip away the byval attribute - call_inst->removeAttribute(i, llvm::Attribute::ByVal); + call_inst->removeAttribute(I, llvm::Attribute::ByVal); changed = true; } } diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 1667490f1344..34d99cd39de2 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -1132,6 +1132,10 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, case 0: case TRAP_TRACE: +#ifdef TRAP_CAP + // Map TRAP_CAP to a trace trap in the absense of a more specific handler. + case TRAP_CAP: +#endif if (log) log->Printf("ProcessMonitor::%s() received trace event, tid = %" PRIu64 " : si_code = %d", diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 80751147b4f5..efb19fc414f9 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -167,8 +167,6 @@ NativeProcessNetBSD::NativeProcessNetBSD() // Handles all waitpid events from the inferior process. void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - switch (signal) { case SIGTRAP: return MonitorSIGTRAP(pid); @@ -196,7 +194,6 @@ void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, int signal, } void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); ptrace_siginfo_t info; const auto siginfo_err = @@ -305,8 +302,6 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { } void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - ptrace_siginfo_t info; const auto siginfo_err = PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); @@ -898,6 +893,19 @@ void NativeProcessNetBSD::SigchldHandler() { MonitorCallback(wait_pid, signal); } +bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) { + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not contain NULL threads"); + if (thread_sp->GetID() == thread_id) { + // We have this thread. + return true; + } + } + + // We don't have this thread. + return false; +} + NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); @@ -916,8 +924,6 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { } ::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Status &error) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (pid <= 1) { error.SetErrorToGenericError(); error.SetErrorString("Attaching to process 1 is not allowed."); @@ -1006,7 +1012,7 @@ Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf, io.piod_len = size; do { - io.piod_addr = (void *)(src + bytes_written); + io.piod_addr = const_cast(static_cast(src + bytes_written)); io.piod_offs = (void *)(addr + bytes_written); Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); @@ -1034,10 +1040,11 @@ NativeProcessNetBSD::GetAuxvData() const { ErrorOr> buf = llvm::MemoryBuffer::getNewMemBuffer(auxv_size); - struct ptrace_io_desc io = {.piod_op = PIOD_READ_AUXV, - .piod_offs = 0, - .piod_addr = (void *)buf.get()->getBufferStart(), - .piod_len = auxv_size}; + struct ptrace_io_desc io; + io.piod_op = PIOD_READ_AUXV; + io.piod_offs = 0; + io.piod_addr = const_cast(static_cast(buf.get()->getBufferStart())); + io.piod_len = auxv_size; Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index e18ba162e523..758956e3dca1 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -115,6 +115,8 @@ class NativeProcessNetBSD : public NativeProcessProtocol { // --------------------------------------------------------------------- NativeProcessNetBSD(); + bool HasThreadNoLock(lldb::tid_t thread_id); + NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id); Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 550ec0ea499a..33aed7a43c4a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -30,7 +30,6 @@ #include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" // Project includes @@ -3152,6 +3151,211 @@ bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) { response.IsOKResponse(); } +lldb::user_id_t +GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options, + Status &error) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + lldb::user_id_t ret_uid = LLDB_INVALID_UID; + + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jTraceStart:"); + + StructuredData::Dictionary json_packet; + json_packet.AddIntegerItem("type", options.getType()); + json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); + json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); + + if (options.getThreadID() != LLDB_INVALID_THREAD_ID) + json_packet.AddIntegerItem("threadid", options.getThreadID()); + + StructuredData::DictionarySP custom_params = options.getTraceParams(); + if (custom_params) + json_packet.AddItem("params", custom_params); + + StreamString json_string; + json_packet.Dump(json_string, false); + escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (!response.IsNormalResponse()) { + error.SetError(response.GetError(), eErrorTypeGeneric); + LLDB_LOG(log, "Target does not support Tracing"); + } else { + ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat("failed to send packet: '%s'", + escaped_packet.GetData()); + } + return ret_uid; +} + +Status +GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid, + lldb::tid_t thread_id) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + StringExtractorGDBRemote response; + Status error; + + StructuredData::Dictionary json_packet; + StreamGDBRemote escaped_packet; + StreamString json_string; + escaped_packet.PutCString("jTraceStop:"); + + json_packet.AddIntegerItem("traceid", uid); + + if (thread_id != LLDB_INVALID_THREAD_ID) + json_packet.AddIntegerItem("threadid", thread_id); + + json_packet.Dump(json_string, false); + + escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (!response.IsOKResponse()) { + error.SetError(response.GetError(), eErrorTypeGeneric); + LLDB_LOG(log, "stop tracing failed"); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat( + "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(), + response.GetError()); + } + return error; +} + +Status GDBRemoteCommunicationClient::SendGetDataPacket( + lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, size_t offset) { + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jTraceBufferRead:"); + return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); +} + +Status GDBRemoteCommunicationClient::SendGetMetaDataPacket( + lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, size_t offset) { + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jTraceMetaRead:"); + return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); +} + +Status +GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid, + TraceOptions &options) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + StringExtractorGDBRemote response; + Status error; + + StreamString json_string; + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jTraceConfigRead:"); + + StructuredData::Dictionary json_packet; + json_packet.AddIntegerItem("traceid", uid); + + if (options.getThreadID() != LLDB_INVALID_THREAD_ID) + json_packet.AddIntegerItem("threadid", options.getThreadID()); + + json_packet.Dump(json_string, false); + escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (response.IsNormalResponse()) { + uint64_t type = std::numeric_limits::max(); + uint64_t buffersize = std::numeric_limits::max(); + uint64_t metabuffersize = std::numeric_limits::max(); + + auto json_object = StructuredData::ParseJSON(response.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) { + error.SetErrorString("Invalid Configuration obtained"); + return error; + } + + auto json_dict = json_object->GetAsDictionary(); + + json_dict->GetValueForKeyAsInteger("metabuffersize", + metabuffersize); + options.setMetaDataBufferSize(metabuffersize); + + json_dict->GetValueForKeyAsInteger("buffersize", buffersize); + options.setTraceBufferSize(buffersize); + + json_dict->GetValueForKeyAsInteger("type", type); + options.setType(static_cast(type)); + + StructuredData::ObjectSP custom_params_sp = + json_dict->GetValueForKey("params"); + if (custom_params_sp) { + if (custom_params_sp->GetType() != + lldb::eStructuredDataTypeDictionary) { + error.SetErrorString("Invalid Configuration obtained"); + return error; + } else + options.setTraceParams( + static_pointer_cast( + custom_params_sp)); + } + } else { + error.SetError(response.GetError(), eErrorTypeGeneric); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat("failed to send packet: '%s'", + escaped_packet.GetData()); + } + return error; +} + +Status GDBRemoteCommunicationClient::SendGetTraceDataPacket( + StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, size_t offset) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + Status error; + + StructuredData::Dictionary json_packet; + + json_packet.AddIntegerItem("traceid", uid); + json_packet.AddIntegerItem("offset", offset); + json_packet.AddIntegerItem("buffersize", buffer.size()); + + if (thread_id != LLDB_INVALID_THREAD_ID) + json_packet.AddIntegerItem("threadid", thread_id); + + StreamString json_string; + json_packet.Dump(json_string, false); + + packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetString(), response, true) == + GDBRemoteCommunication::PacketResult::Success) { + if (response.IsNormalResponse()) { + size_t filled_size = response.GetHexBytesAvail(buffer); + buffer = llvm::MutableArrayRef(buffer.data(), filled_size); + } else { + error.SetError(response.GetError(), eErrorTypeGeneric); + buffer = buffer.slice(buffer.size()); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat("failed to send packet: '%s'", + packet.GetData()); + buffer = buffer.slice(buffer.size()); + } + return error; +} + bool GDBRemoteCommunicationClient::GetModuleInfo( const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec, ModuleSpec &module_spec) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 08d0bd5d690b..6306651da7a1 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -25,6 +25,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/StructuredData.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/StreamGDBRemote.h" #include "llvm/ADT/Optional.h" @@ -499,6 +500,21 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { ConfigureRemoteStructuredData(const ConstString &type_name, const StructuredData::ObjectSP &config_sp); + lldb::user_id_t SendStartTracePacket(const TraceOptions &options, + Status &error); + + Status SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id); + + Status SendGetDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, + size_t offset = 0); + + Status SendGetMetaDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, + size_t offset = 0); + + Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options); + protected: LazyBool m_supports_not_sending_acks; LazyBool m_supports_thread_suffix; @@ -587,6 +603,11 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response, bool send_async); + Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid, + lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, + size_t offset); + private: DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient); }; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index ec7c2f5330d7..d318c35366f1 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -183,6 +183,22 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { StringExtractorGDBRemote::eServerPacketType_QPassSignals, &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceStart, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceStop, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead, + &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead); + RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, bool &quit) { @@ -1083,6 +1099,231 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { } } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + if (!packet.ConsumeFront("jTraceStart:")) + return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); + + TraceOptions options; + uint64_t type = std::numeric_limits::max(); + uint64_t buffersize = std::numeric_limits::max(); + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + uint64_t metabuffersize = std::numeric_limits::max(); + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize); + options.setMetaDataBufferSize(metabuffersize); + + json_dict->GetValueForKeyAsInteger("buffersize", buffersize); + options.setTraceBufferSize(buffersize); + + json_dict->GetValueForKeyAsInteger("type", type); + options.setType(static_cast(type)); + + json_dict->GetValueForKeyAsInteger("threadid", tid); + options.setThreadID(tid); + + StructuredData::ObjectSP custom_params_sp = + json_dict->GetValueForKey("params"); + if (custom_params_sp && + custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); + + options.setTraceParams( + static_pointer_cast(custom_params_sp)); + + if (buffersize == std::numeric_limits::max() || + type != lldb::TraceType::eTraceTypeProcessorTrace) { + LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize, + type); + return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet "); + } + + Status error; + lldb::user_id_t uid = LLDB_INVALID_UID; + uid = m_debugged_process_sp->StartTrace(options, error); + LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError()); + if (error.Fail()) + return SendErrorResponse(error.GetError()); + + StreamGDBRemote response; + response.Printf("%" PRIx64, uid); + return SendPacketNoLock(response.GetString()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jTraceStop( + StringExtractorGDBRemote &packet) { + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + if (!packet.ConsumeFront("jTraceStop:")) + return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); + + lldb::user_id_t uid = LLDB_INVALID_UID; + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) + return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); + + json_dict->GetValueForKeyAsInteger("threadid", tid); + + Status error = m_debugged_process_sp->StopTrace(uid, tid); + + if (error.Fail()) + return SendErrorResponse(error.GetError()); + + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead( + StringExtractorGDBRemote &packet) { + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + if (!packet.ConsumeFront("jTraceConfigRead:")) + return SendIllFormedResponse(packet, + "jTraceConfigRead: Ill formed packet "); + + lldb::user_id_t uid = LLDB_INVALID_UID; + lldb::tid_t threadid = LLDB_INVALID_THREAD_ID; + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, + "jTraceConfigRead: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) + return SendIllFormedResponse(packet, + "jTraceConfigRead: Ill formed packet "); + + json_dict->GetValueForKeyAsInteger("threadid", threadid); + + TraceOptions options; + StreamGDBRemote response; + + options.setThreadID(threadid); + Status error = m_debugged_process_sp->GetTraceConfig(uid, options); + + if (error.Fail()) + return SendErrorResponse(error.GetError()); + + StreamGDBRemote escaped_response; + StructuredData::Dictionary json_packet; + + json_packet.AddIntegerItem("type", options.getType()); + json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); + json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); + + StructuredData::DictionarySP custom_params = options.getTraceParams(); + if (custom_params) + json_packet.AddItem("params", custom_params); + + StreamString json_string; + json_packet.Dump(json_string, false); + escaped_response.PutEscapedBytes(json_string.GetData(), + json_string.GetSize()); + return SendPacketNoLock(escaped_response.GetString()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jTraceRead( + StringExtractorGDBRemote &packet) { + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + enum PacketType { MetaData, BufferData }; + PacketType tracetype = MetaData; + + if (packet.ConsumeFront("jTraceBufferRead:")) + tracetype = BufferData; + else if (packet.ConsumeFront("jTraceMetaRead:")) + tracetype = MetaData; + else { + return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); + } + + lldb::user_id_t uid = LLDB_INVALID_UID; + + size_t byte_count = std::numeric_limits::max(); + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + size_t offset = std::numeric_limits::max(); + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + if (!json_dict->GetValueForKeyAsInteger("traceid", uid) || + !json_dict->GetValueForKeyAsInteger("offset", offset) || + !json_dict->GetValueForKeyAsInteger("buffersize", byte_count)) + return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); + + json_dict->GetValueForKeyAsInteger("threadid", tid); + + // Allocate the response buffer. + std::unique_ptr buffer (new (std::nothrow) uint8_t[byte_count]); + if (!buffer) + return SendErrorResponse(0x78); + + StreamGDBRemote response; + Status error; + llvm::MutableArrayRef buf(buffer.get(), byte_count); + + if (tracetype == BufferData) + error = m_debugged_process_sp->GetData(uid, tid, buf, offset); + else if (tracetype == MetaData) + error = m_debugged_process_sp->GetMetaData(uid, tid, buf, offset); + + if (error.Fail()) + return SendErrorResponse(error.GetError()); + + for (size_t i = 0; i < buf.size(); ++i) + response.PutHex8(buf[i]); + + StreamGDBRemote escaped_response; + escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); + return SendPacketNoLock(escaped_response.GetString()); +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( StringExtractorGDBRemote &packet) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index ebda9a911d3c..a7d7850d454f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -189,6 +189,14 @@ class GDBRemoteCommunicationServerLLGS PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet); + PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet); + + PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet); + + PacketResult Handle_jTraceStop(StringExtractorGDBRemote &packet); + + PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet); + PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet); PacketResult Handle_vAttach(StringExtractorGDBRemote &packet); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 64684c5963b3..aeb7c742b4f4 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1236,6 +1236,32 @@ Status ProcessGDBRemote::DoAttachToProcessWithName( return error; } +lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options, + Status &error) { + return m_gdb_comm.SendStartTracePacket(options, error); +} + +Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) { + return m_gdb_comm.SendStopTracePacket(uid, thread_id); +} + +Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, + size_t offset) { + return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset); +} + +Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, + size_t offset) { + return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset); +} + +Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid, + TraceOptions &options) { + return m_gdb_comm.SendGetTraceConfigPacket(uid, options); +} + void ProcessGDBRemote::DidExit() { // When we exit, disconnect from the GDB server communications m_gdb_comm.Disconnect(); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 60f0464f86bb..d7a4e961b540 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -31,6 +31,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" +#include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringExtractor.h" #include "lldb/Utility/StringList.h" @@ -177,6 +178,21 @@ class ProcessGDBRemote : public Process, Status GetWatchpointSupportInfo(uint32_t &num) override; + lldb::user_id_t StartTrace(const TraceOptions &options, + Status &error) override; + + Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) override; + + Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, + size_t offset = 0) override; + + Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, + llvm::MutableArrayRef &buffer, + size_t offset = 0) override; + + Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override; + Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override; bool StartNoticingNewThreads() override; diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index ff86b0dbe051..c6ad536cee10 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -4823,6 +4823,48 @@ GetExpressionTimeout(const EvaluateExpressionOptions &options, return *options.GetTimeout() - GetOneThreadExpressionTimeout(options); } +static llvm::Optional +HandleStoppedEvent(Thread &thread, const ThreadPlanSP &thread_plan_sp, + RestorePlanState &restorer, const EventSP &event_sp, + EventSP &event_to_broadcast_sp, + const EvaluateExpressionOptions &options, bool handle_interrupts) { + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS); + + ThreadPlanSP plan = thread.GetCompletedPlan(); + if (plan == thread_plan_sp && plan->PlanSucceeded()) { + LLDB_LOG(log, "execution completed successfully"); + + // Restore the plan state so it will get reported as intended when we are + // done. + restorer.Clean(); + return eExpressionCompleted; + } + + StopInfoSP stop_info_sp = thread.GetStopInfo(); + if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint && + stop_info_sp->ShouldNotify(event_sp.get())) { + LLDB_LOG(log, "stopped for breakpoint: {0}.", stop_info_sp->GetDescription()); + if (!options.DoesIgnoreBreakpoints()) { + // Restore the plan state and then force Private to false. We are going + // to stop because of this plan so we need it to become a public plan or + // it won't report correctly when we continue to its termination later on. + restorer.Clean(); + thread_plan_sp->SetPrivate(false); + event_to_broadcast_sp = event_sp; + } + return eExpressionHitBreakpoint; + } + + if (!handle_interrupts && + Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get())) + return llvm::None; + + LLDB_LOG(log, "thread plan did not successfully complete"); + if (!options.DoesUnwindOnError()) + event_to_broadcast_sp = event_sp; + return eExpressionInterrupted; +} + ExpressionResults Process::RunThreadPlan(ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp, @@ -5228,65 +5270,22 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, "but our thread (index-id=%u) has vanished.", thread_idx_id); return_value = eExpressionInterrupted; - } else { + } else if (Process::ProcessEventData::GetRestartedFromEvent( + event_sp.get())) { // If we were restarted, we just need to go back up to fetch // another event. - if (Process::ProcessEventData::GetRestartedFromEvent( - event_sp.get())) { - if (log) { - log->Printf("Process::RunThreadPlan(): Got a stop and " - "restart, so we'll continue waiting."); - } - keep_going = true; - do_resume = false; - handle_running_event = true; - } else { - ThreadPlanSP plan = thread->GetCompletedPlan(); - if (plan == thread_plan_sp && plan->PlanSucceeded()) { - - if (log) - log->PutCString("Process::RunThreadPlan(): execution " - "completed successfully."); - - // Restore the plan state so it will get reported as - // intended when we are done. - thread_plan_restorer.Clean(); - - return_value = eExpressionCompleted; - } else { - StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); - // Something restarted the target, so just wait for it to - // stop for real. - if (stop_info_sp && - stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { - if (log) - log->Printf("Process::RunThreadPlan() stopped for " - "breakpoint: %s.", - stop_info_sp->GetDescription()); - return_value = eExpressionHitBreakpoint; - if (!options.DoesIgnoreBreakpoints()) { - // Restore the plan state and then force Private to - // false. We are - // going to stop because of this plan so we need it to - // become a public - // plan or it won't report correctly when we continue to - // its termination - // later on. - thread_plan_restorer.Clean(); - if (thread_plan_sp) - thread_plan_sp->SetPrivate(false); - event_to_broadcast_sp = event_sp; - } - } else { - if (log) - log->PutCString("Process::RunThreadPlan(): thread plan " - "didn't successfully complete."); - if (!options.DoesUnwindOnError()) - event_to_broadcast_sp = event_sp; - return_value = eExpressionInterrupted; - } - } + if (log) { + log->Printf("Process::RunThreadPlan(): Got a stop and " + "restart, so we'll continue waiting."); } + keep_going = true; + do_resume = false; + handle_running_event = true; + } else { + const bool handle_interrupts = true; + return_value = *HandleStoppedEvent( + *thread, thread_plan_sp, thread_plan_restorer, event_sp, + event_to_broadcast_sp, options, handle_interrupts); } } break; @@ -5392,20 +5391,6 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, } if (stop_state == lldb::eStateStopped) { - // Between the time we initiated the Halt and the time we - // delivered it, the process could have - // already finished its job. Check that here: - - if (thread->IsThreadPlanDone(thread_plan_sp.get())) { - if (log) - log->PutCString("Process::RunThreadPlan(): Even though we " - "timed out, the call plan was done. " - "Exiting wait loop."); - return_value = eExpressionCompleted; - back_to_top = false; - break; - } - if (Process::ProcessEventData::GetRestartedFromEvent( event_sp.get())) { if (log) @@ -5419,6 +5404,18 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, continue; } + // Between the time we initiated the Halt and the time we + // delivered it, the process could have + // already finished its job. Check that here: + const bool handle_interrupts = false; + if (auto result = HandleStoppedEvent( + *thread, thread_plan_sp, thread_plan_restorer, event_sp, + event_to_broadcast_sp, options, handle_interrupts)) { + return_value = *result; + back_to_top = false; + break; + } + if (!options.GetTryAllThreads()) { if (log) log->PutCString("Process::RunThreadPlan(): try_all_threads " diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp index 43ae7b5413be..4aba30be5f78 100644 --- a/source/Target/Thread.cpp +++ b/source/Target/Thread.cpp @@ -51,6 +51,7 @@ #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" +#include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; @@ -397,7 +398,7 @@ lldb::StopInfoSP Thread::GetStopInfo() { bool plan_overrides_trace = have_valid_stop_info && have_valid_completed_plan && (m_stop_info_sp->GetStopReason() == eStopReasonTrace); - + if (have_valid_stop_info && !plan_overrides_trace) { return m_stop_info_sp; } else if (have_valid_completed_plan) { @@ -541,7 +542,7 @@ bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) { saved_state.orig_stop_id = process_sp->GetStopID(); saved_state.current_inlined_depth = GetCurrentInlinedDepth(); saved_state.m_completed_plan_stack = m_completed_plan_stack; - + return true; } @@ -1994,13 +1995,12 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level, thread_info->GetObjectForDotSeparatedPath("trace_messages"); bool printed_activity = false; - if (activity && - activity->GetType() == StructuredData::Type::eTypeDictionary) { + if (activity && activity->GetType() == eStructuredDataTypeDictionary) { StructuredData::Dictionary *activity_dict = activity->GetAsDictionary(); StructuredData::ObjectSP id = activity_dict->GetValueForKey("id"); StructuredData::ObjectSP name = activity_dict->GetValueForKey("name"); - if (name && name->GetType() == StructuredData::Type::eTypeString && id && - id->GetType() == StructuredData::Type::eTypeInteger) { + if (name && name->GetType() == eStructuredDataTypeString && id && + id->GetType() == eStructuredDataTypeInteger) { strm.Format(" Activity '{0}', {1:x}\n", name->GetAsString()->GetValue(), id->GetAsInteger()->GetValue()); @@ -2008,8 +2008,7 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level, printed_activity = true; } bool printed_breadcrumb = false; - if (breadcrumb && - breadcrumb->GetType() == StructuredData::Type::eTypeDictionary) { + if (breadcrumb && breadcrumb->GetType() == eStructuredDataTypeDictionary) { if (printed_activity) strm.Printf("\n"); StructuredData::Dictionary *breadcrumb_dict = @@ -2017,13 +2016,13 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level, StructuredData::ObjectSP breadcrumb_text = breadcrumb_dict->GetValueForKey("name"); if (breadcrumb_text && - breadcrumb_text->GetType() == StructuredData::Type::eTypeString) { + breadcrumb_text->GetType() == eStructuredDataTypeString) { strm.Format(" Current Breadcrumb: {0}\n", breadcrumb_text->GetAsString()->GetValue()); } printed_breadcrumb = true; } - if (messages && messages->GetType() == StructuredData::Type::eTypeArray) { + if (messages && messages->GetType() == eStructuredDataTypeArray) { if (printed_breadcrumb) strm.Printf("\n"); StructuredData::Array *messages_array = messages->GetAsArray(); @@ -2032,14 +2031,13 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level, strm.Printf(" %zu trace messages:\n", msg_count); for (size_t i = 0; i < msg_count; i++) { StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i); - if (message && - message->GetType() == StructuredData::Type::eTypeDictionary) { + if (message && message->GetType() == eStructuredDataTypeDictionary) { StructuredData::Dictionary *message_dict = message->GetAsDictionary(); StructuredData::ObjectSP message_text = message_dict->GetValueForKey("message"); if (message_text && - message_text->GetType() == StructuredData::Type::eTypeString) { + message_text->GetType() == eStructuredDataTypeString) { strm.Format(" {0}\n", message_text->GetAsString()->GetValue()); } } diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp index a94f6bcd0087..cf5c7e227448 100644 --- a/source/Utility/StringExtractor.cpp +++ b/source/Utility/StringExtractor.cpp @@ -280,6 +280,15 @@ uint64_t StringExtractor::GetHexMaxU64(bool little_endian, return result; } +bool StringExtractor::ConsumeFront(const llvm::StringRef &str) { + llvm::StringRef S = GetStringRef(); + if (!S.startswith(str)) + return false; + else + m_index += str.size(); + return true; +} + size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef dest, uint8_t fail_fill_value) { size_t bytes_extracted = 0; diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp index 08226f4c8f90..3473a9e96689 100644 --- a/source/Utility/StringExtractorGDBRemote.cpp +++ b/source/Utility/StringExtractorGDBRemote.cpp @@ -286,6 +286,16 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_jSignalsInfo; if (PACKET_MATCHES("jThreadsInfo")) return eServerPacketType_jThreadsInfo; + if (PACKET_STARTS_WITH("jTraceBufferRead:")) + return eServerPacketType_jTraceBufferRead; + if (PACKET_STARTS_WITH("jTraceConfigRead:")) + return eServerPacketType_jTraceConfigRead; + if (PACKET_STARTS_WITH("jTraceMetaRead:")) + return eServerPacketType_jTraceMetaRead; + if (PACKET_STARTS_WITH("jTraceStart:")) + return eServerPacketType_jTraceStart; + if (PACKET_STARTS_WITH("jTraceStop:")) + return eServerPacketType_jTraceStop; break; case 'v': diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h index a5c0c8e803b6..473cab04f800 100644 --- a/source/Utility/StringExtractorGDBRemote.h +++ b/source/Utility/StringExtractorGDBRemote.h @@ -164,6 +164,12 @@ class StringExtractorGDBRemote : public StringExtractor { eServerPacketType__M, eServerPacketType__m, eServerPacketType_notify, // '%' notification + + eServerPacketType_jTraceStart, + eServerPacketType_jTraceBufferRead, + eServerPacketType_jTraceMetaRead, + eServerPacketType_jTraceStop, + eServerPacketType_jTraceConfigRead, }; ServerPacketType GetServerPacketType() const; diff --git a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp index 56a7e74269aa..c9ab0b6050a0 100644 --- a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -11,8 +11,10 @@ #include "GDBRemoteTestUtils.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" +#include "lldb/lldb-enumerations.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/StructuredData.h" +#include "lldb/Core/TraceOptions.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/DataBuffer.h" @@ -370,3 +372,227 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfoInvalidResponse) { HandlePacket(server, "qMemoryRegionInfo:4000", "start:4000;size:0000;"); EXPECT_FALSE(result.get().Success()); } + +TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + TraceOptions options; + Status error; + + options.setType(lldb::TraceType::eTraceTypeProcessorTrace); + options.setMetaDataBufferSize(8192); + options.setTraceBufferSize(8192); + options.setThreadID(0x23); + + StructuredData::DictionarySP custom_params = + std::make_shared(); + custom_params->AddStringItem("tracetech", "intel-pt"); + custom_params->AddIntegerItem("psb", 0x01); + + options.setTraceParams(custom_params); + + std::future result = std::async(std::launch::async, [&] { + return client.SendStartTracePacket(options, error); + }); + + // Since the line is exceeding 80 characters. + std::string expected_packet1 = + R"(jTraceStart:{"buffersize" : 8192,"metabuffersize" : 8192,"params" :)"; + std::string expected_packet2 = + R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})"; + HandlePacket(server, (expected_packet1 + expected_packet2), "1"); + ASSERT_TRUE(error.Success()); + ASSERT_EQ(result.get(), 1); + + error.Clear(); + result = std::async(std::launch::async, [&] { + return client.SendStartTracePacket(options, error); + }); + + HandlePacket(server, (expected_packet1 + expected_packet2), "E23"); + ASSERT_EQ(result.get(), LLDB_INVALID_UID); + ASSERT_FALSE(error.Success()); +} + +TEST_F(GDBRemoteCommunicationClientTest, SendStopTracePacket) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + lldb::tid_t thread_id = 0x23; + lldb::user_id_t trace_id = 3; + + std::future result = std::async(std::launch::async, [&] { + return client.SendStopTracePacket(trace_id, thread_id); + }); + + const char *expected_packet = + R"(jTraceStop:{"threadid" : 35,"traceid" : 3})"; + HandlePacket(server, expected_packet, "OK"); + ASSERT_TRUE(result.get().Success()); + + result = std::async(std::launch::async, [&] { + return client.SendStopTracePacket(trace_id, thread_id); + }); + + HandlePacket(server, expected_packet, "E23"); + ASSERT_FALSE(result.get().Success()); +} + +TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + lldb::tid_t thread_id = 0x23; + lldb::user_id_t trace_id = 3; + + uint8_t buf[32] = {}; + llvm::MutableArrayRef buffer(buf, 32); + size_t offset = 0; + + std::future result = std::async(std::launch::async, [&] { + return client.SendGetDataPacket(trace_id, thread_id, buffer, offset); + }); + + std::string expected_packet1 = + R"(jTraceBufferRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)"; + std::string expected_packet2 = R"("traceid" : 3})"; + HandlePacket(server, expected_packet1+expected_packet2, "123456"); + ASSERT_TRUE(result.get().Success()); + ASSERT_EQ(buffer.size(), 3); + ASSERT_EQ(buf[0], 0x12); + ASSERT_EQ(buf[1], 0x34); + ASSERT_EQ(buf[2], 0x56); + + llvm::MutableArrayRef buffer2(buf, 32); + result = std::async(std::launch::async, [&] { + return client.SendGetDataPacket(trace_id, thread_id, buffer2, offset); + }); + + HandlePacket(server, expected_packet1+expected_packet2, "E23"); + ASSERT_FALSE(result.get().Success()); + ASSERT_EQ(buffer2.size(), 0); +} + +TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + lldb::tid_t thread_id = 0x23; + lldb::user_id_t trace_id = 3; + + uint8_t buf[32] = {}; + llvm::MutableArrayRef buffer(buf, 32); + size_t offset = 0; + + std::future result = std::async(std::launch::async, [&] { + return client.SendGetMetaDataPacket(trace_id, thread_id, buffer, offset); + }); + + std::string expected_packet1 = + R"(jTraceMetaRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)"; + std::string expected_packet2 = R"("traceid" : 3})"; + HandlePacket(server, expected_packet1+expected_packet2, "123456"); + ASSERT_TRUE(result.get().Success()); + ASSERT_EQ(buffer.size(), 3); + ASSERT_EQ(buf[0], 0x12); + ASSERT_EQ(buf[1], 0x34); + ASSERT_EQ(buf[2], 0x56); + + llvm::MutableArrayRef buffer2(buf, 32); + result = std::async(std::launch::async, [&] { + return client.SendGetMetaDataPacket(trace_id, thread_id, buffer2, offset); + }); + + HandlePacket(server, expected_packet1+expected_packet2, "E23"); + ASSERT_FALSE(result.get().Success()); + ASSERT_EQ(buffer2.size(), 0); +} + +TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + lldb::tid_t thread_id = 0x23; + lldb::user_id_t trace_id = 3; + TraceOptions options; + options.setThreadID(thread_id); + + std::future result = std::async(std::launch::async, [&] { + return client.SendGetTraceConfigPacket(trace_id, options); + }); + + const char *expected_packet = + R"(jTraceConfigRead:{"threadid" : 35,"traceid" : 3})"; + std::string response1 = + R"({"buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})"; + std::string response2 = + R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])"; + HandlePacket(server, expected_packet, response1+response2); + ASSERT_TRUE(result.get().Success()); + ASSERT_EQ(options.getTraceBufferSize(), 8192); + ASSERT_EQ(options.getMetaDataBufferSize(), 8192); + ASSERT_EQ(options.getType(), 1); + + auto custom_params = options.getTraceParams(); + + uint64_t psb_value; + llvm::StringRef trace_tech_value; + + ASSERT_TRUE(custom_params); + ASSERT_EQ(custom_params->GetType(), eStructuredDataTypeDictionary); + ASSERT_TRUE( + custom_params->GetValueForKeyAsInteger("psb", psb_value)); + ASSERT_EQ(psb_value, 1); + ASSERT_TRUE( + custom_params->GetValueForKeyAsString("tracetech", trace_tech_value)); + ASSERT_STREQ(trace_tech_value.data(), "intel-pt"); + + // Checking error response. + std::future result2 = std::async(std::launch::async, [&] { + return client.SendGetTraceConfigPacket(trace_id, options); + }); + + HandlePacket(server, expected_packet, "E23"); + ASSERT_FALSE(result2.get().Success()); + + // Wrong JSON as response. + std::future result3 = std::async(std::launch::async, [&] { + return client.SendGetTraceConfigPacket(trace_id, options); + }); + + std::string incorrect_json1 = + R"("buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})"; + std::string incorrect_json2 = + R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])"; + HandlePacket(server, expected_packet, incorrect_json1+incorrect_json2); + ASSERT_FALSE(result3.get().Success()); + + // Wrong JSON as custom_params. + std::future result4 = std::async(std::launch::async, [&] { + return client.SendGetTraceConfigPacket(trace_id, options); + }); + + std::string incorrect_custom_params1 = + R"({"buffersize" : 8192,"params" : "psb" : 1,"tracetech" : "intel-pt"})"; + std::string incorrect_custom_params2 = + R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])"; + HandlePacket(server, expected_packet, incorrect_custom_params1+ + incorrect_custom_params2); + ASSERT_FALSE(result4.get().Success()); +} diff --git a/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp b/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp index 192e64d07034..1376f268aa79 100644 --- a/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp +++ b/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp @@ -15,6 +15,7 @@ #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" +#include "lldb/lldb-enumerations.h" #include "PythonTestSuite.h" @@ -355,9 +356,9 @@ TEST_F(PythonDataObjectsTest, TestPythonListToStructuredList) { list.AppendItem(PythonString(string_value1)); auto array_sp = list.CreateStructuredArray(); - EXPECT_EQ(StructuredData::Type::eTypeInteger, + EXPECT_EQ(lldb::eStructuredDataTypeInteger, array_sp->GetItemAtIndex(0)->GetType()); - EXPECT_EQ(StructuredData::Type::eTypeString, + EXPECT_EQ(lldb::eStructuredDataTypeString, array_sp->GetItemAtIndex(1)->GetType()); auto int_sp = array_sp->GetItemAtIndex(0)->GetAsInteger(); @@ -424,9 +425,9 @@ TEST_F(PythonDataObjectsTest, TestPythonTupleToStructuredList) { auto array_sp = tuple.CreateStructuredArray(); EXPECT_EQ(tuple.GetSize(), array_sp->GetSize()); - EXPECT_EQ(StructuredData::Type::eTypeInteger, + EXPECT_EQ(lldb::eStructuredDataTypeInteger, array_sp->GetItemAtIndex(0)->GetType()); - EXPECT_EQ(StructuredData::Type::eTypeString, + EXPECT_EQ(lldb::eStructuredDataTypeString, array_sp->GetItemAtIndex(1)->GetType()); } From dfe1ca0d7aa4b8df73527e27644f0d97ab1e8306 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 30 May 2017 17:38:12 +0000 Subject: [PATCH 05/22] Vendor import of lldb trunk r304222: https://llvm.org/svn/llvm-project/lldb/trunk@304222 --- include/lldb/Utility/Log.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/lldb/Utility/Log.h b/include/lldb/Utility/Log.h index bfc0f4c9590a..d856fc81eb0d 100644 --- a/include/lldb/Utility/Log.h +++ b/include/lldb/Utility/Log.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringMap.h" // for StringMap #include "llvm/ADT/StringRef.h" // for StringRef, StringLiteral #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/RWMutex.h" #include @@ -30,9 +31,6 @@ namespace llvm { class raw_ostream; } -namespace llvm { -template class ManagedStatic; -} //---------------------------------------------------------------------- // Logging Options //---------------------------------------------------------------------- From 416ada0f75bab22b084a1776deb229cd4a669c4d Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Thu, 1 Jun 2017 20:58:49 +0000 Subject: [PATCH 06/22] Vendor import of clang trunk r304460: https://llvm.org/svn/llvm-project/cfe/trunk@304460 --- docs/Modules.rst | 2 +- docs/ThinLTO.rst | 2 + docs/UndefinedBehaviorSanitizer.rst | 2 + include/clang/AST/VTableBuilder.h | 22 + include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticIDs.h | 2 +- include/clang/Basic/DiagnosticSemaKinds.td | 4 +- include/clang/Basic/Module.h | 4 + include/clang/Basic/Sanitizers.def | 7 +- include/clang/Basic/TokenKinds.def | 2 +- include/clang/Basic/TypeTraits.h | 1 + include/clang/Driver/CLCompatOptions.td | 7 + include/clang/Driver/Options.td | 4 +- include/clang/Lex/HeaderSearch.h | 7 +- lib/AST/ODRHash.cpp | 28 +- lib/Basic/Targets.cpp | 16 + lib/CodeGen/ABIInfo.h | 1 - lib/CodeGen/CGCall.cpp | 18 +- lib/CodeGen/CGCleanup.cpp | 7 + lib/CodeGen/CGExpr.cpp | 60 +- lib/CodeGen/CGExprScalar.cpp | 210 ++- lib/CodeGen/CGObjCRuntime.cpp | 6 +- lib/CodeGen/CGVTables.cpp | 2 + lib/CodeGen/CodeGenFunction.h | 8 + lib/CodeGen/CodeGenModule.cpp | 31 +- lib/CodeGen/CodeGenModule.h | 11 +- lib/CodeGen/ItaniumCXXABI.cpp | 43 +- lib/CodeGen/MicrosoftCXXABI.cpp | 3 + lib/CodeGen/TargetInfo.cpp | 22 +- lib/Driver/ToolChains/Clang.cpp | 63 +- lib/Driver/ToolChains/Gnu.cpp | 12 +- lib/Format/UnwrappedLineParser.cpp | 25 +- lib/Frontend/CompilerInvocation.cpp | 4 +- lib/Frontend/FrontendAction.cpp | 20 +- lib/Lex/HeaderSearch.cpp | 17 +- lib/Sema/SemaCoroutine.cpp | 8 +- lib/Sema/SemaDecl.cpp | 11 + lib/Sema/SemaDeclObjC.cpp | 4 - lib/Sema/SemaExprCXX.cpp | 33 +- lib/Sema/SemaOverload.cpp | 298 ++-- lib/Sema/SemaType.cpp | 6 +- lib/Serialization/ASTWriter.cpp | 9 +- test/CodeGen/arm_neon_intrinsics.c | 1238 ++++++++--------- test/CodeGen/ubsan-pointer-overflow.m | 171 +++ test/CodeGenCXX/stmtexpr.cpp | 30 +- test/CodeGenCXX/strict-vtable-pointers.cpp | 115 +- .../vtable-available-externally.cpp | 32 +- test/CodeGenCXX/vtable-linkage.cpp | 6 +- .../coro-await-domination.cpp | 38 + test/CodeGenObjC/parameterized_classes.m | 28 + test/CodeGenOpenCL/bool_cast.cl | 2 +- test/CodeGenOpenCL/kernel-attributes.cl | 6 +- test/CodeGenOpenCL/kernel-metadata.cl | 2 +- .../kernels-have-spir-cc-by-default.cl | 65 + test/CodeGenOpenCL/pipe_types.cl | 2 +- test/CodeGenOpenCL/ptx-calls.cl | 2 +- test/CodeGenOpenCL/ptx-kernels.cl | 2 +- test/Driver/arm-cortex-cpus.c | 12 +- test/Driver/cl-cc-flags.c | 33 + test/Driver/cl-diagnostics.c | 28 + test/Driver/cl-include.c | 14 + test/Driver/cl-zc.cpp | 5 + test/Driver/fsanitize.c | 18 +- test/Driver/gold-lto.c | 2 +- test/Driver/nacl-direct.c | 2 +- test/Driver/openmp-offload.c | 8 +- test/Misc/diag-mapping2.c | 1 + test/Modules/odr_hash.cpp | 34 + test/Modules/preprocess-module.cpp | 10 +- test/Modules/preprocess-nested.cpp | 2 - test/Modules/preprocess-unavailable.cpp | 2 +- .../attr-require-constant-initialization.cpp | 72 +- test/SemaCXX/coreturn.cpp | 2 +- .../coroutine-uninitialized-warning-crash.cpp | 44 + test/SemaCXX/coroutines.cpp | 22 +- test/SemaCXX/type-traits.cpp | 96 ++ test/SemaObjC/attr-deprecated.m | 12 +- test/SemaObjC/class-unavail-warning.m | 4 +- .../warn-deprecated-implementations.m | 5 +- unittests/Format/FormatTestJS.cpp | 9 +- utils/TableGen/ClangAttrEmitter.cpp | 50 +- utils/TableGen/ClangDiagnosticsEmitter.cpp | 4 +- utils/TableGen/ClangOptionDocEmitter.cpp | 13 +- utils/TableGen/ClangSACheckersEmitter.cpp | 3 +- 84 files changed, 2272 insertions(+), 1017 deletions(-) create mode 100644 test/CodeGen/ubsan-pointer-overflow.m create mode 100644 test/CodeGenCoroutines/coro-await-domination.cpp create mode 100644 test/CodeGenOpenCL/kernels-have-spir-cc-by-default.cl create mode 100644 test/Driver/cl-cc-flags.c create mode 100644 test/Driver/cl-diagnostics.c create mode 100644 test/Driver/cl-include.c create mode 100644 test/SemaCXX/coroutine-uninitialized-warning-crash.cpp diff --git a/docs/Modules.rst b/docs/Modules.rst index b8841c0a5cec..7bd2adf8af52 100644 --- a/docs/Modules.rst +++ b/docs/Modules.rst @@ -403,7 +403,7 @@ A *requires-declaration* specifies the requirements that an importing translatio *feature*: ``!``:sub:`opt` *identifier* -The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. The optional ``!`` indicates that a feature is incompatible with the module. +The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. When building a module for use by a compilation, submodules requiring unavailable features are ignored. The optional ``!`` indicates that a feature is incompatible with the module. The following features are defined: diff --git a/docs/ThinLTO.rst b/docs/ThinLTO.rst index 7c7d9513025a..d417febda502 100644 --- a/docs/ThinLTO.rst +++ b/docs/ThinLTO.rst @@ -123,6 +123,8 @@ which currently must be enabled through a linker option. ``-Wl,-plugin-opt,cache-dir=/path/to/cache`` - ld64 (support in clang 3.9 and Xcode 8): ``-Wl,-cache_path_lto,/path/to/cache`` +- lld (as of LLVM r296702): + ``-Wl,--thinlto-cache-dir=/path/to/cache`` Clang Bootstrap --------------- diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst index d6fdad2a0c01..ea776a770470 100644 --- a/docs/UndefinedBehaviorSanitizer.rst +++ b/docs/UndefinedBehaviorSanitizer.rst @@ -106,6 +106,8 @@ Available checks are: invalid pointers. These checks are made in terms of ``__builtin_object_size``, and consequently may be able to detect more problems at higher optimization levels. + - ``-fsanitize=pointer-overflow``: Performing pointer arithmetic which + overflows. - ``-fsanitize=return``: In C++, reaching the end of a value-returning function without returning a value. - ``-fsanitize=returns-nonnull-attribute``: Returning null pointer diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h index 5cbcf51dd69b..b0b71e473516 100644 --- a/include/clang/AST/VTableBuilder.h +++ b/include/clang/AST/VTableBuilder.h @@ -154,6 +154,28 @@ class VTableComponent { bool isRTTIKind() const { return isRTTIKind(getKind()); } + GlobalDecl getGlobalDecl() const { + assert(isUsedFunctionPointerKind() && + "GlobalDecl can be created only from virtual function"); + + auto *DtorDecl = dyn_cast(getFunctionDecl()); + switch (getKind()) { + case CK_FunctionPointer: + return GlobalDecl(getFunctionDecl()); + case CK_CompleteDtorPointer: + return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete); + case CK_DeletingDtorPointer: + return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting); + case CK_VCallOffset: + case CK_VBaseOffset: + case CK_OffsetToTop: + case CK_RTTI: + case CK_UnusedFunctionPointer: + llvm_unreachable("Only function pointers kinds"); + } + llvm_unreachable("Should already return"); + } + private: static bool isFunctionPointerKind(Kind ComponentKind) { return isUsedFunctionPointerKind(ComponentKind) || diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index e1a41584023c..cf404768472f 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -733,6 +733,7 @@ def Pedantic : DiagGroup<"pedantic">; // Aliases. def : DiagGroup<"", [Extra]>; // -W = -Wextra def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wextra-tokens +def : DiagGroup<"cpp", [PoundWarning]>; // -Wcpp = -W#warnings def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment def : DiagGroup<"conversion-null", [NullConversion]>; // -Wconversion-null = -Wnull-conversion diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index 7646e33d2366..479d1978c62d 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -32,7 +32,7 @@ namespace clang { DIAG_START_FRONTEND = DIAG_START_DRIVER + 200, DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100, DIAG_START_LEX = DIAG_START_SERIALIZATION + 120, - DIAG_START_PARSE = DIAG_START_LEX + 300, + DIAG_START_PARSE = DIAG_START_LEX + 400, DIAG_START_AST = DIAG_START_PARSE + 500, DIAG_START_COMMENT = DIAG_START_AST + 110, DIAG_START_SEMA = DIAG_START_COMMENT + 100, diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 629e8b837f59..4de4f47b8a5a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -8979,10 +8979,10 @@ def err_coroutine_promise_new_requires_nothrow : Error< def note_coroutine_promise_call_implicitly_required : Note< "call to %0 implicitly required by coroutine function here">; def err_await_suspend_invalid_return_type : Error< - "the return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)" + "return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)" >; def note_await_ready_no_bool_conversion : Note< - "the return type of 'await_ready' is required to be contextually convertible to 'bool'" + "return type of 'await_ready' is required to be contextually convertible to 'bool'" >; } diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 28aa7db52992..326d84eeb6c2 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -83,6 +83,10 @@ class Module { /// are found. const DirectoryEntry *Directory; + /// \brief The presumed file name for the module map defining this module. + /// Only non-empty when building from preprocessed source. + std::string PresumedModuleMapFile; + /// \brief The umbrella header or directory. llvm::PointerUnion Umbrella; diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index f20d326e08f8..71b11974dbfd 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -73,6 +73,7 @@ SANITIZER("nullability-return", NullabilityReturn) SANITIZER_GROUP("nullability", Nullability, NullabilityArg | NullabilityAssign | NullabilityReturn) SANITIZER("object-size", ObjectSize) +SANITIZER("pointer-overflow", PointerOverflow) SANITIZER("return", Return) SANITIZER("returns-nonnull-attribute", ReturnsNonnullAttribute) SANITIZER("shift-base", ShiftBase) @@ -108,9 +109,9 @@ SANITIZER("safe-stack", SafeStack) SANITIZER_GROUP("undefined", Undefined, Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow | FloatDivideByZero | IntegerDivideByZero | NonnullAttribute | - Null | ObjectSize | Return | ReturnsNonnullAttribute | - Shift | SignedIntegerOverflow | Unreachable | VLABound | - Function | Vptr) + Null | ObjectSize | PointerOverflow | Return | + ReturnsNonnullAttribute | Shift | SignedIntegerOverflow | + Unreachable | VLABound | Function | Vptr) // -fsanitize=undefined-trap is an alias for -fsanitize=undefined. SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined) diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 968b203a3827..be67663a1015 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -411,6 +411,7 @@ TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS) // MSVC12.0 / VS2013 Type Traits TYPE_TRAIT_1(__is_destructible, IsDestructible, KEYMS) +TYPE_TRAIT_1(__is_trivially_destructible, IsTriviallyDestructible, KEYCXX) TYPE_TRAIT_1(__is_nothrow_destructible, IsNothrowDestructible, KEYMS) TYPE_TRAIT_2(__is_nothrow_assignable, IsNothrowAssignable, KEYCXX) TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX) @@ -439,7 +440,6 @@ TYPE_TRAIT_2(__is_convertible_to, IsConvertibleTo, KEYCXX) TYPE_TRAIT_1(__is_empty, IsEmpty, KEYCXX) TYPE_TRAIT_1(__is_enum, IsEnum, KEYCXX) TYPE_TRAIT_1(__is_final, IsFinal, KEYCXX) -// Tentative name - there's no implementation of std::is_literal_type yet. TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX) // Name for GCC 4.6 compatibility - people have already written libraries using // this name unfortunately. diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index ffe62559002e..6aadf795d82e 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -65,6 +65,7 @@ namespace clang { UTT_IsStandardLayout, UTT_IsTrivial, UTT_IsTriviallyCopyable, + UTT_IsTriviallyDestructible, UTT_IsUnion, UTT_IsUnsigned, UTT_IsVoid, diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index d0d9c679de7a..aebb36ed0e2b 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -63,6 +63,12 @@ def _SLASH_C : CLFlag<"C">, def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias; def _SLASH_d1reportAllClassLayout : CLFlag<"d1reportAllClassLayout">, HelpText<"Dump record layout information">, Alias; +def _SLASH_diagnostics_caret : CLFlag<"diagnostics:caret">, + HelpText<"Enable caret and column diagnostics (on by default)">; +def _SLASH_diagnostics_column : CLFlag<"diagnostics:column">, + HelpText<"Disable caret diagnostics but keep column info">; +def _SLASH_diagnostics_classic : CLFlag<"diagnostics:classic">, + HelpText<"Disable column and caret diagnostics">; def _SLASH_D : CLJoinedOrSeparate<"D">, HelpText<"Define macro">, MetaVarName<"">, Alias; def _SLASH_E : CLFlag<"E">, HelpText<"Preprocess to stdout">, Alias; @@ -324,6 +330,7 @@ def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">; def _SLASH_Zc_inline : CLIgnoredFlag<"Zc:inline">; def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">; def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">; +def _SLASH_Zc_ternary : CLIgnoredFlag<"Zc:ternary">; def _SLASH_Zm : CLIgnoredJoined<"Zm">; def _SLASH_Zo : CLIgnoredFlag<"Zo">; def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 2de4a2d1b419..12e36cc52b0b 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -2084,7 +2084,7 @@ def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[DriverOption]>; def no_pedantic : Flag<["-", "--"], "no-pedantic">, Group; def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_terms">; -def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option]>, +def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option, CoreOption]>, HelpText<"Disable builtin #include directories">; def nocudainc : Flag<["-"], "nocudainc">; def nocudalib : Flag<["-"], "nocudalib">; @@ -2096,7 +2096,7 @@ def nopie : Flag<["-"], "nopie">; def noprebind : Flag<["-"], "noprebind">; def noseglinkedit : Flag<["-"], "noseglinkedit">; def nostartfiles : Flag<["-"], "nostartfiles">; -def nostdinc : Flag<["-"], "nostdinc">; +def nostdinc : Flag<["-"], "nostdinc">, Flags<[CoreOption]>; def nostdlibinc : Flag<["-"], "nostdlibinc">; def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>, HelpText<"Disable standard #include directories for the C++ standard library">; diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 6e24e1893ab6..ee17dcbb8b5a 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -543,10 +543,13 @@ class HeaderSearch { /// \param Offset [inout] An offset within ID to start parsing. On exit, /// filled by the end of the parsed contents (either EOF or the /// location of an end-of-module-map pragma). - /// + /// \param OriginalModuleMapFile The original path to the module map file, + /// used to resolve paths within the module (this is required when + /// building the module from preprocessed source). /// \returns true if an error occurred, false otherwise. bool loadModuleMapFile(const FileEntry *File, bool IsSystem, - FileID ID = FileID(), unsigned *Offset = nullptr); + FileID ID = FileID(), unsigned *Offset = nullptr, + StringRef OriginalModuleMapFile = StringRef()); /// \brief Collect the set of all known, top-level modules. /// diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 24371db64d07..0e822ce35b8c 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -110,7 +110,24 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { } } -void ODRHash::AddTemplateName(TemplateName Name) {} +void ODRHash::AddTemplateName(TemplateName Name) { + auto Kind = Name.getKind(); + ID.AddInteger(Kind); + + switch (Kind) { + case TemplateName::Template: + AddDecl(Name.getAsTemplateDecl()); + break; + // TODO: Support these cases. + case TemplateName::OverloadedTemplate: + case TemplateName::QualifiedTemplate: + case TemplateName::DependentTemplate: + case TemplateName::SubstTemplateTemplateParm: + case TemplateName::SubstTemplateTemplateParmPack: + break; + } +} + void ODRHash::AddTemplateArgument(TemplateArgument TA) {} void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {} @@ -492,6 +509,15 @@ class ODRTypeVisitor : public TypeVisitor { AddQualType(T->getNamedType()); VisitTypeWithKeyword(T); } + + void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { + ID.AddInteger(T->getNumArgs()); + for (const auto &TA : T->template_arguments()) { + Hash.AddTemplateArgument(TA); + } + Hash.AddTemplateName(T->getTemplateName()); + VisitType(T); + } }; void ODRHash::AddType(const Type *T) { diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 6be83d22a256..605f73802afb 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -3123,6 +3123,7 @@ class X86TargetInfo : public TargetInfo { case CC_Swift: case CC_X86Pascal: case CC_IntelOclBicc: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -4834,6 +4835,7 @@ class X86_64TargetInfo : public X86TargetInfo { case CC_PreserveMost: case CC_PreserveAll: case CC_X86RegCall: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -4907,6 +4909,7 @@ class WindowsX86_64TargetInfo : public WindowsTargetInfo { case CC_X86_64SysV: case CC_Swift: case CC_X86RegCall: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -5860,6 +5863,7 @@ class ARMTargetInfo : public TargetInfo { case CC_AAPCS: case CC_AAPCS_VFP: case CC_Swift: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -6019,6 +6023,7 @@ class WindowsARMTargetInfo : public WindowsTargetInfo { case CC_X86VectorCall: return CCCR_Ignore; case CC_C: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -6329,6 +6334,7 @@ class AArch64TargetInfo : public TargetInfo { case CC_Swift: case CC_PreserveMost: case CC_PreserveAll: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -7380,6 +7386,7 @@ class SystemZTargetInfo : public TargetInfo { switch (CC) { case CC_C: case CC_Swift: + case CC_OpenCLKernel: return CCCR_OK; default: return CCCR_Warning; @@ -7663,6 +7670,15 @@ class BPFTargetInfo : public TargetInfo { ArrayRef getGCCRegAliases() const override { return None; } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_OpenCLKernel: + return CCCR_OK; + } + } }; class MipsTargetInfo : public TargetInfo { diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h index c0be60ef53bc..e4dce2f2a004 100644 --- a/lib/CodeGen/ABIInfo.h +++ b/lib/CodeGen/ABIInfo.h @@ -149,7 +149,6 @@ namespace swiftcall { return info->supportsSwift(); } }; - } // end namespace CodeGen } // end namespace clang diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index c677d9887acc..8f405eee6e52 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -707,6 +707,12 @@ CodeGenTypes::arrangeCall(const CGFunctionInfo &signature, signature.getRequiredArgs()); } +namespace clang { +namespace CodeGen { +void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); +} +} + /// Arrange the argument and result information for an abstract value /// of a given function type. This is the method which all of the /// above functions ultimately defer to. @@ -741,12 +747,16 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType, bool inserted = FunctionsBeingProcessed.insert(FI).second; (void)inserted; assert(inserted && "Recursively being processed?"); - + // Compute ABI information. - if (info.getCC() != CC_Swift) { - getABIInfo().computeInfo(*FI); - } else { + if (CC == llvm::CallingConv::SPIR_KERNEL) { + // Force target independent argument handling for the host visible + // kernel functions. + computeSPIRKernelABIInfo(CGM, *FI); + } else if (info.getCC() == CC_Swift) { swiftcall::computeABIInfo(CGM, *FI); + } else { + getABIInfo().computeInfo(*FI); } // Loop over all of the computed argument and return value info. If any of diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index e8bcf0a3ac56..b5453bc11e30 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -448,6 +448,13 @@ void CodeGenFunction::PopCleanupBlocks( auto *Inst = dyn_cast_or_null(*ReloadedValue); if (!Inst) continue; + + // Don't spill static allocas, they dominate all cleanups. These are created + // by binding a reference to a local variable or temporary. + auto *AI = dyn_cast(Inst); + if (AI && AI->isStaticAlloca()) + continue; + Address Tmp = CreateDefaultAlignTempAlloca(Inst->getType(), "tmp.exprcleanup"); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index b918a663ce5c..84ce896506d5 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -3002,9 +3002,10 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF, llvm::Value *ptr, ArrayRef indices, bool inbounds, + SourceLocation loc, const llvm::Twine &name = "arrayidx") { if (inbounds) { - return CGF.Builder.CreateInBoundsGEP(ptr, indices, name); + return CGF.EmitCheckedInBoundsGEP(ptr, indices, loc, name); } else { return CGF.Builder.CreateGEP(ptr, indices, name); } @@ -3035,8 +3036,9 @@ static QualType getFixedSizeElementType(const ASTContext &ctx, } static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, - ArrayRef indices, + ArrayRef indices, QualType eltType, bool inbounds, + SourceLocation loc, const llvm::Twine &name = "arrayidx") { // All the indices except that last must be zero. #ifndef NDEBUG @@ -3057,7 +3059,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); llvm::Value *eltPtr = - emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, name); + emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, loc, name); return Address(eltPtr, eltAlign); } @@ -3110,7 +3112,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, Address Addr = EmitExtVectorElementLValue(LV); QualType EltType = LV.getType()->castAs()->getElementType(); - Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true); + Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true, + E->getExprLoc()); return MakeAddrLValue(Addr, EltType, LV.getBaseInfo()); } @@ -3138,7 +3141,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, } Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(), - !getLangOpts().isSignedOverflowDefined()); + !getLangOpts().isSignedOverflowDefined(), + E->getExprLoc()); } else if (const ObjCObjectType *OIT = E->getType()->getAs()){ // Indexing over an interface, as in "NSString *P; P[4];" @@ -3163,8 +3167,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // Do the GEP. CharUnits EltAlign = getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); - llvm::Value *EltPtr = - emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false); + llvm::Value *EltPtr = emitArraySubscriptGEP( + *this, Addr.getPointer(), ScaledIdx, false, E->getExprLoc()); Addr = Address(EltPtr, EltAlign); // Cast back. @@ -3189,14 +3193,16 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, Addr = emitArraySubscriptGEP(*this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, E->getType(), - !getLangOpts().isSignedOverflowDefined()); + !getLangOpts().isSignedOverflowDefined(), + E->getExprLoc()); BaseInfo = ArrayLV.getBaseInfo(); } else { // The base must be a pointer; emit it with an estimate of its alignment. Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), - !getLangOpts().isSignedOverflowDefined()); + !getLangOpts().isSignedOverflowDefined(), + E->getExprLoc()); } LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo); @@ -3368,7 +3374,8 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, else Idx = Builder.CreateNSWMul(Idx, NumElements); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(), - !getLangOpts().isSignedOverflowDefined()); + !getLangOpts().isSignedOverflowDefined(), + E->getExprLoc()); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the // base to be a ArrayToPointerDecay implicit cast. While correct, it is @@ -3387,13 +3394,15 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, // Propagate the alignment from the array itself to the result. EltPtr = emitArraySubscriptGEP( *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, - ResultExprTy, !getLangOpts().isSignedOverflowDefined()); + ResultExprTy, !getLangOpts().isSignedOverflowDefined(), + E->getExprLoc()); BaseInfo = ArrayLV.getBaseInfo(); } else { Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, BaseTy, ResultExprTy, IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, - !getLangOpts().isSignedOverflowDefined()); + !getLangOpts().isSignedOverflowDefined(), + E->getExprLoc()); } return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo); @@ -3530,6 +3539,25 @@ static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base, return CGF.Builder.CreateStructGEP(base, idx, offset, field->getName()); } +static bool hasAnyVptr(const QualType Type, const ASTContext &Context) { + const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl(); + if (!RD) + return false; + + if (RD->isDynamicClass()) + return true; + + for (const auto &Base : RD->bases()) + if (hasAnyVptr(Base.getType(), Context)) + return true; + + for (const FieldDecl *Field : RD->fields()) + if (hasAnyVptr(Field->getType(), Context)) + return true; + + return false; +} + LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field) { LValueBaseInfo BaseInfo = base.getBaseInfo(); @@ -3572,6 +3600,14 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, assert(!type->isReferenceType() && "union has reference member"); // TODO: handle path-aware TBAA for union. TBAAPath = false; + + const auto FieldType = field->getType(); + if (CGM.getCodeGenOpts().StrictVTablePointers && + hasAnyVptr(FieldType, getContext())) + // Because unions can easily skip invariant.barriers, we need to add + // a barrier every time CXXRecord field with vptr is referenced. + addr = Address(Builder.CreateInvariantGroupBarrier(addr.getPointer()), + addr.getAlignment()); } else { // For structs, we GEP to the field that the record layout suggests. addr = emitAddrOfFieldStorage(*this, addr, field); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 048b50d8261d..d604b4130a23 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -30,6 +30,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" @@ -44,6 +45,43 @@ using llvm::Value; //===----------------------------------------------------------------------===// namespace { + +/// Determine whether the given binary operation may overflow. +/// Sets \p Result to the value of the operation for BO_Add, BO_Sub, BO_Mul, +/// and signed BO_{Div,Rem}. For these opcodes, and for unsigned BO_{Div,Rem}, +/// the returned overflow check is precise. The returned value is 'true' for +/// all other opcodes, to be conservative. +bool mayHaveIntegerOverflow(llvm::ConstantInt *LHS, llvm::ConstantInt *RHS, + BinaryOperator::Opcode Opcode, bool Signed, + llvm::APInt &Result) { + // Assume overflow is possible, unless we can prove otherwise. + bool Overflow = true; + const auto &LHSAP = LHS->getValue(); + const auto &RHSAP = RHS->getValue(); + if (Opcode == BO_Add) { + if (Signed) + Result = LHSAP.sadd_ov(RHSAP, Overflow); + else + Result = LHSAP.uadd_ov(RHSAP, Overflow); + } else if (Opcode == BO_Sub) { + if (Signed) + Result = LHSAP.ssub_ov(RHSAP, Overflow); + else + Result = LHSAP.usub_ov(RHSAP, Overflow); + } else if (Opcode == BO_Mul) { + if (Signed) + Result = LHSAP.smul_ov(RHSAP, Overflow); + else + Result = LHSAP.umul_ov(RHSAP, Overflow); + } else if (Opcode == BO_Div || Opcode == BO_Rem) { + if (Signed && !RHS->isZero()) + Result = LHSAP.sdiv_ov(RHSAP, Overflow); + else + return false; + } + return Overflow; +} + struct BinOpInfo { Value *LHS; Value *RHS; @@ -55,37 +93,14 @@ struct BinOpInfo { /// Check if the binop can result in integer overflow. bool mayHaveIntegerOverflow() const { // Without constant input, we can't rule out overflow. - const auto *LHSCI = dyn_cast(LHS); - const auto *RHSCI = dyn_cast(RHS); + auto *LHSCI = dyn_cast(LHS); + auto *RHSCI = dyn_cast(RHS); if (!LHSCI || !RHSCI) return true; - // Assume overflow is possible, unless we can prove otherwise. - bool Overflow = true; - const auto &LHSAP = LHSCI->getValue(); - const auto &RHSAP = RHSCI->getValue(); - if (Opcode == BO_Add) { - if (Ty->hasSignedIntegerRepresentation()) - (void)LHSAP.sadd_ov(RHSAP, Overflow); - else - (void)LHSAP.uadd_ov(RHSAP, Overflow); - } else if (Opcode == BO_Sub) { - if (Ty->hasSignedIntegerRepresentation()) - (void)LHSAP.ssub_ov(RHSAP, Overflow); - else - (void)LHSAP.usub_ov(RHSAP, Overflow); - } else if (Opcode == BO_Mul) { - if (Ty->hasSignedIntegerRepresentation()) - (void)LHSAP.smul_ov(RHSAP, Overflow); - else - (void)LHSAP.umul_ov(RHSAP, Overflow); - } else if (Opcode == BO_Div || Opcode == BO_Rem) { - if (Ty->hasSignedIntegerRepresentation() && !RHSCI->isZero()) - (void)LHSAP.sdiv_ov(RHSAP, Overflow); - else - return false; - } - return Overflow; + llvm::APInt Result; + return ::mayHaveIntegerOverflow( + LHSCI, RHSCI, Opcode, Ty->hasSignedIntegerRepresentation(), Result); } /// Check if the binop computes a division or a remainder. @@ -1925,7 +1940,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, numElts, "vla.inc"); else - value = Builder.CreateInBoundsGEP(value, numElts, "vla.inc"); + value = CGF.EmitCheckedInBoundsGEP(value, numElts, E->getExprLoc(), + "vla.inc"); // Arithmetic on function pointers (!) is just +-1. } else if (type->isFunctionType()) { @@ -1935,7 +1951,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, amt, "incdec.funcptr"); else - value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr"); + value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(), + "incdec.funcptr"); value = Builder.CreateBitCast(value, input->getType()); // For everything else, we can just do a simple increment. @@ -1944,7 +1961,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, amt, "incdec.ptr"); else - value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr"); + value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(), + "incdec.ptr"); } // Vector increment/decrement. @@ -2025,7 +2043,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, sizeValue, "incdec.objptr"); else - value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr"); + value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, E->getExprLoc(), + "incdec.objptr"); value = Builder.CreateBitCast(value, input->getType()); } @@ -2692,7 +2711,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr"); } else { index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index"); - pointer = CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr"); + pointer = CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(), + "add.ptr"); } return pointer; } @@ -2709,7 +2729,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, if (CGF.getLangOpts().isSignedOverflowDefined()) return CGF.Builder.CreateGEP(pointer, index, "add.ptr"); - return CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr"); + return CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(), + "add.ptr"); } // Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and @@ -3824,3 +3845,124 @@ LValue CodeGenFunction::EmitCompoundAssignmentLValue( llvm_unreachable("Unhandled compound assignment operator"); } + +Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, + ArrayRef IdxList, + SourceLocation Loc, + const Twine &Name) { + Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name); + + // If the pointer overflow sanitizer isn't enabled, do nothing. + if (!SanOpts.has(SanitizerKind::PointerOverflow)) + return GEPVal; + + // If the GEP has already been reduced to a constant, leave it be. + if (isa(GEPVal)) + return GEPVal; + + // Only check for overflows in the default address space. + if (GEPVal->getType()->getPointerAddressSpace()) + return GEPVal; + + auto *GEP = cast(GEPVal); + assert(GEP->isInBounds() && "Expected inbounds GEP"); + + SanitizerScope SanScope(this); + auto &VMContext = getLLVMContext(); + const auto &DL = CGM.getDataLayout(); + auto *IntPtrTy = DL.getIntPtrType(GEP->getPointerOperandType()); + + // Grab references to the signed add/mul overflow intrinsics for intptr_t. + auto *Zero = llvm::ConstantInt::getNullValue(IntPtrTy); + auto *SAddIntrinsic = + CGM.getIntrinsic(llvm::Intrinsic::sadd_with_overflow, IntPtrTy); + auto *SMulIntrinsic = + CGM.getIntrinsic(llvm::Intrinsic::smul_with_overflow, IntPtrTy); + + // The total (signed) byte offset for the GEP. + llvm::Value *TotalOffset = nullptr; + // The offset overflow flag - true if the total offset overflows. + llvm::Value *OffsetOverflows = Builder.getFalse(); + + /// Return the result of the given binary operation. + auto eval = [&](BinaryOperator::Opcode Opcode, llvm::Value *LHS, + llvm::Value *RHS) -> llvm::Value * { + assert(Opcode == BO_Add || Opcode == BO_Mul && "Can't eval binop"); + + // If the operands are constants, return a constant result. + if (auto *LHSCI = dyn_cast(LHS)) { + if (auto *RHSCI = dyn_cast(RHS)) { + llvm::APInt N; + bool HasOverflow = mayHaveIntegerOverflow(LHSCI, RHSCI, Opcode, + /*Signed=*/true, N); + if (HasOverflow) + OffsetOverflows = Builder.getTrue(); + return llvm::ConstantInt::get(VMContext, N); + } + } + + // Otherwise, compute the result with checked arithmetic. + auto *ResultAndOverflow = Builder.CreateCall( + (Opcode == BO_Add) ? SAddIntrinsic : SMulIntrinsic, {LHS, RHS}); + OffsetOverflows = Builder.CreateOr( + OffsetOverflows, Builder.CreateExtractValue(ResultAndOverflow, 1)); + return Builder.CreateExtractValue(ResultAndOverflow, 0); + }; + + // Determine the total byte offset by looking at each GEP operand. + for (auto GTI = llvm::gep_type_begin(GEP), GTE = llvm::gep_type_end(GEP); + GTI != GTE; ++GTI) { + llvm::Value *LocalOffset; + auto *Index = GTI.getOperand(); + // Compute the local offset contributed by this indexing step: + if (auto *STy = GTI.getStructTypeOrNull()) { + // For struct indexing, the local offset is the byte position of the + // specified field. + unsigned FieldNo = cast(Index)->getZExtValue(); + LocalOffset = llvm::ConstantInt::get( + IntPtrTy, DL.getStructLayout(STy)->getElementOffset(FieldNo)); + } else { + // Otherwise this is array-like indexing. The local offset is the index + // multiplied by the element size. + auto *ElementSize = llvm::ConstantInt::get( + IntPtrTy, DL.getTypeAllocSize(GTI.getIndexedType())); + auto *IndexS = Builder.CreateIntCast(Index, IntPtrTy, /*isSigned=*/true); + LocalOffset = eval(BO_Mul, ElementSize, IndexS); + } + + // If this is the first offset, set it as the total offset. Otherwise, add + // the local offset into the running total. + if (!TotalOffset || TotalOffset == Zero) + TotalOffset = LocalOffset; + else + TotalOffset = eval(BO_Add, TotalOffset, LocalOffset); + } + + // Common case: if the total offset is zero, don't emit a check. + if (TotalOffset == Zero) + return GEPVal; + + // Now that we've computed the total offset, add it to the base pointer (with + // wrapping semantics). + auto *IntPtr = Builder.CreatePtrToInt(GEP->getPointerOperand(), IntPtrTy); + auto *ComputedGEP = Builder.CreateAdd(IntPtr, TotalOffset); + + // The GEP is valid if: + // 1) The total offset doesn't overflow, and + // 2) The sign of the difference between the computed address and the base + // pointer matches the sign of the total offset. + llvm::Value *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr); + llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr); + auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero); + llvm::Value *ValidGEP = Builder.CreateAnd( + Builder.CreateNot(OffsetOverflows), + Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid)); + + llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc)}; + // Pass the computed GEP to the runtime to avoid emitting poisoned arguments. + llvm::Value *DynamicArgs[] = {IntPtr, ComputedGEP}; + EmitCheck(std::make_pair(ValidGEP, SanitizerKind::PointerOverflow), + SanitizerHandler::PointerOverflow, StaticArgs, DynamicArgs); + + return GEPVal; +} diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp index 3e3d04672357..b5599dad3096 100644 --- a/lib/CodeGen/CGObjCRuntime.cpp +++ b/lib/CodeGen/CGObjCRuntime.cpp @@ -90,7 +90,11 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, unsigned CVRQualifiers, llvm::Value *Offset) { // Compute (type*) ( (char *) BaseValue + Offset) - QualType IvarTy = Ivar->getType().withCVRQualifiers(CVRQualifiers); + QualType InterfaceTy{OID->getTypeForDecl(), 0}; + QualType ObjectPtrTy = + CGF.CGM.getContext().getObjCObjectPointerType(InterfaceTy); + QualType IvarTy = + Ivar->getUsageType(ObjectPtrTy).withCVRQualifiers(CVRQualifiers); llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy); V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr"); diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 1869c0e809df..64b6d0d3fe9f 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -901,6 +901,8 @@ void CodeGenModule::EmitDeferredVTables() { for (const CXXRecordDecl *RD : DeferredVTables) if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD)) VTables.GenerateClassData(RD); + else if (shouldOpportunisticallyEmitVTables()) + OpportunisticVTables.push_back(RD); assert(savedSize == DeferredVTables.size() && "deferred extra vtables during vtable emission?"); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 526ef9a1e579..42ffd0d3efcc 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -120,6 +120,7 @@ enum TypeEvaluationKind { SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \ SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) \ SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \ + SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \ SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \ SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \ SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \ @@ -3551,6 +3552,13 @@ class CodeGenFunction : public CodeGenTypeCache { /// nonnull, if \p LHS is marked _Nonnull. void EmitNullabilityCheck(LValue LHS, llvm::Value *RHS, SourceLocation Loc); + /// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to + /// detect undefined behavior when the pointer overflow sanitizer is enabled. + llvm::Value *EmitCheckedInBoundsGEP(llvm::Value *Ptr, + ArrayRef IdxList, + SourceLocation Loc, + const Twine &Name = ""); + /// \brief Emit a description of a type in a format suitable for passing to /// a runtime sanitizer handler. llvm::Constant *EmitCheckTypeDescriptor(QualType T); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index e4e5fce02279..c61a5f6ffa71 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -382,6 +382,7 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags, void CodeGenModule::Release() { EmitDeferred(); + EmitVTablesOpportunistically(); applyGlobalValReplacements(); applyReplacements(); checkAliases(); @@ -472,10 +473,10 @@ void CodeGenModule::Release() { // Width of wchar_t in bytes uint64_t WCharWidth = Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity(); - assert(LangOpts.ShortWChar || - llvm::TargetLibraryInfoImpl::getTargetWCharSize(Target.getTriple()) == - Target.getWCharWidth() / 8 && - "LLVM wchar_t size out of sync"); + assert((LangOpts.ShortWChar || + llvm::TargetLibraryInfoImpl::getTargetWCharSize(Target.getTriple()) == + Target.getWCharWidth() / 8) && + "LLVM wchar_t size out of sync"); // We need to record the widths of enums and wchar_t, so that we can generate // the correct build attributes in the ARM backend. wchar_size is also used by @@ -1386,6 +1387,24 @@ void CodeGenModule::EmitDeferred() { } } +void CodeGenModule::EmitVTablesOpportunistically() { + // Try to emit external vtables as available_externally if they have emitted + // all inlined virtual functions. It runs after EmitDeferred() and therefore + // is not allowed to create new references to things that need to be emitted + // lazily. Note that it also uses fact that we eagerly emitting RTTI. + + assert((OpportunisticVTables.empty() || shouldOpportunisticallyEmitVTables()) + && "Only emit opportunistic vtables with optimizations"); + + for (const CXXRecordDecl *RD : OpportunisticVTables) { + assert(getVTables().isVTableExternal(RD) && + "This queue should only contain external vtables"); + if (getCXXABI().canSpeculativelyEmitVTable(RD)) + VTables.GenerateClassData(RD); + } + OpportunisticVTables.clear(); +} + void CodeGenModule::EmitGlobalAnnotations() { if (Annotations.empty()) return; @@ -1906,6 +1925,10 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) { return !isTriviallyRecursive(F); } +bool CodeGenModule::shouldOpportunisticallyEmitVTables() { + return CodeGenOpts.OptimizationLevel > 0; +} + void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { const auto *D = cast(GD.getDecl()); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index e38337814ebc..0a71c635e8f0 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -341,6 +341,9 @@ class CodeGenModule : public CodeGenTypeCache { /// A queue of (optional) vtables to consider emitting. std::vector DeferredVTables; + /// A queue of (optional) vtables that may be emitted opportunistically. + std::vector OpportunisticVTables; + /// List of global values which are required to be present in the object file; /// bitcast to i8*. This is used for forcing visibility of symbols which may /// otherwise be optimized out. @@ -450,7 +453,7 @@ class CodeGenModule : public CodeGenTypeCache { bool isTriviallyRecursive(const FunctionDecl *F); bool shouldEmitFunction(GlobalDecl GD); - + bool shouldOpportunisticallyEmitVTables(); /// Map used to be sure we don't emit the same CompoundLiteral twice. llvm::DenseMap EmittedCompoundLiterals; @@ -1278,6 +1281,12 @@ class CodeGenModule : public CodeGenTypeCache { /// Emit any needed decls for which code generation was deferred. void EmitDeferred(); + /// Try to emit external vtables as available_externally if they have emitted + /// all inlined virtual functions. It runs after EmitDeferred() and therefore + /// is not allowed to create new references to things that need to be emitted + /// lazily. + void EmitVTablesOpportunistically(); + /// Call replaceAllUsesWith on all pairs in Replacements. void applyReplacements(); diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 66f51305430a..62b0e6155f99 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -366,20 +366,30 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override; private: - bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const { - const auto &VtableLayout = - CGM.getItaniumVTableContext().getVTableLayout(RD); + bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const { + const auto &VtableLayout = + CGM.getItaniumVTableContext().getVTableLayout(RD); - for (const auto &VtableComponent : VtableLayout.vtable_components()) { - // Skip empty slot. - if (!VtableComponent.isUsedFunctionPointerKind()) - continue; + for (const auto &VtableComponent : VtableLayout.vtable_components()) { + // Skip empty slot. + if (!VtableComponent.isUsedFunctionPointerKind()) + continue; - const CXXMethodDecl *Method = VtableComponent.getFunctionDecl(); - if (Method->getCanonicalDecl()->isInlined()) - return true; - } - return false; + const CXXMethodDecl *Method = VtableComponent.getFunctionDecl(); + if (!Method->getCanonicalDecl()->isInlined()) + continue; + + StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl()); + auto *Entry = CGM.GetGlobalValue(Name); + // This checks if virtual inline function has already been emitted. + // Note that it is possible that this inline function would be emitted + // after trying to emit vtable speculatively. Because of this we do + // an extra pass after emitting all deferred vtables to find and emit + // these vtables opportunistically. + if (!Entry || Entry->isDeclaration()) + return true; + } + return false; } bool isVTableHidden(const CXXRecordDecl *RD) const { @@ -1687,11 +1697,11 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const { if (CGM.getLangOpts().AppleKext) return false; - // If we don't have any inline virtual functions, and if vtable is not hidden, - // then we are safe to emit available_externally copy of vtable. + // If we don't have any not emitted inline virtual function, and if vtable is + // not hidden, then we are safe to emit available_externally copy of vtable. // FIXME we can still emit a copy of the vtable if we // can emit definition of the inline functions. - return !hasAnyVirtualInlineFunction(RD) && !isVTableHidden(RD); + return !hasAnyUnusedVirtualInlineFunction(RD) && !isVTableHidden(RD); } static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, Address InitialPtr, @@ -2576,6 +2586,9 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { if (!GV) { // Create a new global variable. + // Note for the future: If we would ever like to do deferred emission of + // RTTI, check if emitting vtables opportunistically need any adjustment. + GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, /*Constant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr, diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 4cacf494e694..ff5aca88131e 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -3756,6 +3756,9 @@ llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) { if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); + // Note for the future: If we would ever like to do deferred emission of + // RTTI, check if emitting vtables opportunistically need any adjustment. + // Compute the fields for the TypeDescriptor. SmallString<256> TypeInfoString; { diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index d0ba74119b7d..427ec06a2fff 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -398,7 +398,17 @@ TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib, } unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const { - return llvm::CallingConv::C; + // OpenCL kernels are called via an explicit runtime API with arguments + // set with clSetKernelArg(), not as normal sub-functions. + // Return SPIR_KERNEL by default as the kernel calling convention to + // ensure the fingerprint is fixed such way that each OpenCL argument + // gets one matching argument in the produced kernel function argument + // list to enable feasible implementation of clSetKernelArg() with + // aggregates etc. In case we would use the default C calling conv here, + // clSetKernelArg() might break depending on the target-specific + // conventions; different targets might split structs passed as values + // to multiple function arguments etc. + return llvm::CallingConv::SPIR_KERNEL; } llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM, @@ -8068,8 +8078,18 @@ class SPIRTargetCodeGenInfo : public TargetCodeGenInfo { CodeGen::CodeGenModule &M) const override; unsigned getOpenCLKernelCallingConv() const override; }; + } // End anonymous namespace. +namespace clang { +namespace CodeGen { +void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) { + DefaultABIInfo SPIRABI(CGM.getTypes()); + SPIRABI.computeInfo(FI); +} +} +} + /// Emit SPIR specific metadata: OpenCL and SPIR version. void SPIRTargetCodeGenInfo::emitTargetMD(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 555847aeeb23..698c3aa326cb 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3985,9 +3985,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, << value; } + bool CaretDefault = true; + bool ColumnDefault = true; + if (Arg *DiagArg = Args.getLastArg(options::OPT__SLASH_diagnostics_classic, + options::OPT__SLASH_diagnostics_column, + options::OPT__SLASH_diagnostics_caret)) { + switch (DiagArg->getOption().getID()) { + case options::OPT__SLASH_diagnostics_caret: + CaretDefault = true; + ColumnDefault = true; + break; + case options::OPT__SLASH_diagnostics_column: + CaretDefault = false; + ColumnDefault = true; + break; + case options::OPT__SLASH_diagnostics_classic: + CaretDefault = false; + ColumnDefault = false; + break; + } + } + // -fcaret-diagnostics is default. if (!Args.hasFlag(options::OPT_fcaret_diagnostics, - options::OPT_fno_caret_diagnostics, true)) + options::OPT_fno_caret_diagnostics, CaretDefault)) CmdArgs.push_back("-fno-caret-diagnostics"); // -fdiagnostics-fixit-info is default, only pass non-default. @@ -4059,7 +4080,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fdiagnostics-absolute-paths"); if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column, - true)) + ColumnDefault)) CmdArgs.push_back("-fno-show-column"); if (!Args.hasFlag(options::OPT_fspell_checking, @@ -4781,14 +4802,36 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, CmdArgs.push_back("-fms-memptr-rep=virtual"); } - if (Args.getLastArg(options::OPT__SLASH_Gd)) - CmdArgs.push_back("-fdefault-calling-conv=cdecl"); - else if (Args.getLastArg(options::OPT__SLASH_Gr)) - CmdArgs.push_back("-fdefault-calling-conv=fastcall"); - else if (Args.getLastArg(options::OPT__SLASH_Gz)) - CmdArgs.push_back("-fdefault-calling-conv=stdcall"); - else if (Args.getLastArg(options::OPT__SLASH_Gv)) - CmdArgs.push_back("-fdefault-calling-conv=vectorcall"); + // Parse the default calling convention options. + if (Arg *CCArg = + Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr, + options::OPT__SLASH_Gz, options::OPT__SLASH_Gv)) { + unsigned DCCOptId = CCArg->getOption().getID(); + const char *DCCFlag = nullptr; + bool ArchSupported = true; + llvm::Triple::ArchType Arch = getToolChain().getArch(); + switch (DCCOptId) { + case options::OPT__SLASH_Gd: + DCCFlag = "-fdefault-calling-conv=cdecl"; + break; + case options::OPT__SLASH_Gr: + ArchSupported = Arch == llvm::Triple::x86; + DCCFlag = "-fdefault-calling-conv=fastcall"; + break; + case options::OPT__SLASH_Gz: + ArchSupported = Arch == llvm::Triple::x86; + DCCFlag = "-fdefault-calling-conv=stdcall"; + break; + case options::OPT__SLASH_Gv: + ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64; + DCCFlag = "-fdefault-calling-conv=vectorcall"; + break; + } + + // MSVC doesn't warn if /Gr or /Gz is used on x64, so we don't either. + if (ArchSupported && DCCFlag) + CmdArgs.push_back(DCCFlag); + } if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ)) A->render(Args, CmdArgs); diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index 1a398fd8a773..d50f8e21f62f 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -278,20 +278,20 @@ static void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C, LksStream << "SECTIONS\n"; LksStream << "{\n"; - LksStream << " .omp_offloading :\n"; - LksStream << " ALIGN(0x10)\n"; - LksStream << " {\n"; - for (auto &BI : InputBinaryInfo) { - LksStream << " . = ALIGN(0x10);\n"; + // Put each target binary into a separate section. + for (const auto &BI : InputBinaryInfo) { + LksStream << " .omp_offloading." << BI.first << " :\n"; + LksStream << " ALIGN(0x10)\n"; + LksStream << " {\n"; LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first << " = .);\n"; LksStream << " " << BI.second << "\n"; LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first << " = .);\n"; + LksStream << " }\n"; } - LksStream << " }\n"; // Add commands to define host entries begin and end. We use 1-byte subalign // so that the linker does not add any padding and the elements in this // section form an array. diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index ae79ea5d8a66..eda7ef36434d 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -360,16 +360,21 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { switch (Tok->Tok.getKind()) { case tok::l_brace: - if (Style.Language == FormatStyle::LK_JavaScript && PrevTok && - PrevTok->is(tok::colon)) - // A colon indicates this code is in a type, or a braced list following - // a label in an object literal ({a: {b: 1}}). - // The code below could be confused by semicolons between the individual - // members in a type member list, which would normally trigger BK_Block. - // In both cases, this must be parsed as an inline braced init. - Tok->BlockKind = BK_BracedInit; - else + if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) { + if (PrevTok->is(tok::colon)) + // A colon indicates this code is in a type, or a braced list + // following a label in an object literal ({a: {b: 1}}). The code + // below could be confused by semicolons between the individual + // members in a type member list, which would normally trigger + // BK_Block. In both cases, this must be parsed as an inline braced + // init. + Tok->BlockKind = BK_BracedInit; + else if (PrevTok->is(tok::r_paren)) + // `) { }` can only occur in function or method declarations in JS. + Tok->BlockKind = BK_Block; + } else { Tok->BlockKind = BK_Unknown; + } LBraceStack.push_back(Tok); break; case tok::r_brace: @@ -391,6 +396,8 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { // BlockKind later if we parse a braced list (where all blocks // inside are by default braced lists), or when we explicitly detect // blocks (for example while parsing lambdas). + // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a + // braced list in JS. ProbablyBracedList = (Style.Language == FormatStyle::LK_JavaScript && NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 7d7e7d49e9f0..47c763d29357 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2214,8 +2214,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, llvm::Triple T(TargetOpts.Triple); llvm::Triple::ArchType Arch = T.getArch(); bool emitError = (DefaultCC == LangOptions::DCC_FastCall || - DefaultCC == LangOptions::DCC_StdCall) && - Arch != llvm::Triple::x86; + DefaultCC == LangOptions::DCC_StdCall) && + Arch != llvm::Triple::x86; emitError |= DefaultCC == LangOptions::DCC_VectorCall && !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64); if (emitError) diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 874c1b6be41e..cd67e469ddad 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -373,10 +373,11 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, return std::error_code(); } -static bool -loadModuleMapForModuleBuild(CompilerInstance &CI, StringRef Filename, - bool IsSystem, bool IsPreprocessed, - unsigned &Offset) { +static bool loadModuleMapForModuleBuild(CompilerInstance &CI, + StringRef Filename, bool IsSystem, + bool IsPreprocessed, + std::string &PresumedModuleMapFile, + unsigned &Offset) { auto &SrcMgr = CI.getSourceManager(); HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); @@ -388,16 +389,15 @@ loadModuleMapForModuleBuild(CompilerInstance &CI, StringRef Filename, // line directives are not part of the module map syntax in general. Offset = 0; if (IsPreprocessed) { - std::string PresumedModuleMapFile; SourceLocation EndOfLineMarker = ReadOriginalFileName(CI, PresumedModuleMapFile, /*AddLineNote*/true); if (EndOfLineMarker.isValid()) Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second; - // FIXME: Use PresumedModuleMapFile as the MODULE_MAP_FILE in the PCM. } // Load the module map file. - if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset)) + if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset, + PresumedModuleMapFile)) return true; if (SrcMgr.getBuffer(ModuleMapID)->getBufferSize() == Offset) @@ -664,15 +664,19 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (Input.getKind().getFormat() == InputKind::ModuleMap) { CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap); + std::string PresumedModuleMapFile; unsigned OffsetToContents; if (loadModuleMapForModuleBuild(CI, Input.getFile(), Input.isSystem(), - Input.isPreprocessed(), OffsetToContents)) + Input.isPreprocessed(), + PresumedModuleMapFile, OffsetToContents)) goto failure; auto *CurrentModule = prepareToBuildModule(CI, Input.getFile()); if (!CurrentModule) goto failure; + CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile; + if (OffsetToContents) // If the module contents are in the same file, skip to them. CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true); diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index f5b7c59e446f..9084bc352f76 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -1326,14 +1326,27 @@ static const FileEntry *getPrivateModuleMap(const FileEntry *File, } bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, - FileID ID, unsigned *Offset) { + FileID ID, unsigned *Offset, + StringRef OriginalModuleMapFile) { // Find the directory for the module. For frameworks, that may require going // up from the 'Modules' directory. const DirectoryEntry *Dir = nullptr; if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) Dir = FileMgr.getDirectory("."); else { - Dir = File->getDir(); + if (!OriginalModuleMapFile.empty()) { + // We're building a preprocessed module map. Find or invent the directory + // that it originally occupied. + Dir = FileMgr.getDirectory( + llvm::sys::path::parent_path(OriginalModuleMapFile)); + if (!Dir) { + auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0); + Dir = FakeFile->getDir(); + } + } else { + Dir = File->getDir(); + } + StringRef DirName(Dir->getName()); if (llvm::sys::path::filename(DirName) == "Modules") { DirName = llvm::sys::path::parent_path(DirName); diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index ae6c35f22065..8a548c0ab861 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -391,8 +391,11 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, // [expr.await]p3 [...] // - await-suspend is the expression e.await_suspend(h), which shall be // a prvalue of type void or bool. - QualType RetType = AwaitSuspend->getType(); - if (RetType != S.Context.BoolTy && RetType != S.Context.VoidTy) { + QualType RetType = AwaitSuspend->getCallReturnType(S.Context); + // non-class prvalues always have cv-unqualified types + QualType AdjRetType = RetType.getUnqualifiedType(); + if (RetType->isReferenceType() || + (AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) { S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(), diag::err_await_suspend_invalid_return_type) << RetType; @@ -437,6 +440,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { if (VD->isInvalidDecl()) return nullptr; ActOnUninitializedDecl(VD); + FD->addDecl(VD); assert(!VD->isInvalidDecl()); return VD; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a9adbec4f842..ea1f7526a832 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -11116,6 +11116,17 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { << Init->getSourceRange(); Diag(attr->getLocation(), diag::note_declared_required_constant_init_here) << attr->getRange(); + if (getLangOpts().CPlusPlus11) { + APValue Value; + SmallVector Notes; + Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes); + for (auto &it : Notes) + Diag(it.first, it.second); + } else { + Diag(CacheCulprit->getExprLoc(), + diag::note_invalid_subexpr_in_const_expr) + << CacheCulprit->getSourceRange(); + } } } else if (!var->isConstexpr() && IsGlobal && diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 370461c4a24e..2c8080dbf02b 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1851,10 +1851,6 @@ Decl *Sema::ActOnStartCategoryImplementation( // FIXME: PushOnScopeChains? CurContext->addDecl(CDecl); - // If the interface is deprecated/unavailable, warn/error about it. - if (IDecl) - DiagnoseUseOfDecl(IDecl, ClassLoc); - // If the interface has the objc_runtime_visible attribute, we // cannot implement a category for it. if (IDecl && IDecl->hasAttr()) { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 8500b748a3ec..a05f7a7e406b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4080,24 +4080,23 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr); return true; - // C++0x [meta.unary.prop] Table 49 requires the following traits to be - // applied to a complete type. + // C++1z [meta.unary.prop]: + // remove_all_extents_t shall be a complete type or cv void. case UTT_IsAggregate: case UTT_IsTrivial: case UTT_IsTriviallyCopyable: case UTT_IsStandardLayout: case UTT_IsPOD: case UTT_IsLiteral: + ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0); + LLVM_FALLTHROUGH; + // C++1z [meta.unary.prop]: + // T shall be a complete type, cv void, or an array of unknown bound. case UTT_IsDestructible: case UTT_IsNothrowDestructible: - // Fall-through - - // These trait expressions are designed to help implement predicates in - // [meta.unary.prop] despite not being named the same. They are specified - // by both GCC and the Embarcadero C++ compiler, and require the complete - // type due to the overarching C++0x type predicates being implemented - // requiring the complete type. + case UTT_IsTriviallyDestructible: + // Per the GCC type traits documentation, the same constraints apply to these. case UTT_HasNothrowAssign: case UTT_HasNothrowMoveAssign: case UTT_HasNothrowConstructor: @@ -4109,17 +4108,11 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: - // Arrays of unknown bound are expressly allowed. - QualType ElTy = ArgTy; - if (ArgTy->isIncompleteArrayType()) - ElTy = S.Context.getAsArrayType(ArgTy)->getElementType(); - - // The void type is expressly allowed. - if (ElTy->isVoidType()) + if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType()) return true; return !S.RequireCompleteType( - Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr); + Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr); } } @@ -4356,6 +4349,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, !RD->hasNonTrivialCopyAssignment(); return false; case UTT_IsDestructible: + case UTT_IsTriviallyDestructible: case UTT_IsNothrowDestructible: // C++14 [meta.unary.prop]: // For reference types, is_destructible::value is true. @@ -4373,6 +4367,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, if (T->isIncompleteType() || T->isFunctionType()) return false; + // A type that requires destruction (via a non-trivial destructor or ARC + // lifetime semantics) is not trivially-destructible. + if (UTT == UTT_IsTriviallyDestructible && T.isDestructedType()) + return false; + // C++14 [meta.unary.prop]: // For object types and given U equal to remove_all_extents_t, if the // expression std::declval().~U() is well-formed when treated as an diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 1ba84034fa47..7bdd8872456a 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -49,12 +49,12 @@ static bool functionHasPassObjectSizeParams(const FunctionDecl *FD) { static ExprResult CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, bool HadMultipleCandidates, - SourceLocation Loc = SourceLocation(), + SourceLocation Loc = SourceLocation(), const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ if (S.DiagnoseUseOfDecl(FoundDecl, Loc)) - return ExprError(); + return ExprError(); // If FoundDecl is different from Fn (such as if one is a template - // and the other a specialization), make sure DiagnoseUseOfDecl is + // and the other a specialization), make sure DiagnoseUseOfDecl is // called on both. // FIXME: This would be more comprehensively addressed by modifying // DiagnoseUseOfDecl to accept both the FoundDecl and the decl @@ -79,7 +79,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, bool CStyle, bool AllowObjCWritebackConversion); -static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From, +static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From, QualType &ToType, bool InOverloadResolution, StandardConversionSequence &SCS, @@ -330,13 +330,13 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) { llvm::APSInt IntConstantValue; const Expr *Initializer = IgnoreNarrowingConversion(Converted); + assert(Initializer && "Unknown conversion expression"); // If it's value-dependent, we can't tell whether it's narrowing. if (Initializer->isValueDependent()) return NK_Dependent_Narrowing; - if (Initializer && - Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { + if (Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { // Convert the integer to the floating type. llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType)); Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(), @@ -852,7 +852,7 @@ namespace { Expr *Saved; }; SmallVector Entries; - + public: void save(Sema &S, Expr *&E) { assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); @@ -863,7 +863,7 @@ namespace { void restore() { for (SmallVectorImpl::iterator - i = Entries.begin(), e = Entries.end(); i != e; ++i) + i = Entries.begin(), e = Entries.end(); i != e; ++i) *i->Addr = i->Saved; } }; @@ -1368,9 +1368,9 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion) { - return ::TryImplicitConversion(*this, From, ToType, + return ::TryImplicitConversion(*this, From, ToType, SuppressUserConversions, AllowExplicit, - InOverloadResolution, CStyle, + InOverloadResolution, CStyle, AllowObjCWritebackConversion, /*AllowObjCConversionOnExplicit=*/false); } @@ -1396,7 +1396,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // Objective-C ARC: Determine whether we will allow the writeback conversion. bool AllowObjCWritebackConversion - = getLangOpts().ObjCAutoRefCount && + = getLangOpts().ObjCAutoRefCount && (Action == AA_Passing || Action == AA_Sending); if (getLangOpts().ObjC1) CheckObjCBridgeRelatedConversions(From->getLocStart(), @@ -1592,15 +1592,15 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // if the function type matches except for [[noreturn]], it's ok if (!S.IsFunctionConversion(FromType, S.ExtractUnqualifiedFunctionType(ToType), resultTy)) - // otherwise, only a boolean conversion is standard - if (!ToType->isBooleanType()) - return false; + // otherwise, only a boolean conversion is standard + if (!ToType->isBooleanType()) + return false; } // Check if the "from" expression is taking the address of an overloaded // function and recompute the FromType accordingly. Take advantage of the // fact that non-static member functions *must* have such an address-of - // expression. + // expression. CXXMethodDecl *Method = dyn_cast(Fn); if (Method && !Method->isStatic()) { assert(isa(From->IgnoreParens()) && @@ -1638,7 +1638,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, SCS.First = ICK_Lvalue_To_Rvalue; // C11 6.3.2.1p2: - // ... if the lvalue has atomic type, the value has the non-atomic version + // ... if the lvalue has atomic type, the value has the non-atomic version // of the type of the lvalue ... if (const AtomicType *Atomic = FromType->getAs()) FromType = Atomic->getValueType(); @@ -1890,12 +1890,12 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, } static bool -IsTransparentUnionStandardConversion(Sema &S, Expr* From, +IsTransparentUnionStandardConversion(Sema &S, Expr* From, QualType &ToType, bool InOverloadResolution, StandardConversionSequence &SCS, bool CStyle) { - + const RecordType *UT = ToType->getAsUnionType(); if (!UT || !UT->getDecl()->hasAttr()) return false; @@ -2129,7 +2129,7 @@ BuildSimilarlyQualifiedPointerType(const Type *FromPtr, "Invalid similarly-qualified pointer type"); /// Conversions to 'id' subsume cv-qualifier conversions. - if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType()) + if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType()) return ToType.getUnqualifiedType(); QualType CanonFromPointee @@ -2139,7 +2139,7 @@ BuildSimilarlyQualifiedPointerType(const Type *FromPtr, if (StripObjCLifetime) Quals.removeObjCLifetime(); - + // Exact qualifier match -> return the pointer type we're converting to. if (CanonToPointee.getLocalQualifiers() == Quals) { // ToType is exactly what we need. Return it. @@ -2323,21 +2323,21 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, ToType, Context); return true; } - + return false; } - + /// \brief Adopt the given qualifiers for the given type. static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ Qualifiers TQs = T.getQualifiers(); - + // Check whether qualifiers already match. if (TQs == Qs) return T; - + if (Qs.compatiblyIncludes(TQs)) return Context.getQualifiedType(T, Qs); - + return Context.getQualifiedType(T.getUnqualifiedType(), Qs); } @@ -2352,7 +2352,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, // The set of qualifiers on the type we're converting from. Qualifiers FromQualifiers = FromType.getQualifiers(); - + // First, we handle all conversions on ObjC object pointer types. const ObjCObjectPointerType* ToObjCPtr = ToType->getAs(); @@ -2443,7 +2443,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ToPointeeType->getAs() && isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, IncompatibleObjC)) { - + ConvertedType = Context.getPointerType(ConvertedType); ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); return true; @@ -2526,46 +2526,46 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, /// this conversion. bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType, QualType &ConvertedType) { - if (!getLangOpts().ObjCAutoRefCount || + if (!getLangOpts().ObjCAutoRefCount || Context.hasSameUnqualifiedType(FromType, ToType)) return false; - + // Parameter must be a pointer to __autoreleasing (with no other qualifiers). QualType ToPointee; if (const PointerType *ToPointer = ToType->getAs()) ToPointee = ToPointer->getPointeeType(); else return false; - + Qualifiers ToQuals = ToPointee.getQualifiers(); - if (!ToPointee->isObjCLifetimeType() || + if (!ToPointee->isObjCLifetimeType() || ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing || !ToQuals.withoutObjCLifetime().empty()) return false; - + // Argument must be a pointer to __strong to __weak. QualType FromPointee; if (const PointerType *FromPointer = FromType->getAs()) FromPointee = FromPointer->getPointeeType(); else return false; - + Qualifiers FromQuals = FromPointee.getQualifiers(); if (!FromPointee->isObjCLifetimeType() || (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong && FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak)) return false; - + // Make sure that we have compatible qualifiers. FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing); if (!ToQuals.compatiblyIncludes(FromQuals)) return false; - + // Remove qualifiers from the pointee type we're converting from; they // aren't used in the compatibility check belong, and we'll be adding back // qualifiers (with __autoreleasing) if the compatibility check succeeds. FromPointee = FromPointee.getUnqualifiedType(); - + // The unqualified form of the pointee types must be compatible. ToPointee = ToPointee.getUnqualifiedType(); bool IncompatibleObjC; @@ -2574,7 +2574,7 @@ bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType, else if (!isObjCPointerConversion(FromPointee, ToPointee, FromPointee, IncompatibleObjC)) return false; - + /// \brief Construct the type we're converting to, which is a pointer to /// __autoreleasing pointee. FromPointee = Context.getQualifiedType(FromPointee, FromQuals); @@ -2590,7 +2590,7 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, ToPointeeType = ToBlockPtr->getPointeeType(); else return false; - + QualType FromPointeeType; if (const BlockPointerType *FromBlockPtr = FromType->getAs()) @@ -2600,24 +2600,24 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, // We have pointer to blocks, check whether the only // differences in the argument and result types are in Objective-C // pointer conversions. If so, we permit the conversion. - + const FunctionProtoType *FromFunctionType = FromPointeeType->getAs(); const FunctionProtoType *ToFunctionType = ToPointeeType->getAs(); - + if (!FromFunctionType || !ToFunctionType) return false; if (Context.hasSameType(FromPointeeType, ToPointeeType)) return true; - + // Perform the quick checks that will tell us whether these // function types are obviously different. if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() || FromFunctionType->isVariadic() != ToFunctionType->isVariadic()) return false; - + FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo(); FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo(); if (FromEInfo != ToEInfo) @@ -2645,7 +2645,7 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, else return false; } - + // Check argument types. for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams(); ArgIdx != NumArgs; ++ArgIdx) { @@ -2666,7 +2666,7 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, if (!Context.doFunctionTypesMatchOnExtParameterInfos(FromFunctionType, ToFunctionType)) return false; - + ConvertedType = ToType; return true; } @@ -3012,7 +3012,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals, Qualifiers ToQuals) { // Converting anything to const __unsafe_unretained is trivial. - if (ToQuals.hasConst() && + if (ToQuals.hasConst() && ToQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone) return false; @@ -3032,7 +3032,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, FromType = Context.getCanonicalType(FromType); ToType = Context.getCanonicalType(ToType); ObjCLifetimeConversion = false; - + // If FromType and ToType are the same type, this is not a // qualification conversion. if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType()) @@ -3058,7 +3058,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, // Ignore __unaligned qualifier if this type is void. if (ToType.getUnqualifiedType()->isVoidType()) FromQuals.removeUnaligned(); - + // Objective-C ARC: // Check Objective-C lifetime conversions. if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() && @@ -3074,14 +3074,14 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, return false; } } - + // Allow addition/removal of GC attributes but not changing GC attributes. if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() && (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) { FromQuals.removeObjCGCAttr(); ToQuals.removeObjCGCAttr(); } - + // -- for every j > 0, if const is in cv 1,j then const is in cv // 2,j, and similarly for volatile. if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals)) @@ -3119,13 +3119,13 @@ static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType, const AtomicType *ToAtomic = ToType->getAs(); if (!ToAtomic) return false; - + StandardConversionSequence InnerSCS; - if (!IsStandardConversion(S, From, ToAtomic->getValueType(), + if (!IsStandardConversion(S, From, ToAtomic->getValueType(), InOverloadResolution, InnerSCS, CStyle, /*AllowObjCWritebackConversion=*/false)) return false; - + SCS.Second = InnerSCS.Second; SCS.setToType(1, InnerSCS.getToType(1)); SCS.Third = InnerSCS.Third; @@ -3180,8 +3180,8 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, bool HadMultipleCandidates = (CandidateSet.size() > 1); OverloadCandidateSet::iterator Best; - switch (auto Result = - CandidateSet.BestViableFunction(S, From->getLocStart(), + switch (auto Result = + CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { case OR_Deleted: case OR_Success: { @@ -3552,7 +3552,7 @@ CompareImplicitConversionSequences(Sema &S, SourceLocation Loc, // Two implicit conversion sequences of the same form are // indistinguishable conversion sequences unless one of the // following rules apply: (C++ 13.3.3.2p3): - + // List-initialization sequence L1 is a better conversion sequence than // list-initialization sequence L2 if: // - L1 converts to std::initializer_list for some X and L2 does not, or, @@ -3587,7 +3587,7 @@ CompareImplicitConversionSequences(Sema &S, SourceLocation Loc, ICS1.UserDefined.After, ICS2.UserDefined.After); else - Result = compareConversionFunctions(S, + Result = compareConversionFunctions(S, ICS1.UserDefined.ConversionFunction, ICS2.UserDefined.ConversionFunction); } @@ -3769,9 +3769,9 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc, const ObjCObjectPointerType* FromObjCPtr2 = FromType2->getAs(); if (FromObjCPtr1 && FromObjCPtr2) { - bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1, + bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1, FromObjCPtr2); - bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2, + bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2, FromObjCPtr1); if (AssignLeft != AssignRight) { return AssignLeft? ImplicitConversionSequence::Better @@ -3809,13 +3809,13 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc, if (UnqualT1 == UnqualT2) { // Objective-C++ ARC: If the references refer to objects with different // lifetimes, prefer bindings that don't change lifetime. - if (SCS1.ObjCLifetimeConversionBinding != + if (SCS1.ObjCLifetimeConversionBinding != SCS2.ObjCLifetimeConversionBinding) { return SCS1.ObjCLifetimeConversionBinding ? ImplicitConversionSequence::Worse : ImplicitConversionSequence::Better; } - + // If the type is an array type, promote the element qualifiers to the // type for comparison. if (isa(T1) && T1Quals) @@ -3825,7 +3825,7 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc, if (T2.isMoreQualifiedThan(T1)) return ImplicitConversionSequence::Better; else if (T1.isMoreQualifiedThan(T2)) - return ImplicitConversionSequence::Worse; + return ImplicitConversionSequence::Worse; } } @@ -3891,17 +3891,17 @@ CompareQualificationConversions(Sema &S, ImplicitConversionSequence::CompareKind Result = ImplicitConversionSequence::Indistinguishable; - + // Objective-C++ ARC: // Prefer qualification conversions not involving a change in lifetime // to qualification conversions that do not change lifetime. - if (SCS1.QualificationIncludesObjCLifetime != + if (SCS1.QualificationIncludesObjCLifetime != SCS2.QualificationIncludesObjCLifetime) { Result = SCS1.QualificationIncludesObjCLifetime ? ImplicitConversionSequence::Worse : ImplicitConversionSequence::Better; } - + while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) { // Within each iteration of the loop, we check the qualifiers to // determine if this still looks like a qualification @@ -4033,7 +4033,7 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, = ToType1->getAs(); const ObjCObjectPointerType *ToPtr2 = ToType2->getAs(); - + if (FromPtr1 && FromPtr2 && ToPtr1 && ToPtr2) { // Apply the same conversion ranking rules for Objective-C pointer types // that we do for C++ pointers to class types. However, we employ the @@ -4048,7 +4048,7 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, bool ToAssignRight = S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1); - // A conversion to an a non-id object pointer type or qualified 'id' + // A conversion to an a non-id object pointer type or qualified 'id' // type is better than a conversion to 'id'. if (ToPtr1->isObjCIdType() && (ToPtr2->isObjCQualifiedIdType() || ToPtr2->getInterfaceDecl())) @@ -4056,15 +4056,15 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, if (ToPtr2->isObjCIdType() && (ToPtr1->isObjCQualifiedIdType() || ToPtr1->getInterfaceDecl())) return ImplicitConversionSequence::Better; - - // A conversion to a non-id object pointer type is better than a - // conversion to a qualified 'id' type + + // A conversion to a non-id object pointer type is better than a + // conversion to a qualified 'id' type if (ToPtr1->isObjCQualifiedIdType() && ToPtr2->getInterfaceDecl()) return ImplicitConversionSequence::Worse; if (ToPtr2->isObjCQualifiedIdType() && ToPtr1->getInterfaceDecl()) return ImplicitConversionSequence::Better; - - // A conversion to an a non-Class object pointer type or qualified 'Class' + + // A conversion to an a non-Class object pointer type or qualified 'Class' // type is better than a conversion to 'Class'. if (ToPtr1->isObjCClassType() && (ToPtr2->isObjCQualifiedClassType() || ToPtr2->getInterfaceDecl())) @@ -4072,8 +4072,8 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, if (ToPtr2->isObjCClassType() && (ToPtr1->isObjCQualifiedClassType() || ToPtr1->getInterfaceDecl())) return ImplicitConversionSequence::Better; - - // A conversion to a non-Class object pointer type is better than a + + // A conversion to a non-Class object pointer type is better than a // conversion to a qualified 'Class' type. if (ToPtr1->isObjCQualifiedClassType() && ToPtr2->getInterfaceDecl()) return ImplicitConversionSequence::Worse; @@ -4108,7 +4108,7 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, : ImplicitConversionSequence::Worse; } } - + // Ranking of member-pointer types. if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member && FromType1->isMemberPointerType() && FromType2->isMemberPointerType() && @@ -4264,9 +4264,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, ObjCLifetimeConversion = true; T1Quals.removeObjCLifetime(); - T2Quals.removeObjCLifetime(); + T2Quals.removeObjCLifetime(); } - + // MS compiler ignores __unaligned qualifier for references; do the same. T1Quals.removeUnaligned(); T2Quals.removeUnaligned(); @@ -4313,7 +4313,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, bool DerivedToBase = false; bool ObjCConversion = false; bool ObjCLifetimeConversion = false; - + // If we are initializing an rvalue reference, don't permit conversion // functions that return lvalues. if (!ConvTemplate && DeclType->isRValueReferenceType()) { @@ -4322,7 +4322,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, if (RefType && !RefType->getPointeeType()->isFunctionType()) continue; } - + if (!ConvTemplate && S.CompareReferenceRelationship( DeclLoc, @@ -6051,24 +6051,24 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance, NumNamedArgs = Method->param_size(); if (Args.size() < NumNamedArgs) continue; - + for (unsigned i = 0; i < NumNamedArgs; i++) { // We can't do any type-checking on a type-dependent argument. if (Args[i]->isTypeDependent()) { Match = false; break; } - + ParmVarDecl *param = Method->parameters()[i]; Expr *argExpr = Args[i]; assert(argExpr && "SelectBestMethod(): missing expression"); - + // Strip the unbridged-cast placeholder expression off unless it's // a consumed argument. if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) && !param->hasAttr()) argExpr = stripARCUnbridgedCast(argExpr); - + // If the parameter is __unknown_anytype, move on to the next method. if (param->getType() == Context.UnknownAnyTy) { Match = false; @@ -6754,7 +6754,7 @@ static bool isAllowableExplicitConversion(Sema &S, return S.isObjCPointerConversion(ConvType, ToNonRefType, ConvertedType, IncompatibleObjC); } - + /// AddConversionCandidate - Add a C++ conversion function as a /// candidate in the candidate set (C++ [over.match.conv], /// C++ [over.match.copy]). From is the expression we're converting from, @@ -6785,8 +6785,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // Per C++ [over.match.conv]p1, [over.match.ref]p1, an explicit conversion // operator is only a candidate if its return type is the target type or // can be converted to the target type with a qualification conversion. - if (Conversion->isExplicit() && - !isAllowableExplicitConversion(*this, ConvType, ToType, + if (Conversion->isExplicit() && + !isAllowableExplicitConversion(*this, ConvType, ToType, AllowObjCConversionOnExplicit)) return; @@ -7230,7 +7230,7 @@ class BuiltinCandidateTypeSet { /// \brief A flag indicating whether the nullptr type was present in the /// candidate set. bool HasNullPtrType; - + /// Sema - The semantic analysis instance where we are building the /// candidate type set. Sema &SemaRef; @@ -7314,14 +7314,14 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, } else { PointeeTy = PointerTy->getPointeeType(); } - + // Don't add qualified variants of arrays. For one, they're not allowed // (the qualifier would sink to the element type), and for another, the // only overload situation where it matters is subscript or pointer +- int, // and those shouldn't have qualifier variants anyway. if (PointeeTy->isArrayType()) return true; - + unsigned BaseCVR = PointeeTy.getCVRQualifiers(); bool hasVolatile = VisibleQuals.hasVolatile(); bool hasRestrict = VisibleQuals.hasRestrict(); @@ -7331,24 +7331,24 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, if ((CVR | BaseCVR) != CVR) continue; // Skip over volatile if no volatile found anywhere in the types. if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue; - + // Skip over restrict if no restrict found anywhere in the types, or if // the type cannot be restrict-qualified. if ((CVR & Qualifiers::Restrict) && (!hasRestrict || (!(PointeeTy->isAnyPointerType() || PointeeTy->isReferenceType())))) continue; - + // Build qualified pointee type. QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); - + // Build qualified pointer type. QualType QPointerTy; if (!buildObjCPtr) QPointerTy = Context.getPointerType(QPointeeTy); else QPointerTy = Context.getObjCObjectPointerType(QPointeeTy); - + // Insert qualified pointer type. PointerTypes.insert(QPointerTy); } @@ -7705,7 +7705,7 @@ class BuiltinOperatorOverloadBuilder { else S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); } - + // Add restrict version only if there are conversions to a restrict type // and our candidate type is a non-restrict-qualified pointer. if (HasRestrict && CandidateTy->isAnyPointerType() && @@ -7717,7 +7717,7 @@ class BuiltinOperatorOverloadBuilder { S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet); else S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet); - + if (HasVolatile) { ParamTypes[0] = S.Context.getLValueReferenceType( @@ -8274,7 +8274,7 @@ class BuiltinOperatorOverloadBuilder { S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); } - + if (!(*Ptr).isRestrictQualified() && VisibleTypeConversionsQuals.hasRestrict()) { // restrict version @@ -8282,7 +8282,7 @@ class BuiltinOperatorOverloadBuilder { = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/isEqualOp); - + if (NeedVolatile) { // volatile restrict version ParamTypes[0] @@ -8323,7 +8323,7 @@ class BuiltinOperatorOverloadBuilder { S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); } - + if (!(*Ptr).isRestrictQualified() && VisibleTypeConversionsQuals.hasRestrict()) { // restrict version @@ -8331,7 +8331,7 @@ class BuiltinOperatorOverloadBuilder { = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet, /*IsAssigmentOperator=*/true); - + if (NeedVolatile) { // volatile restrict version ParamTypes[0] @@ -9424,13 +9424,13 @@ void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType, OverloadExpr *OvlExpr = Ovl.Expression; for (UnresolvedSetIterator I = OvlExpr->decls_begin(), - IEnd = OvlExpr->decls_end(); + IEnd = OvlExpr->decls_end(); I != IEnd; ++I) { - if (FunctionTemplateDecl *FunTmpl = + if (FunctionTemplateDecl *FunTmpl = dyn_cast((*I)->getUnderlyingDecl()) ) { NoteOverloadCandidate(*I, FunTmpl->getTemplatedDecl(), DestType, TakingAddress); - } else if (FunctionDecl *Fun + } else if (FunctionDecl *Fun = dyn_cast((*I)->getUnderlyingDecl()) ) { NoteOverloadCandidate(*I, Fun, DestType, TakingAddress); } @@ -9608,7 +9608,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy << ToTy << (unsigned) isObjectArgument << I+1 << (unsigned) (Cand->Fix.Kind); - + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -9711,7 +9711,7 @@ static bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand, // right number of arguments, because only overloaded operators have // the weird behavior of overloading member and non-member functions. // Just don't report anything. - if (Fn->isInvalidDecl() && + if (Fn->isInvalidDecl() && Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) return true; @@ -9735,9 +9735,9 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D, "The templated declaration should at least be a function" " when diagnosing bad template argument deduction due to too many" " or too few arguments"); - + FunctionDecl *Fn = cast(D); - + // TODO: treat calls to a missing default constructor as a special case const FunctionProtoType *FnTy = Fn->getType()->getAs(); unsigned MinParams = Fn->getMinRequiredArguments(); @@ -9993,8 +9993,8 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; // FIXME: For generic lambda parameters, check if the function is a lambda - // call operator, and if so, emit a prettier and more informative - // diagnostic that mentions 'auto' and lambda in addition to + // call operator, and if so, emit a prettier and more informative + // diagnostic that mentions 'auto' and lambda in addition to // (or instead of?) the canonical template type parameters. S.Diag(Templated->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch) @@ -10692,16 +10692,16 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) { // R (S::*)(A) --> R (A) QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) { QualType Ret = PossiblyAFunctionType; - if (const PointerType *ToTypePtr = + if (const PointerType *ToTypePtr = PossiblyAFunctionType->getAs()) Ret = ToTypePtr->getPointeeType(); - else if (const ReferenceType *ToTypeRef = + else if (const ReferenceType *ToTypeRef = PossiblyAFunctionType->getAs()) Ret = ToTypeRef->getPointeeType(); else if (const MemberPointerType *MemTypePtr = - PossiblyAFunctionType->getAs()) - Ret = MemTypePtr->getPointeeType(); - Ret = + PossiblyAFunctionType->getAs()) + Ret = MemTypePtr->getPointeeType(); + Ret = Context.getCanonicalType(Ret).getUnqualifiedType(); return Ret; } @@ -10727,9 +10727,9 @@ namespace { class AddressOfFunctionResolver { Sema& S; Expr* SourceExpr; - const QualType& TargetType; - QualType TargetFunctionType; // Extracted function type from target type - + const QualType& TargetType; + QualType TargetFunctionType; // Extracted function type from target type + bool Complain; //DeclAccessPair& ResultFunctionAccessPair; ASTContext& Context; @@ -10739,7 +10739,7 @@ class AddressOfFunctionResolver { bool StaticMemberFunctionFromBoundPointer; bool HasComplained; - OverloadExpr::FindResult OvlExprInfo; + OverloadExpr::FindResult OvlExprInfo; OverloadExpr *OvlExpr; TemplateArgumentListInfo OvlExplicitTemplateArgs; SmallVector, 4> Matches; @@ -10786,7 +10786,7 @@ class AddressOfFunctionResolver { } return; } - + if (OvlExpr->hasExplicitTemplateArgs()) OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs); @@ -10864,7 +10864,7 @@ class AddressOfFunctionResolver { } // return true if any matching specializations were found - bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate, + bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate, const DeclAccessPair& CurAccessFunPair) { if (CXXMethodDecl *Method = dyn_cast(FunctionTemplate->getTemplatedDecl())) { @@ -10872,7 +10872,7 @@ class AddressOfFunctionResolver { // static when converting to member pointer. if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) return false; - } + } else if (TargetTypeIsNonStaticMemberFunction) return false; @@ -10885,17 +10885,17 @@ class AddressOfFunctionResolver { FunctionDecl *Specialization = nullptr; TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (Sema::TemplateDeductionResult Result - = S.DeduceTemplateArguments(FunctionTemplate, + = S.DeduceTemplateArguments(FunctionTemplate, &OvlExplicitTemplateArgs, - TargetFunctionType, Specialization, + TargetFunctionType, Specialization, Info, /*IsAddressOfFunction*/true)) { // Make a note of the failed deduction for diagnostics. FailedCandidates.addCandidate() .set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(), MakeDeductionFailureInfo(Context, Result, Info)); return false; - } - + } + // Template argument deduction ensures that we have an exact match or // compatible pointer-to-function arguments that would be adjusted by ICS. // This function template specicalization works. @@ -10909,15 +10909,15 @@ class AddressOfFunctionResolver { Matches.push_back(std::make_pair(CurAccessFunPair, Specialization)); return true; } - - bool AddMatchingNonTemplateFunction(NamedDecl* Fn, + + bool AddMatchingNonTemplateFunction(NamedDecl* Fn, const DeclAccessPair& CurAccessFunPair) { if (CXXMethodDecl *Method = dyn_cast(Fn)) { // Skip non-static functions when converting to pointer, and static // when converting to member pointer. if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) return false; - } + } else if (TargetTypeIsNonStaticMemberFunction) return false; @@ -10947,20 +10947,20 @@ class AddressOfFunctionResolver { return true; } } - + return false; } - + bool FindAllFunctionsThatMatchTargetTypeExactly() { bool Ret = false; - + // If the overload expression doesn't have the form of a pointer to // member, don't try to convert it to a pointer-to-member type. if (IsInvalidFormOfPointerToMemberFunction()) return false; for (UnresolvedSetIterator I = OvlExpr->decls_begin(), - E = OvlExpr->decls_end(); + E = OvlExpr->decls_end(); I != E; ++I) { // Look through any using declarations to find the underlying function. NamedDecl *Fn = (*I)->getUnderlyingDecl(); @@ -11103,12 +11103,12 @@ class AddressOfFunctionResolver { bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); } int getNumMatches() const { return Matches.size(); } - + FunctionDecl* getMatchingFunctionDecl() const { if (Matches.size() != 1) return nullptr; return Matches[0].second; } - + const DeclAccessPair* getMatchingFunctionAccessPair() const { if (Matches.size() != 1) return nullptr; return &Matches[0].first; @@ -11248,7 +11248,7 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate( /// If no template-ids are found, no diagnostics are emitted and NULL is /// returned. FunctionDecl * -Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, +Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, bool Complain, DeclAccessPair *FoundResult) { // C++ [over.over]p1: @@ -11311,9 +11311,9 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, } return nullptr; } - + Matched = Specialization; - if (FoundResult) *FoundResult = I.getPair(); + if (FoundResult) *FoundResult = I.getPair(); } if (Matched && @@ -11336,8 +11336,8 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, // returns true if 'complain' is set. bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, bool doFunctionPointerConverion, - bool complain, SourceRange OpRangeForComplaining, - QualType DestTypeForComplaining, + bool complain, SourceRange OpRangeForComplaining, + QualType DestTypeForComplaining, unsigned DiagIDForComplaining) { assert(SrcExpr.get()->getType() == Context.OverloadTy); @@ -11394,7 +11394,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) << ovl.Expression->getName() << DestTypeForComplaining - << OpRangeForComplaining + << OpRangeForComplaining << ovl.Expression->getQualifierLoc().getSourceRange(); NoteAllOverloadCandidates(SrcExpr.get()); @@ -12183,8 +12183,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // TODO: provide better source location info in DNLoc component. DeclarationNameInfo OpNameInfo(OpName, OpLoc); UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, NamingClass, - NestedNameSpecifierLoc(), OpNameInfo, + = UnresolvedLookupExpr::Create(Context, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return new (Context) @@ -12747,12 +12747,12 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc())) return ExprError(); // If FoundDecl is different from Method (such as if one is a template - // and the other a specialization), make sure DiagnoseUseOfDecl is + // and the other a specialization), make sure DiagnoseUseOfDecl is // called on both. // FIXME: This would be more comprehensively addressed by modifying // DiagnoseUseOfDecl to accept both the FoundDecl and the decl // being used. - if (Method != FoundDecl.getDecl() && + if (Method != FoundDecl.getDecl() && DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc())) return ExprError(); break; @@ -12775,7 +12775,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, case OR_Deleted: Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) << Best->Function->isDeleted() - << DeclName + << DeclName << getDeletedOrUnavailableSuffix(Best->Function) << MemExprE->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); @@ -12848,8 +12848,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } } - if ((isa(CurContext) || - isa(CurContext)) && + if ((isa(CurContext) || + isa(CurContext)) && TheCall->getMethodDecl()->isPure()) { const CXXMethodDecl *MD = TheCall->getMethodDecl(); @@ -12929,7 +12929,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, } // C++ [over.call.object]p2: - // In addition, for each (non-explicit in C++0x) conversion function + // In addition, for each (non-explicit in C++0x) conversion function // declared in T of the form // // operator conversion-type-id () cv-qualifier; @@ -13008,7 +13008,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Diag(Object.get()->getLocStart(), diag::err_ovl_deleted_object_call) << Best->Function->isDeleted() - << Object.get()->getType() + << Object.get()->getType() << getDeletedOrUnavailableSuffix(Best->Function) << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); @@ -13031,7 +13031,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Best->FoundDecl); if (DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc)) return ExprError(); - assert(Conv == Best->FoundDecl.getDecl() && + assert(Conv == Best->FoundDecl.getDecl() && "Found Decl & conversion-to-functionptr should be same, right?!"); // We selected one of the surrogate functions that converts the // object parameter to a function pointer. Perform the conversion @@ -13242,7 +13242,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, case OR_Deleted: Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() - << "->" + << "->" << getDeletedOrUnavailableSuffix(Best->Function) << Base->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index f8970744389b..e7315934b515 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -3175,11 +3175,7 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); Attr; Attr = Attr->getNext()) { if (Attr->getKind() == AttributeList::AT_OpenCLKernel) { - llvm::Triple::ArchType arch = S.Context.getTargetInfo().getTriple().getArch(); - if (arch == llvm::Triple::spir || arch == llvm::Triple::spir64 || - arch == llvm::Triple::amdgcn || arch == llvm::Triple::r600) { - CC = CC_OpenCLKernel; - } + CC = CC_OpenCLKernel; break; } } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index c931b13f65f3..95cb54f944e4 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1422,8 +1422,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); } - if (WritingModule) { + if (WritingModule) { // Module name auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME)); @@ -1466,9 +1466,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.clear(); auto &Map = PP.getHeaderSearchInfo().getModuleMap(); - - // Primary module map file. - AddPath(Map.getModuleMapFileForUniquing(WritingModule)->getName(), Record); + AddPath(WritingModule->PresumedModuleMapFile.empty() + ? Map.getModuleMapFileForUniquing(WritingModule)->getName() + : StringRef(WritingModule->PresumedModuleMapFile), + Record); // Additional module map files. if (auto *AdditionalModMaps = diff --git a/test/CodeGen/arm_neon_intrinsics.c b/test/CodeGen/arm_neon_intrinsics.c index ae7c78e08f86..62888dd73339 100644 --- a/test/CodeGen/arm_neon_intrinsics.c +++ b/test/CodeGen/arm_neon_intrinsics.c @@ -3,8 +3,6 @@ // RUN: -disable-O0-optnone -emit-llvm -o - %s \ // RUN: | opt -S -mem2reg | FileCheck %s -// REQUIRES: long-tests - #include // CHECK-LABEL: @test_vaba_s8( @@ -3481,11 +3479,11 @@ float32_t test_vgetq_lane_f32(float32x4_t a) { } // CHECK-LABEL: @test_vgetq_lane_f16( -// CHECK: [[__REINT_244:%.*]] = alloca <8 x half>, align 8 +// CHECK: [[__REINT_244:%.*]] = alloca <8 x half>, align 16 // CHECK: [[__REINT1_244:%.*]] = alloca i16, align 2 -// CHECK: store <8 x half> %a, <8 x half>* [[__REINT_244]], align 8 +// CHECK: store <8 x half> %a, <8 x half>* [[__REINT_244]], align 16 // CHECK: [[TMP0:%.*]] = bitcast <8 x half>* [[__REINT_244]] to <8 x i16>* -// CHECK: [[TMP1:%.*]] = load <8 x i16>, <8 x i16>* [[TMP0]], align 8 +// CHECK: [[TMP1:%.*]] = load <8 x i16>, <8 x i16>* [[TMP0]], align 16 // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> [[TMP1]] to <16 x i8> // CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16> // CHECK: [[VGET_LANE:%.*]] = extractelement <8 x i16> [[TMP3]], i32 3 @@ -4543,7 +4541,7 @@ poly16x4_t test_vld1_lane_p16(poly16_t const * a, poly16x4_t b) { } // CHECK-LABEL: @test_vld2q_u8( -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8> uint8x16x2_t test_vld2q_u8(uint8_t const * a) { @@ -4551,7 +4549,7 @@ uint8x16x2_t test_vld2q_u8(uint8_t const * a) { } // CHECK-LABEL: @test_vld2q_u16( -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16> @@ -4560,7 +4558,7 @@ uint16x8x2_t test_vld2q_u16(uint16_t const * a) { } // CHECK-LABEL: @test_vld2q_u32( -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <4 x i32>, <4 x i32> @@ -4569,7 +4567,7 @@ uint32x4x2_t test_vld2q_u32(uint32_t const * a) { } // CHECK-LABEL: @test_vld2q_s8( -// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8> int8x16x2_t test_vld2q_s8(int8_t const * a) { @@ -4577,7 +4575,7 @@ int8x16x2_t test_vld2q_s8(int8_t const * a) { } // CHECK-LABEL: @test_vld2q_s16( -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16> @@ -4586,7 +4584,7 @@ int16x8x2_t test_vld2q_s16(int16_t const * a) { } // CHECK-LABEL: @test_vld2q_s32( -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <4 x i32>, <4 x i32> @@ -4595,7 +4593,7 @@ int32x4x2_t test_vld2q_s32(int32_t const * a) { } // CHECK-LABEL: @test_vld2q_f16( -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16> @@ -4604,7 +4602,7 @@ float16x8x2_t test_vld2q_f16(float16_t const * a) { } // CHECK-LABEL: @test_vld2q_f32( -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <4 x float>, <4 x float> @@ -4613,7 +4611,7 @@ float32x4x2_t test_vld2q_f32(float32_t const * a) { } // CHECK-LABEL: @test_vld2q_p8( -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8> poly8x16x2_t test_vld2q_p8(poly8_t const * a) { @@ -4621,7 +4619,7 @@ poly8x16x2_t test_vld2q_p8(poly8_t const * a) { } // CHECK-LABEL: @test_vld2q_p16( -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16> @@ -4840,24 +4838,24 @@ poly16x4x2_t test_vld2_dup_p16(poly16_t const * a) { } // CHECK-LABEL: @test_vld2q_lane_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -4867,24 +4865,24 @@ uint16x8x2_t test_vld2q_lane_u16(uint16_t const * a, uint16x8x2_t b) { } // CHECK-LABEL: @test_vld2q_lane_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x i32>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> @@ -4894,24 +4892,24 @@ uint32x4x2_t test_vld2q_lane_u32(uint32_t const * a, uint32x4x2_t b) { } // CHECK-LABEL: @test_vld2q_lane_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -4921,24 +4919,24 @@ int16x8x2_t test_vld2q_lane_s16(int16_t const * a, int16x8x2_t b) { } // CHECK-LABEL: @test_vld2q_lane_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x i32>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> @@ -4948,24 +4946,24 @@ int32x4x2_t test_vld2q_lane_s32(int32_t const * a, int32x4x2_t b) { } // CHECK-LABEL: @test_vld2q_lane_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x half>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -4975,24 +4973,24 @@ float16x8x2_t test_vld2q_lane_f16(float16_t const * a, float16x8x2_t b) { } // CHECK-LABEL: @test_vld2q_lane_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x float>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float> @@ -5002,24 +5000,24 @@ float32x4x2_t test_vld2q_lane_f32(float32_t const * a, float32x4x2_t b) { } // CHECK-LABEL: @test_vld2q_lane_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -5284,7 +5282,7 @@ poly16x4x2_t test_vld2_lane_p16(poly16_t const * a, poly16x4x2_t b) { } // CHECK-LABEL: @test_vld3q_u8( -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> uint8x16x3_t test_vld3q_u8(uint8_t const * a) { @@ -5292,7 +5290,7 @@ uint8x16x3_t test_vld3q_u8(uint8_t const * a) { } // CHECK-LABEL: @test_vld3q_u16( -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> @@ -5301,7 +5299,7 @@ uint16x8x3_t test_vld3q_u16(uint16_t const * a) { } // CHECK-LABEL: @test_vld3q_u32( -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> @@ -5310,7 +5308,7 @@ uint32x4x3_t test_vld3q_u32(uint32_t const * a) { } // CHECK-LABEL: @test_vld3q_s8( -// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> int8x16x3_t test_vld3q_s8(int8_t const * a) { @@ -5318,7 +5316,7 @@ int8x16x3_t test_vld3q_s8(int8_t const * a) { } // CHECK-LABEL: @test_vld3q_s16( -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> @@ -5327,7 +5325,7 @@ int16x8x3_t test_vld3q_s16(int16_t const * a) { } // CHECK-LABEL: @test_vld3q_s32( -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> @@ -5336,7 +5334,7 @@ int32x4x3_t test_vld3q_s32(int32_t const * a) { } // CHECK-LABEL: @test_vld3q_f16( -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> @@ -5345,7 +5343,7 @@ float16x8x3_t test_vld3q_f16(float16_t const * a) { } // CHECK-LABEL: @test_vld3q_f32( -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float> @@ -5354,7 +5352,7 @@ float32x4x3_t test_vld3q_f32(float32_t const * a) { } // CHECK-LABEL: @test_vld3q_p8( -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> poly8x16x3_t test_vld3q_p8(poly8_t const * a) { @@ -5362,7 +5360,7 @@ poly8x16x3_t test_vld3q_p8(poly8_t const * a) { } // CHECK-LABEL: @test_vld3q_p16( -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> @@ -5581,28 +5579,28 @@ poly16x4x3_t test_vld3_dup_p16(poly16_t const * a) { } // CHECK-LABEL: @test_vld3q_lane_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -5613,28 +5611,28 @@ uint16x8x3_t test_vld3q_lane_u16(uint16_t const * a, uint16x8x3_t b) { } // CHECK-LABEL: @test_vld3q_lane_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x i32>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> @@ -5645,28 +5643,28 @@ uint32x4x3_t test_vld3q_lane_u32(uint32_t const * a, uint32x4x3_t b) { } // CHECK-LABEL: @test_vld3q_lane_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -5677,28 +5675,28 @@ int16x8x3_t test_vld3q_lane_s16(int16_t const * a, int16x8x3_t b) { } // CHECK-LABEL: @test_vld3q_lane_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x i32>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> @@ -5709,28 +5707,28 @@ int32x4x3_t test_vld3q_lane_s32(int32_t const * a, int32x4x3_t b) { } // CHECK-LABEL: @test_vld3q_lane_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x half>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -5741,28 +5739,28 @@ float16x8x3_t test_vld3q_lane_f16(float16_t const * a, float16x8x3_t b) { } // CHECK-LABEL: @test_vld3q_lane_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x float>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <4 x float> [[TMP9]] to <16 x i8> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float> @@ -5773,28 +5771,28 @@ float32x4x3_t test_vld3q_lane_f32(float32_t const * a, float32x4x3_t b) { } // CHECK-LABEL: @test_vld3q_lane_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -6104,7 +6102,7 @@ poly16x4x3_t test_vld3_lane_p16(poly16_t const * a, poly16x4x3_t b) { } // CHECK-LABEL: @test_vld4q_u8( -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> uint8x16x4_t test_vld4q_u8(uint8_t const * a) { @@ -6112,7 +6110,7 @@ uint8x16x4_t test_vld4q_u8(uint8_t const * a) { } // CHECK-LABEL: @test_vld4q_u16( -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> @@ -6121,7 +6119,7 @@ uint16x8x4_t test_vld4q_u16(uint16_t const * a) { } // CHECK-LABEL: @test_vld4q_u32( -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> @@ -6130,7 +6128,7 @@ uint32x4x4_t test_vld4q_u32(uint32_t const * a) { } // CHECK-LABEL: @test_vld4q_s8( -// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> int8x16x4_t test_vld4q_s8(int8_t const * a) { @@ -6138,7 +6136,7 @@ int8x16x4_t test_vld4q_s8(int8_t const * a) { } // CHECK-LABEL: @test_vld4q_s16( -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> @@ -6147,7 +6145,7 @@ int16x8x4_t test_vld4q_s16(int16_t const * a) { } // CHECK-LABEL: @test_vld4q_s32( -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> @@ -6156,7 +6154,7 @@ int32x4x4_t test_vld4q_s32(int32_t const * a) { } // CHECK-LABEL: @test_vld4q_f16( -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> @@ -6165,7 +6163,7 @@ float16x8x4_t test_vld4q_f16(float16_t const * a) { } // CHECK-LABEL: @test_vld4q_f32( -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> @@ -6174,7 +6172,7 @@ float32x4x4_t test_vld4q_f32(float32_t const * a) { } // CHECK-LABEL: @test_vld4q_p8( -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> poly8x16x4_t test_vld4q_p8(poly8_t const * a) { @@ -6182,7 +6180,7 @@ poly8x16x4_t test_vld4q_p8(poly8_t const * a) { } // CHECK-LABEL: @test_vld4q_p16( -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align 8 +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* // CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> @@ -6401,32 +6399,32 @@ poly16x4x4_t test_vld4_dup_p16(poly16_t const * a) { } // CHECK-LABEL: @test_vld4q_lane_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP11:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP11:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP12:%.*]] = bitcast <8 x i16> [[TMP11]] to <16 x i8> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -6438,32 +6436,32 @@ uint16x8x4_t test_vld4q_lane_u16(uint16_t const * a, uint16x8x4_t b) { } // CHECK-LABEL: @test_vld4q_lane_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x i32>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP11:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP11:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP12:%.*]] = bitcast <4 x i32> [[TMP11]] to <16 x i8> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> // CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> @@ -6475,32 +6473,32 @@ uint32x4x4_t test_vld4q_lane_u32(uint32_t const * a, uint32x4x4_t b) { } // CHECK-LABEL: @test_vld4q_lane_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP11:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP11:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP12:%.*]] = bitcast <8 x i16> [[TMP11]] to <16 x i8> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -6512,32 +6510,32 @@ int16x8x4_t test_vld4q_lane_s16(int16_t const * a, int16x8x4_t b) { } // CHECK-LABEL: @test_vld4q_lane_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x i32>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP11:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP11:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP12:%.*]] = bitcast <4 x i32> [[TMP11]] to <16 x i8> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> // CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> @@ -6549,32 +6547,32 @@ int32x4x4_t test_vld4q_lane_s32(int32_t const * a, int32x4x4_t b) { } // CHECK-LABEL: @test_vld4q_lane_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x half>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP11:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP11:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP12:%.*]] = bitcast <8 x half> [[TMP11]] to <16 x i8> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -6586,32 +6584,32 @@ float16x8x4_t test_vld4q_lane_f16(float16_t const * a, float16x8x4_t b) { } // CHECK-LABEL: @test_vld4q_lane_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x float>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <4 x float> [[TMP9]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP11:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP11:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP12:%.*]] = bitcast <4 x float> [[TMP11]] to <16 x i8> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> // CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float> @@ -6623,32 +6621,32 @@ float32x4x4_t test_vld4q_lane_f32(float32_t const * a, float32x4x4_t b) { } // CHECK-LABEL: @test_vld4q_lane_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 16 +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8* // CHECK: [[TMP4:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP11:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP11:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP12:%.*]] = bitcast <8 x i16> [[TMP11]] to <16 x i8> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> // CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> @@ -14549,21 +14547,21 @@ float32x4_t test_vsetq_lane_f32(float32_t a, float32x4_t b) { // CHECK-LABEL: @test_vsetq_lane_f16( // CHECK: [[__REINT_248:%.*]] = alloca half, align 2 -// CHECK: [[__REINT1_248:%.*]] = alloca <8 x half>, align 8 -// CHECK: [[__REINT2_248:%.*]] = alloca <8 x i16>, align 8 +// CHECK: [[__REINT1_248:%.*]] = alloca <8 x half>, align 16 +// CHECK: [[__REINT2_248:%.*]] = alloca <8 x i16>, align 16 // CHECK: [[TMP0:%.*]] = load half, half* %a, align 2 // CHECK: store half [[TMP0]], half* [[__REINT_248]], align 2 -// CHECK: store <8 x half> %b, <8 x half>* [[__REINT1_248]], align 8 +// CHECK: store <8 x half> %b, <8 x half>* [[__REINT1_248]], align 16 // CHECK: [[TMP1:%.*]] = bitcast half* [[__REINT_248]] to i16* // CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2 // CHECK: [[TMP3:%.*]] = bitcast <8 x half>* [[__REINT1_248]] to <8 x i16>* -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[TMP3]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[TMP3]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[TMP6:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i16> [[TMP6]], i16 [[TMP2]], i32 3 -// CHECK: store <8 x i16> [[VSET_LANE]], <8 x i16>* [[__REINT2_248]], align 8 +// CHECK: store <8 x i16> [[VSET_LANE]], <8 x i16>* [[__REINT2_248]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16>* [[__REINT2_248]] to <8 x half>* -// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[TMP7]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[TMP7]], align 16 // CHECK: ret <8 x half> [[TMP8]] float16x8_t test_vsetq_lane_f16(float16_t *a, float16x8_t b) { return vsetq_lane_f16(*a, b, 3); @@ -16194,20 +16192,20 @@ void test_vst1_lane_p16(poly16_t * a, poly16x4_t b) { } // CHECK-LABEL: @test_vst2q_u8( -// CHECK: [[B:%.*]] = alloca %struct.uint8x16x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint8x16x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <16 x i8>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: call void @llvm.arm.neon.vst2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i32 1) // CHECK: ret void void test_vst2q_u8(uint8_t * a, uint8x16x2_t b) { @@ -16215,22 +16213,22 @@ void test_vst2q_u8(uint8_t * a, uint8x16x2_t b) { } // CHECK-LABEL: @test_vst2q_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -16241,22 +16239,22 @@ void test_vst2q_u16(uint16_t * a, uint16x8x2_t b) { } // CHECK-LABEL: @test_vst2q_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x i32>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -16267,20 +16265,20 @@ void test_vst2q_u32(uint32_t * a, uint32x4x2_t b) { } // CHECK-LABEL: @test_vst2q_s8( -// CHECK: [[B:%.*]] = alloca %struct.int8x16x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int8x16x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <16 x i8>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: call void @llvm.arm.neon.vst2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i32 1) // CHECK: ret void void test_vst2q_s8(int8_t * a, int8x16x2_t b) { @@ -16288,22 +16286,22 @@ void test_vst2q_s8(int8_t * a, int8x16x2_t b) { } // CHECK-LABEL: @test_vst2q_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -16314,22 +16312,22 @@ void test_vst2q_s16(int16_t * a, int16x8x2_t b) { } // CHECK-LABEL: @test_vst2q_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x i32>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -16340,22 +16338,22 @@ void test_vst2q_s32(int32_t * a, int32x4x2_t b) { } // CHECK-LABEL: @test_vst2q_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x half>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -16366,22 +16364,22 @@ void test_vst2q_f16(float16_t * a, float16x8x2_t b) { } // CHECK-LABEL: @test_vst2q_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x float>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x float> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x float> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x float> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x float> @@ -16392,20 +16390,20 @@ void test_vst2q_f32(float32_t * a, float32x4x2_t b) { } // CHECK-LABEL: @test_vst2q_p8( -// CHECK: [[B:%.*]] = alloca %struct.poly8x16x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly8x16x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <16 x i8>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: call void @llvm.arm.neon.vst2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i32 1) // CHECK: ret void void test_vst2q_p8(poly8_t * a, poly8x16x2_t b) { @@ -16413,22 +16411,22 @@ void test_vst2q_p8(poly8_t * a, poly8x16x2_t b) { } // CHECK-LABEL: @test_vst2q_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -16736,22 +16734,22 @@ void test_vst2_p16(poly16_t * a, poly16x4x2_t b) { } // CHECK-LABEL: @test_vst2q_lane_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -16762,22 +16760,22 @@ void test_vst2q_lane_u16(uint16_t * a, uint16x8x2_t b) { } // CHECK-LABEL: @test_vst2q_lane_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x i32>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -16788,22 +16786,22 @@ void test_vst2q_lane_u32(uint32_t * a, uint32x4x2_t b) { } // CHECK-LABEL: @test_vst2q_lane_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -16814,22 +16812,22 @@ void test_vst2q_lane_s16(int16_t * a, int16x8x2_t b) { } // CHECK-LABEL: @test_vst2q_lane_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x i32>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -16840,22 +16838,22 @@ void test_vst2q_lane_s32(int32_t * a, int32x4x2_t b) { } // CHECK-LABEL: @test_vst2q_lane_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x half>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -16866,22 +16864,22 @@ void test_vst2q_lane_f16(float16_t * a, float16x8x2_t b) { } // CHECK-LABEL: @test_vst2q_lane_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <4 x float>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x float> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x float> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x float> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x float> @@ -16892,22 +16890,22 @@ void test_vst2q_lane_f32(float32_t * a, float32x4x2_t b) { } // CHECK-LABEL: @test_vst2q_lane_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [2 x <8 x i16>]* [[COERCE_DIVE]] to [4 x i64]* -// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 8 +// CHECK: store [4 x i64] [[B]].coerce, [4 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 32, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -17163,23 +17161,23 @@ void test_vst2_lane_p16(poly16_t * a, poly16x4x2_t b) { } // CHECK-LABEL: @test_vst3q_u8( -// CHECK: [[B:%.*]] = alloca %struct.uint8x16x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint8x16x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <16 x i8>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 // CHECK: call void @llvm.arm.neon.vst3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i32 1) // CHECK: ret void void test_vst3q_u8(uint8_t * a, uint8x16x3_t b) { @@ -17187,26 +17185,26 @@ void test_vst3q_u8(uint8_t * a, uint8x16x3_t b) { } // CHECK-LABEL: @test_vst3q_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -17218,26 +17216,26 @@ void test_vst3q_u16(uint16_t * a, uint16x8x3_t b) { } // CHECK-LABEL: @test_vst3q_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x i32>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x i32> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -17249,23 +17247,23 @@ void test_vst3q_u32(uint32_t * a, uint32x4x3_t b) { } // CHECK-LABEL: @test_vst3q_s8( -// CHECK: [[B:%.*]] = alloca %struct.int8x16x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int8x16x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <16 x i8>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 // CHECK: call void @llvm.arm.neon.vst3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i32 1) // CHECK: ret void void test_vst3q_s8(int8_t * a, int8x16x3_t b) { @@ -17273,26 +17271,26 @@ void test_vst3q_s8(int8_t * a, int8x16x3_t b) { } // CHECK-LABEL: @test_vst3q_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -17304,26 +17302,26 @@ void test_vst3q_s16(int16_t * a, int16x8x3_t b) { } // CHECK-LABEL: @test_vst3q_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x i32>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x i32> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -17335,26 +17333,26 @@ void test_vst3q_s32(int32_t * a, int32x4x3_t b) { } // CHECK-LABEL: @test_vst3q_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x half>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x half> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -17366,26 +17364,26 @@ void test_vst3q_f16(float16_t * a, float16x8x3_t b) { } // CHECK-LABEL: @test_vst3q_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x float>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x float> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x float> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x float> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x float> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x float> @@ -17397,23 +17395,23 @@ void test_vst3q_f32(float32_t * a, float32x4x3_t b) { } // CHECK-LABEL: @test_vst3q_p8( -// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <16 x i8>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 // CHECK: call void @llvm.arm.neon.vst3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i32 1) // CHECK: ret void void test_vst3q_p8(poly8_t * a, poly8x16x3_t b) { @@ -17421,26 +17419,26 @@ void test_vst3q_p8(poly8_t * a, poly8x16x3_t b) { } // CHECK-LABEL: @test_vst3q_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -17803,26 +17801,26 @@ void test_vst3_p16(poly16_t * a, poly16x4x3_t b) { } // CHECK-LABEL: @test_vst3q_lane_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -17834,26 +17832,26 @@ void test_vst3q_lane_u16(uint16_t * a, uint16x8x3_t b) { } // CHECK-LABEL: @test_vst3q_lane_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x i32>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x i32> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -17865,26 +17863,26 @@ void test_vst3q_lane_u32(uint32_t * a, uint32x4x3_t b) { } // CHECK-LABEL: @test_vst3q_lane_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -17896,26 +17894,26 @@ void test_vst3q_lane_s16(int16_t * a, int16x8x3_t b) { } // CHECK-LABEL: @test_vst3q_lane_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x i32>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x i32> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -17927,26 +17925,26 @@ void test_vst3q_lane_s32(int32_t * a, int32x4x3_t b) { } // CHECK-LABEL: @test_vst3q_lane_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x half>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x half> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -17958,26 +17956,26 @@ void test_vst3q_lane_f16(float16_t * a, float16x8x3_t b) { } // CHECK-LABEL: @test_vst3q_lane_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <4 x float>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x float> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x float> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x float> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x float> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x float> @@ -17989,26 +17987,26 @@ void test_vst3q_lane_f32(float32_t * a, float32x4x3_t b) { } // CHECK-LABEL: @test_vst3q_lane_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [3 x <8 x i16>]* [[COERCE_DIVE]] to [6 x i64]* -// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 8 +// CHECK: store [6 x i64] [[B]].coerce, [6 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 48, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -18309,26 +18307,26 @@ void test_vst3_lane_p16(poly16_t * a, poly16x4x3_t b) { } // CHECK-LABEL: @test_vst4q_u8( -// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <16 x i8>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP6:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP6:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16 // CHECK: call void @llvm.arm.neon.vst4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], <16 x i8> [[TMP6]], i32 1) // CHECK: ret void void test_vst4q_u8(uint8_t * a, uint8x16x4_t b) { @@ -18336,30 +18334,30 @@ void test_vst4q_u8(uint8_t * a, uint8x16x4_t b) { } // CHECK-LABEL: @test_vst4q_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <8 x i16> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -18372,30 +18370,30 @@ void test_vst4q_u16(uint16_t * a, uint16x8x4_t b) { } // CHECK-LABEL: @test_vst4q_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x i32>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x i32> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <4 x i32> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -18408,26 +18406,26 @@ void test_vst4q_u32(uint32_t * a, uint32x4x4_t b) { } // CHECK-LABEL: @test_vst4q_s8( -// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <16 x i8>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP6:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP6:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16 // CHECK: call void @llvm.arm.neon.vst4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], <16 x i8> [[TMP6]], i32 1) // CHECK: ret void void test_vst4q_s8(int8_t * a, int8x16x4_t b) { @@ -18435,30 +18433,30 @@ void test_vst4q_s8(int8_t * a, int8x16x4_t b) { } // CHECK-LABEL: @test_vst4q_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <8 x i16> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -18471,30 +18469,30 @@ void test_vst4q_s16(int16_t * a, int16x8x4_t b) { } // CHECK-LABEL: @test_vst4q_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x i32>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x i32> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <4 x i32> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -18507,30 +18505,30 @@ void test_vst4q_s32(int32_t * a, int32x4x4_t b) { } // CHECK-LABEL: @test_vst4q_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x half>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x half> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <8 x half> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -18543,30 +18541,30 @@ void test_vst4q_f16(float16_t * a, float16x8x4_t b) { } // CHECK-LABEL: @test_vst4q_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x float>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x float> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x float> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x float> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <4 x float> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x float> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x float> @@ -18579,26 +18577,26 @@ void test_vst4q_f32(float32_t * a, float32x4x4_t b) { } // CHECK-LABEL: @test_vst4q_p8( -// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <16 x i8>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP6:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP6:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16 // CHECK: call void @llvm.arm.neon.vst4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], <16 x i8> [[TMP6]], i32 1) // CHECK: ret void void test_vst4q_p8(poly8_t * a, poly8x16x4_t b) { @@ -18606,30 +18604,30 @@ void test_vst4q_p8(poly8_t * a, poly8x16x4_t b) { } // CHECK-LABEL: @test_vst4q_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <8 x i16> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -19047,30 +19045,30 @@ void test_vst4_p16(poly16_t * a, poly16x4x4_t b) { } // CHECK-LABEL: @test_vst4q_lane_u16( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <8 x i16> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -19083,30 +19081,30 @@ void test_vst4q_lane_u16(uint16_t * a, uint16x8x4_t b) { } // CHECK-LABEL: @test_vst4q_lane_u32( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x i32>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x i32> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <4 x i32> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -19119,30 +19117,30 @@ void test_vst4q_lane_u32(uint32_t * a, uint32x4x4_t b) { } // CHECK-LABEL: @test_vst4q_lane_s16( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <8 x i16> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -19155,30 +19153,30 @@ void test_vst4q_lane_s16(int16_t * a, int16x8x4_t b) { } // CHECK-LABEL: @test_vst4q_lane_s32( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x i32>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i32* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x i32> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x i32> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <4 x i32> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x i32> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x i32> @@ -19191,30 +19189,30 @@ void test_vst4q_lane_s32(int32_t * a, int32x4x4_t b) { } // CHECK-LABEL: @test_vst4q_lane_f16( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x half>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast half* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x half> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x half> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x half> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <8 x half> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -19227,30 +19225,30 @@ void test_vst4q_lane_f16(float16_t * a, float16x8x4_t b) { } // CHECK-LABEL: @test_vst4q_lane_f32( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <4 x float>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast float* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <4 x float> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <4 x float> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <4 x float> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <4 x float> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <4 x float> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <4 x float> @@ -19263,30 +19261,30 @@ void test_vst4q_lane_f32(float32_t * a, float32x4x4_t b) { } // CHECK-LABEL: @test_vst4q_lane_p16( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 8 +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 16 // CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[B]], i32 0, i32 0 // CHECK: [[TMP0:%.*]] = bitcast [4 x <8 x i16>]* [[COERCE_DIVE]] to [8 x i64]* -// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 8 +// CHECK: store [8 x i64] [[B]].coerce, [8 x i64]* [[TMP0]], align 16 // CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8* // CHECK: [[TMP2:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP1]], i8* [[TMP2]], i32 64, i32 16, i1 false) // CHECK: [[TMP3:%.*]] = bitcast i16* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i32 0, i32 0 -// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 // CHECK: [[TMP5:%.*]] = bitcast <8 x i16> [[TMP4]] to <16 x i8> // CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i32 0, i32 1 -// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 // CHECK: [[TMP7:%.*]] = bitcast <8 x i16> [[TMP6]] to <16 x i8> // CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i32 0, i32 2 -// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP9:%.*]] = bitcast <8 x i16> [[TMP8]] to <16 x i8> // CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 // CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i32 0, i32 3 -// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 // CHECK: [[TMP11:%.*]] = bitcast <8 x i16> [[TMP10]] to <16 x i8> // CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP5]] to <8 x i16> // CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP7]] to <8 x i16> @@ -20631,7 +20629,7 @@ poly16x4x2_t test_vtrn_p16(poly16x4_t a, poly16x4_t b) { } // CHECK-LABEL: @test_vtrnq_s8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -20641,14 +20639,14 @@ poly16x4x2_t test_vtrn_p16(poly16x4_t a, poly16x4_t b) { // CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !noalias !30 // CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void int8x16x2_t test_vtrnq_s8(int8x16_t a, int8x16_t b) { return vtrnq_s8(a, b); } // CHECK-LABEL: @test_vtrnq_s16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -20660,14 +20658,14 @@ int8x16x2_t test_vtrnq_s8(int8x16_t a, int8x16_t b) { // CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !noalias !33 // CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void int16x8x2_t test_vtrnq_s16(int16x8_t a, int16x8_t b) { return vtrnq_s16(a, b); } // CHECK-LABEL: @test_vtrnq_s32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8> @@ -20679,14 +20677,14 @@ int16x8x2_t test_vtrnq_s16(int16x8_t a, int16x8_t b) { // CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]], !noalias !36 // CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void int32x4x2_t test_vtrnq_s32(int32x4_t a, int32x4_t b) { return vtrnq_s32(a, b); } // CHECK-LABEL: @test_vtrnq_u8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -20696,14 +20694,14 @@ int32x4x2_t test_vtrnq_s32(int32x4_t a, int32x4_t b) { // CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !noalias !39 // CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void uint8x16x2_t test_vtrnq_u8(uint8x16_t a, uint8x16_t b) { return vtrnq_u8(a, b); } // CHECK-LABEL: @test_vtrnq_u16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -20715,14 +20713,14 @@ uint8x16x2_t test_vtrnq_u8(uint8x16_t a, uint8x16_t b) { // CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !noalias !42 // CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void uint16x8x2_t test_vtrnq_u16(uint16x8_t a, uint16x8_t b) { return vtrnq_u16(a, b); } // CHECK-LABEL: @test_vtrnq_u32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8> @@ -20734,14 +20732,14 @@ uint16x8x2_t test_vtrnq_u16(uint16x8_t a, uint16x8_t b) { // CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP4]], !noalias !45 // CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void uint32x4x2_t test_vtrnq_u32(uint32x4_t a, uint32x4_t b) { return vtrnq_u32(a, b); } // CHECK-LABEL: @test_vtrnq_f32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8> @@ -20753,14 +20751,14 @@ uint32x4x2_t test_vtrnq_u32(uint32x4_t a, uint32x4_t b) { // CHECK: store <4 x float> [[VTRN1_I]], <4 x float>* [[TMP4]], !noalias !48 // CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void float32x4x2_t test_vtrnq_f32(float32x4_t a, float32x4_t b) { return vtrnq_f32(a, b); } // CHECK-LABEL: @test_vtrnq_p8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VTRN_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -20770,14 +20768,14 @@ float32x4x2_t test_vtrnq_f32(float32x4_t a, float32x4_t b) { // CHECK: store <16 x i8> [[VTRN1_I]], <16 x i8>* [[TMP2]], !noalias !51 // CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void poly8x16x2_t test_vtrnq_p8(poly8x16_t a, poly8x16_t b) { return vtrnq_p8(a, b); } // CHECK-LABEL: @test_vtrnq_p16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -20789,7 +20787,7 @@ poly8x16x2_t test_vtrnq_p8(poly8x16_t a, poly8x16_t b) { // CHECK: store <8 x i16> [[VTRN1_I]], <8 x i16>* [[TMP4]], !noalias !54 // CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void poly16x8x2_t test_vtrnq_p16(poly16x8_t a, poly16x8_t b) { return vtrnq_p16(a, b); @@ -21125,7 +21123,7 @@ poly16x4x2_t test_vuzp_p16(poly16x4_t a, poly16x4_t b) { } // CHECK-LABEL: @test_vuzpq_s8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -21135,14 +21133,14 @@ poly16x4x2_t test_vuzp_p16(poly16x4_t a, poly16x4_t b) { // CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !noalias !84 // CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void int8x16x2_t test_vuzpq_s8(int8x16_t a, int8x16_t b) { return vuzpq_s8(a, b); } // CHECK-LABEL: @test_vuzpq_s16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -21154,14 +21152,14 @@ int8x16x2_t test_vuzpq_s8(int8x16_t a, int8x16_t b) { // CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !noalias !87 // CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void int16x8x2_t test_vuzpq_s16(int16x8_t a, int16x8_t b) { return vuzpq_s16(a, b); } // CHECK-LABEL: @test_vuzpq_s32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8> @@ -21173,14 +21171,14 @@ int16x8x2_t test_vuzpq_s16(int16x8_t a, int16x8_t b) { // CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]], !noalias !90 // CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void int32x4x2_t test_vuzpq_s32(int32x4_t a, int32x4_t b) { return vuzpq_s32(a, b); } // CHECK-LABEL: @test_vuzpq_u8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -21190,14 +21188,14 @@ int32x4x2_t test_vuzpq_s32(int32x4_t a, int32x4_t b) { // CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !noalias !93 // CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void uint8x16x2_t test_vuzpq_u8(uint8x16_t a, uint8x16_t b) { return vuzpq_u8(a, b); } // CHECK-LABEL: @test_vuzpq_u16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -21209,14 +21207,14 @@ uint8x16x2_t test_vuzpq_u8(uint8x16_t a, uint8x16_t b) { // CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !noalias !96 // CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void uint16x8x2_t test_vuzpq_u16(uint16x8_t a, uint16x8_t b) { return vuzpq_u16(a, b); } // CHECK-LABEL: @test_vuzpq_u32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8> @@ -21228,14 +21226,14 @@ uint16x8x2_t test_vuzpq_u16(uint16x8_t a, uint16x8_t b) { // CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP4]], !noalias !99 // CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void uint32x4x2_t test_vuzpq_u32(uint32x4_t a, uint32x4_t b) { return vuzpq_u32(a, b); } // CHECK-LABEL: @test_vuzpq_f32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8> @@ -21247,14 +21245,14 @@ uint32x4x2_t test_vuzpq_u32(uint32x4_t a, uint32x4_t b) { // CHECK: store <4 x float> [[VUZP1_I]], <4 x float>* [[TMP4]], !noalias !102 // CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void float32x4x2_t test_vuzpq_f32(float32x4_t a, float32x4_t b) { return vuzpq_f32(a, b); } // CHECK-LABEL: @test_vuzpq_p8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VUZP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -21264,14 +21262,14 @@ float32x4x2_t test_vuzpq_f32(float32x4_t a, float32x4_t b) { // CHECK: store <16 x i8> [[VUZP1_I]], <16 x i8>* [[TMP2]], !noalias !105 // CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void poly8x16x2_t test_vuzpq_p8(poly8x16_t a, poly8x16_t b) { return vuzpq_p8(a, b); } // CHECK-LABEL: @test_vuzpq_p16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -21283,7 +21281,7 @@ poly8x16x2_t test_vuzpq_p8(poly8x16_t a, poly8x16_t b) { // CHECK: store <8 x i16> [[VUZP1_I]], <8 x i16>* [[TMP4]], !noalias !108 // CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void poly16x8x2_t test_vuzpq_p16(poly16x8_t a, poly16x8_t b) { return vuzpq_p16(a, b); @@ -21455,7 +21453,7 @@ poly16x4x2_t test_vzip_p16(poly16x4_t a, poly16x4_t b) { } // CHECK-LABEL: @test_vzipq_s8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -21465,14 +21463,14 @@ poly16x4x2_t test_vzip_p16(poly16x4_t a, poly16x4_t b) { // CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !noalias !138 // CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.int8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void int8x16x2_t test_vzipq_s8(int8x16_t a, int8x16_t b) { return vzipq_s8(a, b); } // CHECK-LABEL: @test_vzipq_s16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -21484,14 +21482,14 @@ int8x16x2_t test_vzipq_s8(int8x16_t a, int8x16_t b) { // CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !noalias !141 // CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void int16x8x2_t test_vzipq_s16(int16x8_t a, int16x8_t b) { return vzipq_s16(a, b); } // CHECK-LABEL: @test_vzipq_s32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.int32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8> @@ -21503,14 +21501,14 @@ int16x8x2_t test_vzipq_s16(int16x8_t a, int16x8_t b) { // CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]], !noalias !144 // CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void int32x4x2_t test_vzipq_s32(int32x4_t a, int32x4_t b) { return vzipq_s32(a, b); } // CHECK-LABEL: @test_vzipq_u8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -21520,14 +21518,14 @@ int32x4x2_t test_vzipq_s32(int32x4_t a, int32x4_t b) { // CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !noalias !147 // CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void uint8x16x2_t test_vzipq_u8(uint8x16_t a, uint8x16_t b) { return vzipq_u8(a, b); } // CHECK-LABEL: @test_vzipq_u16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -21539,14 +21537,14 @@ uint8x16x2_t test_vzipq_u8(uint8x16_t a, uint8x16_t b) { // CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !noalias !150 // CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void uint16x8x2_t test_vzipq_u16(uint16x8_t a, uint16x8_t b) { return vzipq_u16(a, b); } // CHECK-LABEL: @test_vzipq_u32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.uint32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %b to <16 x i8> @@ -21558,14 +21556,14 @@ uint16x8x2_t test_vzipq_u16(uint16x8_t a, uint16x8_t b) { // CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP4]], !noalias !153 // CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void uint32x4x2_t test_vzipq_u32(uint32x4_t a, uint32x4_t b) { return vzipq_u32(a, b); } // CHECK-LABEL: @test_vzipq_f32( -// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.float32x4x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <4 x float> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <4 x float> %b to <16 x i8> @@ -21577,14 +21575,14 @@ uint32x4x2_t test_vzipq_u32(uint32x4_t a, uint32x4_t b) { // CHECK: store <4 x float> [[VZIP1_I]], <4 x float>* [[TMP4]], !noalias !156 // CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void float32x4x2_t test_vzipq_f32(float32x4_t a, float32x4_t b) { return vzipq_f32(a, b); } // CHECK-LABEL: @test_vzipq_p8( -// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.poly8x16x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <16 x i8>* // CHECK: [[VZIP_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> @@ -21594,14 +21592,14 @@ float32x4x2_t test_vzipq_f32(float32x4_t a, float32x4_t b) { // CHECK: store <16 x i8> [[VZIP1_I]], <16 x i8>* [[TMP2]], !noalias !159 // CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* %agg.result to i8* // CHECK: [[TMP4:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false) // CHECK: ret void poly8x16x2_t test_vzipq_p8(poly8x16_t a, poly8x16_t b) { return vzipq_p8(a, b); } // CHECK-LABEL: @test_vzipq_p16( -// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 8 +// CHECK: [[__RET_I:%.*]] = alloca %struct.poly16x8x2_t, align 16 // CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8* // CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %a to <16 x i8> // CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %b to <16 x i8> @@ -21613,7 +21611,7 @@ poly8x16x2_t test_vzipq_p8(poly8x16_t a, poly8x16_t b) { // CHECK: store <8 x i16> [[VZIP1_I]], <8 x i16>* [[TMP4]], !noalias !162 // CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8* // CHECK: [[TMP6:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP5]], i8* [[TMP6]], i32 32, i32 16, i1 false) // CHECK: ret void poly16x8x2_t test_vzipq_p16(poly16x8_t a, poly16x8_t b) { return vzipq_p16(a, b); diff --git a/test/CodeGen/ubsan-pointer-overflow.m b/test/CodeGen/ubsan-pointer-overflow.m new file mode 100644 index 000000000000..c83d527e624e --- /dev/null +++ b/test/CodeGen/ubsan-pointer-overflow.m @@ -0,0 +1,171 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -w -emit-llvm -o - %s -fsanitize=pointer-overflow | FileCheck %s + +// CHECK-LABEL: define void @unary_arith +void unary_arith(char *p) { + // CHECK: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 1, !nosanitize + // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 true, i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize + // CHECK-NEXT: [[VALID:%.*]] = and i1 true, [[DIFFVALID]], !nosanitize + // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize + ++p; + + // CHECK: ptrtoint i8* {{.*}} to i64, !nosanitize + // CHECK-NEXT: add i64 {{.*}}, -1, !nosanitize + // CHECK: select i1 false{{.*}}, !nosanitize + // CHECK-NEXT: and i1 true{{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + --p; + + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + p++; + + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + p--; +} + +// CHECK-LABEL: define void @binary_arith +void binary_arith(char *p, int i) { + // CHECK: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %{{.*}}), !nosanitize + // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize + // CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], !nosanitize + // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize + // CHECK-NEXT: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize + // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize + // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize + // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize + // CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize + // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize + p + i; + + // CHECK: [[OFFSET:%.*]] = sub i64 0, {{.*}} + // CHECK-NEXT: getelementptr inbounds {{.*}} [[OFFSET]] + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + p - i; +} + +// CHECK-LABEL: define void @fixed_len_array +void fixed_len_array(int k) { + // CHECK: getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* [[ARR:%.*]], i64 0, i64 [[IDXPROM:%.*]] + // CHECK-NEXT: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 40, i64 [[IDXPROM]]), !nosanitize + // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize + // CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], !nosanitize + // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize + // CHECK-NEXT: [[BASE:%.*]] = ptrtoint [10 x [10 x i32]]* [[ARR]] to i64, !nosanitize + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize + // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize + // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize + // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize + // CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize + // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize + + // CHECK: getelementptr inbounds [10 x i32], [10 x i32]* {{.*}}, i64 0, i64 [[IDXPROM1:%.*]] + // CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM1]]), !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + + int arr[10][10]; + arr[k][k]; +} + +// CHECK-LABEL: define void @variable_len_array +void variable_len_array(int n, int k) { + // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]] + // CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM]]), !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + + // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM1:%.*]] + // CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM1]]), !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + + int arr[n][n]; + arr[k][k]; +} + +// CHECK-LABEL: define void @pointer_array +void pointer_array(int **arr, int k) { + // CHECK: @llvm.smul.with.overflow.i64(i64 8, i64 {{.*}}), !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + + // CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 {{.*}}), !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + + arr[k][k]; +} + +struct S1 { + int pad1; + union { + char leaf; + struct S1 *link; + } u; + struct S1 *arr; +}; + +// TODO: Currently, structure GEPs are not checked, so there are several +// potentially unsafe GEPs here which we don't instrument. +// +// CHECK-LABEL: define void @struct_index +void struct_index(struct S1 *p) { + // CHECK: getelementptr inbounds %struct.S1, %struct.S1* [[P:%.*]], i64 10 + // CHECK-NEXT: [[BASE:%.*]] = ptrtoint %struct.S1* [[P]] to i64, !nosanitize + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 240, !nosanitize + // CHECK: @__ubsan_handle_pointer_overflow{{.*}} i64 [[BASE]], i64 [[COMPGEP]]) {{.*}}, !nosanitize + + // CHECK-NOT: @__ubsan_handle_pointer_overflow + + p->arr[10].u.link->u.leaf; +} + +typedef void (*funcptr_t)(void); + +// CHECK-LABEL: define void @function_pointer_arith +void function_pointer_arith(funcptr_t *p, int k) { + // CHECK: add i64 {{.*}}, 8, !nosanitize + // CHECK: @__ubsan_handle_pointer_overflow{{.*}} + ++p; + + // CHECK: @llvm.smul.with.overflow.i64(i64 8, i64 {{.*}}), !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + p + k; +} + +// CHECK-LABEL: define void @variable_len_array_arith +void variable_len_array_arith(int n, int k) { + int vla[n]; + int (*p)[n] = &vla; + + // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[INC:%.*]] + // CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 [[INC]]), !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + ++p; + + // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]] + // CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM]]), !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + p + k; +} + +// CHECK-LABEL: define void @objc_id +void objc_id(id *p) { + // CHECK: add i64 {{.*}}, 8, !nosanitize + // CHECK: @__ubsan_handle_pointer_overflow{{.*}} + p++; +} + +// CHECK-LABEL: define void @dont_emit_checks_for_no_op_GEPs +// CHECK-NOT: __ubsan_handle_pointer_overflow +void dont_emit_checks_for_no_op_GEPs(char *p) { + &p[0]; + + int arr[10][10]; + &arr[0][0]; +} diff --git a/test/CodeGenCXX/stmtexpr.cpp b/test/CodeGenCXX/stmtexpr.cpp index 5885a1663e63..5bd9908d6c25 100644 --- a/test/CodeGenCXX/stmtexpr.cpp +++ b/test/CodeGenCXX/stmtexpr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -Wno-unused-value -triple i686-linux-gnu -emit-llvm -o - %s | FileCheck %s // rdar: //8540501 extern "C" int printf(...); extern "C" void abort(); @@ -139,6 +139,34 @@ extern "C" int cleanup_exit_lvalue(bool cond) { // CHECK: %[[v:[^ ]*]] = load i32*, i32** %[[tmp]] // CHECK-NEXT: store i32* %[[v]], i32** %r +// Bind the reference to a byval argument. It is not an instruction or Constant, +// so it's a bit of a corner case. +struct ByVal { int x[3]; }; +extern "C" int cleanup_exit_lvalue_byval(bool cond, ByVal arg) { + ByVal &r = (A(1), ({ if (cond) return 0; (void)ByVal(); }), arg); + return r.x[0]; +} +// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue_byval({{.*}}, %struct.ByVal* byval align 4 %arg) +// CHECK: call {{.*}} @_ZN1AC1Ei +// CHECK: call {{.*}} @_ZN1AD1Ev +// CHECK: switch +// CHECK: store %struct.ByVal* %arg, %struct.ByVal** %r + +// Bind the reference to a local variable. We don't need to spill it. Binding a +// reference to it doesn't generate any instructions. +extern "C" int cleanup_exit_lvalue_local(bool cond) { + int local = 42; + int &r = (A(1), ({ if (cond) return 0; (void)0; }), local); + return r; +} +// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue_local({{.*}}) +// CHECK: %local = alloca i32 +// CHECK: store i32 42, i32* %local +// CHECK: call {{.*}} @_ZN1AC1Ei +// CHECK-NOT: store i32* %local +// CHECK: call {{.*}} @_ZN1AD1Ev +// CHECK: switch +// CHECK: store i32* %local, i32** %r, align 4 // We handle ExprWithCleanups for complex evaluation type separately, and it had // the same bug. diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp index 928817bfb1f5..c3798920abdd 100644 --- a/test/CodeGenCXX/strict-vtable-pointers.cpp +++ b/test/CodeGenCXX/strict-vtable-pointers.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-passes -O2 -emit-llvm -o %t.ll +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -std=c++11 -disable-llvm-passes -O2 -emit-llvm -o %t.ll // RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll // RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll // RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll @@ -180,6 +180,119 @@ struct DynamicFromStatic; // CHECK-CTORS-NOT: @llvm.invariant.group.barrier( // CHECK-CTORS-LABEL: {{^}}} +struct A { + virtual void foo(); +}; +struct B : A { + virtual void foo(); +}; + +union U { + A a; + B b; +}; + +void changeToB(U *u); +void changeToA(U *u); + +void g2(A *a) { + a->foo(); +} +// We have to guard access to union fields with invariant.group, because +// it is very easy to skip the barrier with unions. In this example the inlined +// g2 will produce loads with the same !invariant.group metadata, and +// u->a and u->b would use the same pointer. +// CHECK-NEW-LABEL: define void @_Z14UnionsBarriersP1U +void UnionsBarriers(U *u) { + // CHECK-NEW: call void @_Z9changeToBP1U( + changeToB(u); + // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call void @_Z2g2P1A(%struct.A* + g2(&u->b); + // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* + changeToA(u); + // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // call void @_Z2g2P1A(%struct.A* %a) + g2(&u->a); + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* +} + +struct HoldingVirtuals { + A a; +}; + +struct Empty {}; +struct AnotherEmpty { + Empty e; +}; +union NoVptrs { + int a; + AnotherEmpty empty; +}; +void take(AnotherEmpty &); + +// CHECK-NEW-LABEL: noBarriers +void noBarriers(NoVptrs &noVptrs) { + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: 42 + noVptrs.a += 42; + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call void @_Z4takeR12AnotherEmpty( + take(noVptrs.empty); +} + +union U2 { + HoldingVirtuals h; + int z; +}; +void take(HoldingVirtuals &); + +// CHECK-NEW-LABEL: define void @_Z15UnionsBarriers2R2U2 +void UnionsBarriers2(U2 &u) { + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: 42 + u.z += 42; + // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals( + take(u.h); +} + +struct VirtualInBase : HoldingVirtuals, Empty { +}; + +struct VirtualInVBase : virtual Empty, virtual HoldingVirtuals { +}; + +// It has vtable by virtual inheritance. +struct VirtualInheritance : virtual Empty { +}; + +union U3 { + VirtualInBase v1; + VirtualInBase v2; + VirtualInheritance v3; + int z; +}; + +void take(VirtualInBase &); +void take(VirtualInVBase &); +void take(VirtualInheritance &); + +void UnionsBarrier3(U3 &u) { + // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: 42 + u.z += 42; + // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call void @_Z4takeR13VirtualInBase( + take(u.v1); + // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call void @_Z4takeR13VirtualInBase( + take(u.v2); + + // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8* + // CHECK-NEW: call void @_Z4takeR18VirtualInheritance( + take(u.v3); +} /** DTORS **/ // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev( diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index ae81959a75e9..db99f73d9e72 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -12,6 +12,7 @@ // RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt #include @@ -274,8 +275,8 @@ struct C { virtual D& operator=(const D&); }; -// Cannot emit B's vtable available_externally, because we cannot create -// a reference to the inline virtual B::operator= function. +// Cannot emit D's vtable available_externally, because we cannot create +// a reference to the inline virtual D::operator= function. // CHECK-TEST11: @_ZTVN6Test111DE = external unnamed_addr constant struct D : C { virtual void key(); @@ -391,3 +392,30 @@ void test() { } } +namespace Test17 { +// This test checks if we emit vtables opportunistically. +// CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-TEST17-DAG: @_ZTVN6Test171BE = external + +struct A { + virtual void key(); + virtual void bar() {} +}; + +// We won't gonna use deleting destructor for this type, which will disallow +// emitting vtable as available_externally +struct B { + virtual void key(); + virtual ~B() {} +}; + +void testcaseA() { + A a; + a.bar(); // this forces to emit definition of bar +} + +void testcaseB() { + B b; // This only forces emitting of complete object destructor +} + +} // namespace Test17 diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index c4ebf75b999a..0c55eb26f7f1 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -145,12 +145,14 @@ void use_F() { // F is an explicit template instantiation declaration without a // key function, so its vtable should have external linkage. // CHECK-DAG: @_ZTV1FIiE = external unnamed_addr constant -// CHECK-OPT-DAG: @_ZTV1FIiE = external unnamed_addr constant +// CHECK-OPT-DAG: @_ZTV1FIiE = available_externally unnamed_addr constant // E is an explicit template instantiation declaration. It has a // key function is not instantiated, so we know that vtable definition // will be generated in TU where key function will be defined -// so we can mark it as available_externally (only with optimizations) +// so we can mark it as external (without optimizations) and +// available_externally (with optimizations) because all of the inline +// virtual functions have been emitted. // CHECK-DAG: @_ZTV1EIiE = external unnamed_addr constant // CHECK-OPT-DAG: @_ZTV1EIiE = available_externally unnamed_addr constant diff --git a/test/CodeGenCoroutines/coro-await-domination.cpp b/test/CodeGenCoroutines/coro-await-domination.cpp new file mode 100644 index 000000000000..5df22374a6e7 --- /dev/null +++ b/test/CodeGenCoroutines/coro-await-domination.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - | FileCheck %s +#include "Inputs/coroutine.h" + +using namespace std::experimental; + +struct coro { + struct promise_type { + coro get_return_object(); + suspend_never initial_suspend(); + suspend_never final_suspend(); + void return_void(); + static void unhandled_exception(); + }; +}; + +struct A { + ~A(); + bool await_ready(); + int await_resume() { return 8; } + template void await_suspend(F); +}; + +extern "C" void consume(int); + +// Verifies that domination is properly built during cleanup. +// Without CGCleanup.cpp fix verifier was reporting: +// Instruction does not dominate all uses! +// %tmp.exprcleanup = alloca i32*, align 8 +// store i32* %x, i32** %tmp.exprcleanup, align 8 + + +// CHECK-LABEL: f( +extern "C" coro f(int) { + int x = 42; + x = co_await A{}; + consume(x); +} + diff --git a/test/CodeGenObjC/parameterized_classes.m b/test/CodeGenObjC/parameterized_classes.m index b75cf2e3ad2d..8fe5c52b8d39 100644 --- a/test/CodeGenObjC/parameterized_classes.m +++ b/test/CodeGenObjC/parameterized_classes.m @@ -68,3 +68,31 @@ void blockTest(NSMutableArray *array, NSString *name) { // CHECK: call i8* @objc_retainBlock // CHECK: ret void } + +// CHECK-LABEL: define internal void @"\01-[Derived setDest:] +// CHECK: %[[SELFADDR:.*]] = alloca %[[SELFTY:.*]]* +// CHECK: %[[AADDR:.*]] = alloca %[[IVARTY:.*]]* +// CHECK: %[[V2:.*]] = load %[[IVARTY]]*, %[[IVARTY]]** %[[AADDR]] +// CHECK: %[[V3:.*]] = load %[[SELFTY]]*, %[[SELFTY]]** %[[SELFADDR]] +// CHECK: %[[IVAR:.*]] = load i64, i64* @"OBJC_IVAR_$_Base._destination" +// CHECK: %[[V4:.*]] = bitcast %[[SELFTY]]* %[[V3]] to i8* +// CHECK: %[[ADDPTR:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 %[[IVAR]] +// CHECK: %[[V5:.*]] = bitcast i8* %[[ADDPTR]] to %[[IVARTY]]** +// CHECK: %[[V6:.*]] = bitcast %[[IVARTY]]** %[[V5]] to i8** +// CHECK: %[[V7:.*]] = bitcast %[[IVARTY]]* %[[V2]] to i8* +// CHECK: call void @objc_storeStrong(i8** %[[V6]], i8* %[[V7]]) + +@interface Base : NSObject { + DestType _destination; +} +@end + +@interface Derived : Base +- (void)setDest:(NSObject *)a; +@end + +@implementation Derived +- (void)setDest:(NSObject *)a { + _destination = a; +} +@end diff --git a/test/CodeGenOpenCL/bool_cast.cl b/test/CodeGenOpenCL/bool_cast.cl index ab40eccf571f..72926eb141ab 100644 --- a/test/CodeGenOpenCL/bool_cast.cl +++ b/test/CodeGenOpenCL/bool_cast.cl @@ -4,7 +4,7 @@ typedef unsigned char uchar4 __attribute((ext_vector_type(4))); typedef unsigned int int4 __attribute((ext_vector_type(4))); typedef float float4 __attribute((ext_vector_type(4))); -// CHECK-LABEL: define void @ker() +// CHECK-LABEL: define spir_kernel void @ker() void kernel ker() { bool t = true; int4 vec4 = (int4)t; diff --git a/test/CodeGenOpenCL/kernel-attributes.cl b/test/CodeGenOpenCL/kernel-attributes.cl index e61a75f7b537..eff2e57d8c9b 100644 --- a/test/CodeGenOpenCL/kernel-attributes.cl +++ b/test/CodeGenOpenCL/kernel-attributes.cl @@ -3,13 +3,13 @@ typedef unsigned int uint4 __attribute__((ext_vector_type(4))); kernel __attribute__((vec_type_hint(int))) __attribute__((reqd_work_group_size(1,2,4))) void kernel1(int a) {} -// CHECK: define void @kernel1(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD1:[0-9]+]] !reqd_work_group_size ![[MD2:[0-9]+]] +// CHECK: define spir_kernel void @kernel1(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD1:[0-9]+]] !reqd_work_group_size ![[MD2:[0-9]+]] kernel __attribute__((vec_type_hint(uint4))) __attribute__((work_group_size_hint(8,16,32))) void kernel2(int a) {} -// CHECK: define void @kernel2(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD3:[0-9]+]] !work_group_size_hint ![[MD4:[0-9]+]] +// CHECK: define spir_kernel void @kernel2(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD3:[0-9]+]] !work_group_size_hint ![[MD4:[0-9]+]] kernel __attribute__((intel_reqd_sub_group_size(8))) void kernel3(int a) {} -// CHECK: define void @kernel3(i32 {{[^%]*}}%a) {{[^{]+}} !intel_reqd_sub_group_size ![[MD5:[0-9]+]] +// CHECK: define spir_kernel void @kernel3(i32 {{[^%]*}}%a) {{[^{]+}} !intel_reqd_sub_group_size ![[MD5:[0-9]+]] // CHECK: [[MD1]] = !{i32 undef, i32 1} // CHECK: [[MD2]] = !{i32 1, i32 2, i32 4} diff --git a/test/CodeGenOpenCL/kernel-metadata.cl b/test/CodeGenOpenCL/kernel-metadata.cl index 4165f1fa0ce5..95be43015aa9 100644 --- a/test/CodeGenOpenCL/kernel-metadata.cl +++ b/test/CodeGenOpenCL/kernel-metadata.cl @@ -6,5 +6,5 @@ void normal_function() { __kernel void kernel_function() { } -// CHECK: define void @kernel_function() {{[^{]+}} !kernel_arg_addr_space ![[MD:[0-9]+]] !kernel_arg_access_qual ![[MD]] !kernel_arg_type ![[MD]] !kernel_arg_base_type ![[MD]] !kernel_arg_type_qual ![[MD]] { +// CHECK: define spir_kernel void @kernel_function() {{[^{]+}} !kernel_arg_addr_space ![[MD:[0-9]+]] !kernel_arg_access_qual ![[MD]] !kernel_arg_type ![[MD]] !kernel_arg_base_type ![[MD]] !kernel_arg_type_qual ![[MD]] { // CHECK: ![[MD]] = !{} diff --git a/test/CodeGenOpenCL/kernels-have-spir-cc-by-default.cl b/test/CodeGenOpenCL/kernels-have-spir-cc-by-default.cl new file mode 100644 index 000000000000..5bb52e9beb51 --- /dev/null +++ b/test/CodeGenOpenCL/kernels-have-spir-cc-by-default.cl @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 %s -cl-std=CL1.2 -emit-llvm -triple x86_64-unknown-unknown -o - | FileCheck %s +// RUN: %clang_cc1 %s -cl-std=CL1.2 -emit-llvm -triple amdgcn-unknown-unknown -o - | FileCheck -check-prefixes=AMDGCN %s +// Test that the kernels always use the SPIR calling convention +// to have unambiguous mapping of arguments to feasibly implement +// clSetKernelArg(). + +typedef struct int_single { + int a; +} int_single; + +typedef struct int_pair { + long a; + long b; +} int_pair; + +typedef struct test_struct { + int elementA; + int elementB; + long elementC; + char elementD; + long elementE; + float elementF; + short elementG; + double elementH; +} test_struct; + +kernel void test_single(int_single input, global int* output) { +// CHECK: spir_kernel +// AMDGCN: define amdgpu_kernel void @test_single +// CHECK: struct.int_single* byval nocapture +// CHECK: i32* nocapture %output + output[0] = input.a; +} + +kernel void test_pair(int_pair input, global int* output) { +// CHECK: spir_kernel +// AMDGCN: define amdgpu_kernel void @test_pair +// CHECK: struct.int_pair* byval nocapture +// CHECK: i32* nocapture %output + output[0] = (int)input.a; + output[1] = (int)input.b; +} + +kernel void test_kernel(test_struct input, global int* output) { +// CHECK: spir_kernel +// AMDGCN: define amdgpu_kernel void @test_kernel +// CHECK: struct.test_struct* byval nocapture +// CHECK: i32* nocapture %output + output[0] = input.elementA; + output[1] = input.elementB; + output[2] = (int)input.elementC; + output[3] = (int)input.elementD; + output[4] = (int)input.elementE; + output[5] = (int)input.elementF; + output[6] = (int)input.elementG; + output[7] = (int)input.elementH; +}; + +void test_function(int_pair input, global int* output) { +// CHECK-NOT: spir_kernel +// AMDGCN-NOT: define amdgpu_kernel void @test_function +// CHECK: i64 %input.coerce0, i64 %input.coerce1, i32* nocapture %output + output[0] = (int)input.a; + output[1] = (int)input.b; +} diff --git a/test/CodeGenOpenCL/pipe_types.cl b/test/CodeGenOpenCL/pipe_types.cl index f5b42e2a490f..7c11f74ad7b9 100644 --- a/test/CodeGenOpenCL/pipe_types.cl +++ b/test/CodeGenOpenCL/pipe_types.cl @@ -28,7 +28,7 @@ void test5(read_only pipe int4 p) { typedef read_only pipe int MyPipe; kernel void test6(MyPipe p) { -// CHECK: define void @test6(%opencl.pipe_t* %p) +// CHECK: define spir_kernel void @test6(%opencl.pipe_t* %p) } struct Person { diff --git a/test/CodeGenOpenCL/ptx-calls.cl b/test/CodeGenOpenCL/ptx-calls.cl index bde00bc3d73a..2a3400371edf 100644 --- a/test/CodeGenOpenCL/ptx-calls.cl +++ b/test/CodeGenOpenCL/ptx-calls.cl @@ -7,7 +7,7 @@ void device_function() { __kernel void kernel_function() { device_function(); } -// CHECK-LABEL: define void @kernel_function() +// CHECK-LABEL: define spir_kernel void @kernel_function() // CHECK: call void @device_function() // CHECK: !{{[0-9]+}} = !{void ()* @kernel_function, !"kernel", i32 1} diff --git a/test/CodeGenOpenCL/ptx-kernels.cl b/test/CodeGenOpenCL/ptx-kernels.cl index fc6de4f3d517..b9e1c224c7ce 100644 --- a/test/CodeGenOpenCL/ptx-kernels.cl +++ b/test/CodeGenOpenCL/ptx-kernels.cl @@ -6,6 +6,6 @@ void device_function() { __kernel void kernel_function() { } -// CHECK-LABEL: define void @kernel_function() +// CHECK-LABEL: define spir_kernel void @kernel_function() // CHECK: !{{[0-9]+}} = !{void ()* @kernel_function, !"kernel", i32 1} diff --git a/test/Driver/arm-cortex-cpus.c b/test/Driver/arm-cortex-cpus.c index c52e643f0337..80912678e029 100644 --- a/test/Driver/arm-cortex-cpus.c +++ b/test/Driver/arm-cortex-cpus.c @@ -120,11 +120,11 @@ // RUN: %clang -target armv7a-linux-gnueabi -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7A %s // RUN: %clang -target arm-linux-gnueabi -march=armv7-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7A %s -// CHECK-V7A: "-cc1"{{.*}} "-triple" "armv7-{{.*}} "-target-cpu" "cortex-a8" +// CHECK-V7A: "-cc1"{{.*}} "-triple" "armv7-{{.*}} "-target-cpu" "generic" // RUN: %clang -target armv7a-linux-gnueabi -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7A-THUMB %s // RUN: %clang -target arm-linux-gnueabi -march=armv7-a -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7A-THUMB %s -// CHECK-V7A-THUMB: "-cc1"{{.*}} "-triple" "thumbv7-{{.*}} "-target-cpu" "cortex-a8" +// CHECK-V7A-THUMB: "-cc1"{{.*}} "-triple" "thumbv7-{{.*}} "-target-cpu" "generic" // RUN: %clang -target armv7r-linux-gnueabi -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7R %s // RUN: %clang -target arm-linux-gnueabi -march=armv7-r -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7R %s @@ -144,7 +144,7 @@ // RUN: %clang -target armv8a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A %s // RUN: %clang -target arm -march=armv8a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A %s // RUN: %clang -target arm -mlittle-endian -march=armv8-a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A %s -// CHECK-V8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}}" "-target-cpu" "cortex-a53" +// CHECK-V8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}}" "-target-cpu" "generic" // RUN: %clang -target armv8r-linux-gnueabi -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R %s // RUN: %clang -target arm -march=armv8r -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R %s @@ -189,7 +189,7 @@ // RUN: %clang -target armv8a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A %s // RUN: %clang -target arm -march=armebv8a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A %s // RUN: %clang -target arm -march=armebv8-a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A %s -// CHECK-BE-V8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}}" "-target-cpu" "cortex-a53" +// CHECK-BE-V8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}}" "-target-cpu" "generic" // RUN: %clang -target armv8 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s // RUN: %clang -target arm -march=armv8 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s @@ -199,7 +199,7 @@ // RUN: %clang -target arm -march=armv8 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s // RUN: %clang -target armv8a -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s // RUN: %clang -target arm -march=armv8a -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s -// CHECK-V8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}}" "-target-cpu" "cortex-a53" +// CHECK-V8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}}" "-target-cpu" "generic" // RUN: %clang -target armebv8 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s // RUN: %clang -target armeb -march=armebv8 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s @@ -209,7 +209,7 @@ // RUN: %clang -target arm -march=armebv8 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s // RUN: %clang -target armv8a -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s // RUN: %clang -target arm -march=armebv8a -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s -// CHECK-BE-V8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}}" "-target-cpu" "cortex-a53" +// CHECK-BE-V8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}}" "-target-cpu" "generic" // RUN: %clang -target arm -march=armv8.1a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V81A %s // RUN: %clang -target armv8.1a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V81A %s diff --git a/test/Driver/cl-cc-flags.c b/test/Driver/cl-cc-flags.c new file mode 100644 index 000000000000..76f116e199e2 --- /dev/null +++ b/test/Driver/cl-cc-flags.c @@ -0,0 +1,33 @@ +// Note: %s must be preceded by --, otherwise it may be interpreted as a +// command-line option, e.g. on Mac where %s is commonly under /Users. + +// RUN: %clang_cl --target=i686-windows-msvc /Gd -### -- %s 2>&1 | FileCheck --check-prefix=CDECL %s +// CDECL: -fdefault-calling-conv=cdecl + +// RUN: %clang_cl --target=i686-windows-msvc /Gr -### -- %s 2>&1 | FileCheck --check-prefix=FASTCALL %s +// FASTCALL: -fdefault-calling-conv=fastcall + +// RUN: %clang_cl --target=i686-windows-msvc /Gz -### -- %s 2>&1 | FileCheck --check-prefix=STDCALL %s +// STDCALL: -fdefault-calling-conv=stdcall + +// RUN: %clang_cl --target=i686-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=VECTORCALL %s +// VECTORCALL: -fdefault-calling-conv=vectorcall + +// Last one should win: + +// RUN: %clang_cl --target=i686-windows-msvc /Gd /Gv -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_VECTOR %s +// LASTWINS_VECTOR: -fdefault-calling-conv=vectorcall + +// RUN: %clang_cl --target=i686-windows-msvc /Gv /Gd -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_CDECL %s +// LASTWINS_CDECL: -fdefault-calling-conv=cdecl + +// No fastcall or stdcall on x86_64: + +// RUN: %clang_cl -Wno-msvc-not-found --target=x86_64-windows-msvc /Gr -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s +// RUN: %clang_cl -Wno-msvc-not-found --target=x86_64-windows-msvc /Gz -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s +// RUN: %clang_cl -Wno-msvc-not-found --target=thumbv7-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s + +// UNSUPPORTED-NOT: error: +// UNSUPPORTED-NOT: warning: +// UNSUPPORTED-NOT: -fdefault-calling-conv= + diff --git a/test/Driver/cl-diagnostics.c b/test/Driver/cl-diagnostics.c new file mode 100644 index 000000000000..975a8cf8bb54 --- /dev/null +++ b/test/Driver/cl-diagnostics.c @@ -0,0 +1,28 @@ +// Note: %s must be preceded by --, otherwise it may be interpreted as a +// command-line option, e.g. on Mac where %s is commonly under /Users. + +// RUN: %clang_cl /diagnostics:classic -### -- %s 2>&1 | FileCheck %s --check-prefix=CLASSIC +// CLASSIC: -fno-caret-diagnostics +// CLASSIC: -fno-show-column + +// RUN: %clang_cl /diagnostics:column -### -- %s 2>&1 | FileCheck %s --check-prefix=COLUMN +// COLUMN: -fno-caret-diagnostics +// COLUMN-NOT: -fno-show-column + +// RUN: %clang_cl /diagnostics:caret -### -- %s 2>&1 | FileCheck %s --check-prefix=CARET +// CARET-NOT: -fno-caret-diagnostics +// CARET-NOT: -fno-show-column + +// RUN: not %clang_cl -fms-compatibility-version=19 /diagnostics:classic /Zs -c -- %s 2>&1 | FileCheck %s --check-prefix=OUTPUT_CLASSIC + +// OUTPUT_CLASSIC: cl-diagnostics.c({{[0-9]+}}): error: "asdf" +// OUTPUT_CLASSIC-NOT: #error + +// RUN: not %clang_cl -fms-compatibility-version=19 /diagnostics:caret /Zs -c -- %s 2>&1 | FileCheck %s --check-prefix=OUTPUT_CARET + +// OUTPUT_CARET: cl-diagnostics.c({{[0-9]+,[0-9]+}}): error: "asdf" +// OUTPUT_CARET-NEXT: #error "asdf" +// OUTPUT_CARET-NEXT: ^ + + +#error "asdf" diff --git a/test/Driver/cl-include.c b/test/Driver/cl-include.c new file mode 100644 index 000000000000..d3dc006e575f --- /dev/null +++ b/test/Driver/cl-include.c @@ -0,0 +1,14 @@ +// Note: %s must be preceded by --, otherwise it may be interpreted as a +// command-line option, e.g. on Mac where %s is commonly under /Users. + +// RUN: %clang_cl -### -- %s 2>&1 | FileCheck %s --check-prefix=BUILTIN +// BUILTIN: "-internal-isystem" "{{.*lib.*clang.*include}}" + +// RUN: %clang_cl -nobuiltininc -### -- %s 2>&1 | FileCheck %s --check-prefix=NOBUILTIN +// NOBUILTIN-NOT: "-internal-isystem" "{{.*lib.*clang.*include}}" + +// RUN: env INCLUDE=/my/system/inc %clang_cl -### -- %s 2>&1 | FileCheck %s --check-prefix=STDINC +// STDINC: "-internal-isystem" "/my/system/inc" + +// RUN: env INCLUDE=/my/system/inc %clang_cl -nostdinc -### -- %s 2>&1 | FileCheck %s --check-prefix=NOSTDINC +// NOSTDINC-NOT: "-internal-isystem" "/my/system/inc" diff --git a/test/Driver/cl-zc.cpp b/test/Driver/cl-zc.cpp index 26496293201e..4414eb6ebba2 100644 --- a/test/Driver/cl-zc.cpp +++ b/test/Driver/cl-zc.cpp @@ -53,6 +53,11 @@ // RUN: %clang_cl /c -### /Zc:inline- -- %s 2>&1 | FileCheck -check-prefix=INLINE-OFF %s // INLINE-OFF: argument unused during compilation +// RUN: %clang_cl /c -### /Zc:ternary -- %s 2>&1 | FileCheck -check-prefix=TERNARY-ON %s +// TERNARY-ON-NOT: argument unused during compilation +// RUN: %clang_cl /c -### /Zc:ternary- -- %s 2>&1 | FileCheck -check-prefix=TERNARY-OFF %s +// TERNARY-OFF: argument unused during compilation + // These never warn, but don't have an effect yet. diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 41f573aa7316..786f517f5371 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -3,18 +3,18 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP // RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP -// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} -// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" -// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" +// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute|function),?){19}"}} +// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" +// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED -// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){19}"}} +// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){20}"}} // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-DARWIN -// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} +// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}} // RUN: %clang -target i386-unknown-openbsd -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-OPENBSD -// CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} +// CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}} // RUN: %clang -target i386-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 // RUN: %clang -target i386-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 --check-prefix=CHECK-UNDEFINED-WIN-CXX @@ -23,7 +23,7 @@ // CHECK-UNDEFINED-WIN32: "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib" // CHECK-UNDEFINED-WIN64: "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib" // CHECK-UNDEFINED-WIN-CXX: "--dependent-lib={{[^"]*}}ubsan_standalone_cxx{{[^"]*}}.lib" -// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} +// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}} // RUN: %clang -target i386-pc-win32 -fsanitize-coverage=bb %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-COVERAGE-WIN32 // CHECK-COVERAGE-WIN32: "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib" @@ -43,7 +43,7 @@ // CHECK-FNO-SANITIZE-ALL: "-fsanitize=thread" // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-sanitize=thread -fno-sanitize=float-cast-overflow,vptr,bool,enum %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED -// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|array-bounds|returns-nonnull-attribute|nonnull-attribute),?){15}"}} +// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|array-bounds|returns-nonnull-attribute|nonnull-attribute),?){16}"}} // RUN: %clang -target x86_64-linux-gnu -fsanitize=shift -fno-sanitize=shift-base %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSANITIZE-SHIFT-PARTIAL // CHECK-FSANITIZE-SHIFT-PARTIAL: "-fsanitize=shift-exponent" @@ -217,7 +217,7 @@ // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=all -fsanitize-recover=thread -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fsanitize-recover=all -fno-sanitize-recover=undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN -// CHECK-RECOVER-UBSAN: "-fsanitize-recover={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} +// CHECK-RECOVER-UBSAN: "-fsanitize-recover={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|vla-bound|alignment|null|vptr|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}} // CHECK-NO-RECOVER-UBSAN-NOT: sanitize-recover // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=all -fsanitize-recover=object-size,shift-base -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-RECOVER diff --git a/test/Driver/gold-lto.c b/test/Driver/gold-lto.c index 050b1ef18be1..b8eca5112b5a 100644 --- a/test/Driver/gold-lto.c +++ b/test/Driver/gold-lto.c @@ -19,7 +19,7 @@ // RUN: -march=armv7a -Wl,-plugin-opt=foo -O0 \ // RUN: | FileCheck %s --check-prefix=CHECK-ARM-V7A // CHECK-ARM-V7A: "-plugin" "{{.*}}/LLVMgold.so" -// CHECK-ARM-V7A: "-plugin-opt=mcpu=cortex-a8" +// CHECK-ARM-V7A: "-plugin-opt=mcpu=generic" // CHECK-ARM-V7A: "-plugin-opt=O0" // CHECK-ARM-V7A: "-plugin-opt=foo" // diff --git a/test/Driver/nacl-direct.c b/test/Driver/nacl-direct.c index f71e14f996ee..3c8e33b180b0 100644 --- a/test/Driver/nacl-direct.c +++ b/test/Driver/nacl-direct.c @@ -46,7 +46,7 @@ // RUN: | FileCheck --check-prefix=CHECK-ARM %s // CHECK-ARM: {{.*}}clang{{.*}}" "-cc1" // CHECK-ARM: "-fuse-init-array" -// CHECK-ARM: "-target-cpu" "cortex-a8" +// CHECK-ARM: "-target-cpu" "generic" // CHECK-ARM: "-target-abi" "aapcs-linux" // CHECK-ARM: "-mfloat-abi" "hard" // CHECK-ARM: "-resource-dir" "foo" diff --git a/test/Driver/openmp-offload.c b/test/Driver/openmp-offload.c index 097dc7d17faa..39eb41e6ac08 100644 --- a/test/Driver/openmp-offload.c +++ b/test/Driver/openmp-offload.c @@ -210,14 +210,16 @@ // CHK-LKS-ST: INPUT([[T2BIN:.+\.out-openmp-x86_64-pc-linux-gnu]]) // CHK-LKS: SECTIONS // CHK-LKS: { -// CHK-LKS: .omp_offloading : +// CHK-LKS: .omp_offloading.powerpc64le-ibm-linux-gnu : // CHK-LKS: ALIGN(0x10) // CHK-LKS: { -// CHK-LKS: . = ALIGN(0x10); // CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_start.powerpc64le-ibm-linux-gnu = .); // CHK-LKS: [[T1BIN]] // CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_end.powerpc64le-ibm-linux-gnu = .); -// CHK-LKS: . = ALIGN(0x10); +// CHK-LKS: } +// CHK-LKS: .omp_offloading.x86_64-pc-linux-gnu : +// CHK-LKS: ALIGN(0x10) +// CHK-LKS: { // CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_start.x86_64-pc-linux-gnu = .); // CHK-LKS: [[T2BIN]] // CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_end.x86_64-pc-linux-gnu = .); diff --git a/test/Misc/diag-mapping2.c b/test/Misc/diag-mapping2.c index 672d0548ad82..c3afea94b370 100644 --- a/test/Misc/diag-mapping2.c +++ b/test/Misc/diag-mapping2.c @@ -4,6 +4,7 @@ // This should not emit anything. // RUN: %clang_cc1 %s -w 2>&1 | not grep diagnostic // RUN: %clang_cc1 %s -Wno-#warnings 2>&1 | not grep diagnostic +// RUN: %clang_cc1 %s -Wno-cpp 2>&1 | not grep diagnostic // -Werror can map all warnings to error. // RUN: not %clang_cc1 %s -Werror 2>&1 | grep "error: foo" diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index 947583bcfd21..a6a0b74743aa 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -866,6 +866,40 @@ S9 s9; #endif } +namespace TemplateSpecializationType { +#if defined(FIRST) +template struct U1 {}; +struct S1 { + U1 u; +}; +#elif defined(SECOND) +template struct U1 {}; +struct S1 { + U1 u; +}; +#else +S1 s1; +// expected-error@first.h:* {{'TemplateSpecializationType::S1::u' from module 'FirstModule' is not present in definition of 'TemplateSpecializationType::S1' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'u' does not match}} +#endif + +#if defined(FIRST) +template struct U2 {}; +struct S2 { + U2 u; +}; +#elif defined(SECOND) +template struct V1 {}; +struct S2 { + V1 u; +}; +#else +S2 s2; +// expected-error@first.h:* {{'TemplateSpecializationType::S2::u' from module 'FirstModule' is not present in definition of 'TemplateSpecializationType::S2' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'u' does not match}} +#endif +} + // Interesting cases that should not cause errors. struct S should not error // while struct T should error at the access specifier mismatch at the end. namespace AllDecls { diff --git a/test/Modules/preprocess-module.cpp b/test/Modules/preprocess-module.cpp index eaab3136938f..9d1a2bb6801f 100644 --- a/test/Modules/preprocess-module.cpp +++ b/test/Modules/preprocess-module.cpp @@ -14,8 +14,6 @@ // RUN: FileCheck %s --input-file %t/rewrite.ii --check-prefix=CHECK --check-prefix=REWRITE // Check that we can build a module from the preprocessed output. -// FIXME: For now, we need the headers to exist. -// RUN: touch %t/file.h %t/file2.h // RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm // RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm @@ -27,6 +25,8 @@ // Check the module we built works. // RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -I%t -verify -fno-modules-error-recovery // RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DREWRITE +// RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DINCLUDE -I%S/Inputs/preprocess +// RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DREWRITE -DINCLUDE -I%S/Inputs/preprocess // == module map @@ -102,7 +102,11 @@ __FILE *a; // expected-error {{declaration of '__FILE' must be imported}} // expected-note@no-rewrite.ii:1 {{here}} #endif +#ifdef INCLUDE +#include "file.h" +#else #pragma clang module import file +#endif FILE *b; -int x = file2; +int x = file2; // ok, found in file2.h, even under -DINCLUDE diff --git a/test/Modules/preprocess-nested.cpp b/test/Modules/preprocess-nested.cpp index 8fccf137e94f..f26b65507ece 100644 --- a/test/Modules/preprocess-nested.cpp +++ b/test/Modules/preprocess-nested.cpp @@ -8,8 +8,6 @@ // RUN: FileCheck %s --input-file %t/rewrite.ii --check-prefix=CHECK --check-prefix=REWRITE // Check that we can build a module from the preprocessed output. -// FIXME: For now, the files need to exist. -// RUN: touch %t/a.h %t/b.h %t/c.h // RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm // RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm diff --git a/test/Modules/preprocess-unavailable.cpp b/test/Modules/preprocess-unavailable.cpp index e568cd7b5251..cfd18253daf7 100644 --- a/test/Modules/preprocess-unavailable.cpp +++ b/test/Modules/preprocess-unavailable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -x c++-module-map %s -fmodule-name=a -verify +// RUN: %clang_cc1 -x c++-module-map %s -fmodule-name=a -verify -std=c++98 module a { module b { requires cplusplus11 diff --git a/test/SemaCXX/attr-require-constant-initialization.cpp b/test/SemaCXX/attr-require-constant-initialization.cpp index 3ed51071cd13..0df9f2e88029 100644 --- a/test/SemaCXX/attr-require-constant-initialization.cpp +++ b/test/SemaCXX/attr-require-constant-initialization.cpp @@ -7,9 +7,9 @@ #define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}} -int ReturnInt(); +int ReturnInt(); // expected-note 0+ {{declared here}} -struct PODType { +struct PODType { // expected-note 0+ {{declared here}} int value; int value2; }; @@ -20,20 +20,20 @@ struct PODType { struct LitType { constexpr LitType() : value(0) {} constexpr LitType(int x) : value(x) {} - LitType(void *) : value(-1) {} + LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}} int value; }; #endif -struct NonLit { +struct NonLit { // expected-note 0+ {{declared here}} #if __cplusplus >= 201402L constexpr NonLit() : value(0) {} constexpr NonLit(int x) : value(x) {} #else - NonLit() : value(0) {} + NonLit() : value(0) {} // expected-note 0+ {{declared here}} NonLit(int x) : value(x) {} #endif - NonLit(void *) : value(-1) {} + NonLit(void *) : value(-1) {} // expected-note 0+ {{declared here}} ~NonLit() {} int value; }; @@ -43,7 +43,7 @@ struct StoresNonLit { constexpr StoresNonLit() : obj() {} constexpr StoresNonLit(int x) : obj(x) {} #else - StoresNonLit() : obj() {} + StoresNonLit() : obj() {} // expected-note 0+ {{declared here}} StoresNonLit(int x) : obj(x) {} #endif StoresNonLit(void *p) : obj(p) {} @@ -82,6 +82,12 @@ void test_basic_start_static_2_1() { const int non_global = 42; ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +#if __cplusplus >= 201103L + // expected-note@-3 {{reference to 'non_global' is not a constant expression}} + // expected-note@-5 {{declared here}} +#else + // expected-note@-6 {{subexpression not valid in a constant expression}} +#endif ATTR static const int &global_init = glvalue_int; ATTR static const int &temp_init = 42; } @@ -89,8 +95,18 @@ void test_basic_start_static_2_1() { ATTR const int &temp_ref = 42; ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +#if __cplusplus >= 201103L +// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +#if __cplusplus >= 201103L +// expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a constant expression}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif #if __cplusplus >= 201103L ATTR const LitType &lit_temp_ref = 42; @@ -99,6 +115,11 @@ ATTR const int &subobj_ref = LitType{}.value; ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +#if __cplusplus >= 201103L +// expected-note-re@-3 {{non-literal type '{{.*}}' cannot be used in a constant expression}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif struct TT1 { ATTR static const int &no_init; @@ -116,6 +137,8 @@ const int &TT1::subobj_init = PODType().value; #if __cplusplus >= 201103L thread_local const int &TT1::tl_glvalue_init = glvalue_int; thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{reference to temporary is not a constant expression}} +// expected-note@-2 {{temporary created here}} #endif // [basic.start.static]p2.2 @@ -129,17 +152,25 @@ void test_basic_start_static_2_2() { #else ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}} #endif ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +#if __cplusplus >= 201103L +// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif #if __cplusplus >= 201103L constexpr LitType l; ATTR static LitType static_lit = l; ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} + // expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}} ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} + // expected-note@-2 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} ATTR thread_local LitType tls = 42; #endif } @@ -157,15 +188,23 @@ struct TT2 { ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initialization' attribute here}} #endif }; -PODType TT2::pod_noinit; +PODType TT2::pod_noinit; // expected-note 0+ {{declared here}} #if __cplusplus >= 201103L // expected-error@-2 {{variable does not have a constant initializer}} +// expected-note@-3 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}} #endif PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}} +#if __cplusplus >= 201103L +// expected-note@-2 {{read of non-constexpr variable 'pod_noinit' is not allowed in a constant expression}} +// expected-note@-3 {{in call to 'PODType(pod_noinit)'}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif #if __cplusplus >= 201402L const NonLit TT2::non_lit(42); const NonLit TT2::non_lit_list_init = {42}; const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{subexpression not valid in a constant expression}} #endif #if __cplusplus >= 201103L @@ -183,19 +222,25 @@ ATTR StoresNonLit snl; #else ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'StoresNonLit' cannot be used in a constant expression}} #endif // Non-literal types cannot appear in the initializer of a non-literal type. ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{non-literal type 'NonLit' cannot be used in a constant expression}} ATTR int lit_in_init = LitType{42}.value; #endif @@ -218,6 +263,11 @@ ATTR PODType pod_missing_init = {42 /* should have second arg */}; ATTR PODType pod_full_init = {1, 2}; ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +#if __cplusplus >= 201103L +// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif #if __cplusplus >= 201103L ATTR int val_init{}; @@ -233,15 +283,17 @@ typedef const char *StrType; // initializer struct NotC { constexpr NotC(void *) {} - NotC(int) {} + NotC(int) {} // expected-note 0+ {{declared here}} }; template struct TestCtor { constexpr TestCtor(int x) : value(x) {} + // expected-note@-1 {{non-constexpr constructor 'NotC' cannot be used in a constant expression}} T value; }; ATTR TestCtor t(42); // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{in call to 'TestCtor(42)'}} #endif // Test various array types @@ -261,9 +313,11 @@ struct TestCtor { ATTR LitType non_const_lit(nullptr); // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}} ATTR NonLit non_const(nullptr); // expected-error {{variable does not have a constant initializer}} // expected-warning@-1 {{declaration requires a global destructor}} // expected-note@-2 {{required by 'require_constant_initialization' attribute here}} +// expected-note@-3 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} LitType const_init_lit(nullptr); // expected-warning {{declaration requires a global constructor}} NonLit const_init{42}; // expected-warning {{declaration requires a global destructor}} constexpr TestCtor inval_constexpr(42); // expected-error {{must be initialized by a constant expression}} diff --git a/test/SemaCXX/coreturn.cpp b/test/SemaCXX/coreturn.cpp index 0ec94d1b5997..7265d7c19c2e 100644 --- a/test/SemaCXX/coreturn.cpp +++ b/test/SemaCXX/coreturn.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wno-unreachable-code -Wno-unused-value +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wall -Wextra -Wno-error=unreachable-code #include "Inputs/std-coroutine.h" using std::experimental::suspend_always; diff --git a/test/SemaCXX/coroutine-uninitialized-warning-crash.cpp b/test/SemaCXX/coroutine-uninitialized-warning-crash.cpp new file mode 100644 index 000000000000..5bdb232d5307 --- /dev/null +++ b/test/SemaCXX/coroutine-uninitialized-warning-crash.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wall -Wextra -Wuninitialized -fblocks +#include "Inputs/std-coroutine.h" + +using namespace std::experimental; + + +struct A { + bool await_ready() { return true; } + int await_resume() { return 42; } + template + void await_suspend(F) {} +}; + + +struct coro_t { + struct promise_type { + coro_t get_return_object() { return {}; } + suspend_never initial_suspend() { return {}; } + suspend_never final_suspend() { return {}; } + A yield_value(int) { return {}; } + void return_void() {} + static void unhandled_exception() {} + }; +}; + +coro_t f(int n) { + if (n == 0) + co_return; + co_yield 42; + int x = co_await A{}; +} + +template +coro_t g(int n) { + if (n == 0) + co_return; + co_yield 42; + int x = co_await Await{}; +} + +int main() { + f(0); + g(0); +} diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp index 47ad86e5b02f..a867cf68a6e1 100644 --- a/test/SemaCXX/coroutines.cpp +++ b/test/SemaCXX/coroutines.cpp @@ -840,12 +840,12 @@ coro no_return_value_or_return_void() { struct bad_await_suspend_return { bool await_ready(); - // expected-error@+1 {{the return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}} + // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}} char await_suspend(std::experimental::coroutine_handle<>); void await_resume(); }; struct bad_await_ready_return { - // expected-note@+1 {{the return type of 'await_ready' is required to be contextually convertible to 'bool'}} + // expected-note@+1 {{return type of 'await_ready' is required to be contextually convertible to 'bool'}} void await_ready(); bool await_suspend(std::experimental::coroutine_handle<>); void await_resume(); @@ -858,6 +858,14 @@ struct await_ready_explicit_bool { void await_suspend(std::experimental::coroutine_handle<>); void await_resume(); }; +template +struct await_suspend_type_test { + bool await_ready(); + // expected-error@+2 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &')}} + // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &&')}} + SuspendTy await_suspend(std::experimental::coroutine_handle<>); + void await_resume(); +}; void test_bad_suspend() { { // FIXME: The actual error emitted here is terrible, and no number of notes can save it. @@ -873,4 +881,14 @@ void test_bad_suspend() { await_ready_explicit_bool c; co_await c; // OK } + { + await_suspend_type_test a; + await_suspend_type_test b; + await_suspend_type_test c; + await_suspend_type_test d; + co_await a; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}} + co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}} + co_await c; // OK + co_await d; // OK + } } diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 919122576222..8a994f01ba1a 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -252,6 +252,11 @@ void is_pod() { int arr[F(__is_pod(void))]; } { int arr[F(__is_pod(cvoid))]; } // { int arr[F(__is_pod(NonPODUnion))]; } + + { int arr[T(__is_pod(ACompleteType))]; } + { int arr[F(__is_pod(AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_pod(AnIncompleteType[]))]; } // expected-error {{incomplete type}} + { int arr[F(__is_pod(AnIncompleteType[1]))]; } // expected-error {{incomplete type}} } typedef Empty EmptyAr[10]; @@ -287,6 +292,11 @@ void is_empty() { int arr[F(__is_empty(IntArNB))]; } { int arr[F(__is_empty(HasAnonymousUnion))]; } // { int arr[F(__is_empty(DerivesVirt))]; } + + { int arr[T(__is_empty(ACompleteType))]; } + { int arr[F(__is_empty(AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_empty(AnIncompleteType[]))]; } + { int arr[F(__is_empty(AnIncompleteType[1]))]; } } typedef Derives ClassType; @@ -511,6 +521,8 @@ void is_aggregate() constexpr bool TrueAfterCpp14 = __cplusplus > 201402L; __is_aggregate(AnIncompleteType); // expected-error {{incomplete type}} + __is_aggregate(AnIncompleteType[]); // expected-error {{incomplete type}} + __is_aggregate(AnIncompleteType[1]); // expected-error {{incomplete type}} __is_aggregate(AnIncompleteTypeAr); // expected-error {{incomplete type}} __is_aggregate(AnIncompleteTypeArNB); // expected-error {{incomplete type}} __is_aggregate(AnIncompleteTypeArMB); // expected-error {{incomplete type}} @@ -1220,6 +1232,13 @@ void is_trivial2() int t32[F(__is_trivial(SuperNonTrivialStruct))]; int t33[F(__is_trivial(NonTCStruct))]; int t34[F(__is_trivial(ExtDefaulted))]; + + int t40[T(__is_trivial(ACompleteType))]; + int t41[F(__is_trivial(AnIncompleteType))]; // expected-error {{incomplete type}} + int t42[F(__is_trivial(AnIncompleteType[]))]; // expected-error {{incomplete type}} + int t43[F(__is_trivial(AnIncompleteType[1]))]; // expected-error {{incomplete type}} + int t44[F(__is_trivial(void))]; + int t45[F(__is_trivial(const volatile void))]; } void is_trivially_copyable2() @@ -1257,6 +1276,13 @@ void is_trivially_copyable2() int t34[T(__is_trivially_copyable(const int))]; int t35[T(__is_trivially_copyable(volatile int))]; + + int t40[T(__is_trivially_copyable(ACompleteType))]; + int t41[F(__is_trivially_copyable(AnIncompleteType))]; // expected-error {{incomplete type}} + int t42[F(__is_trivially_copyable(AnIncompleteType[]))]; // expected-error {{incomplete type}} + int t43[F(__is_trivially_copyable(AnIncompleteType[1]))]; // expected-error {{incomplete type}} + int t44[F(__is_trivially_copyable(void))]; + int t45[F(__is_trivially_copyable(const volatile void))]; } struct CStruct { @@ -1320,6 +1346,13 @@ void is_standard_layout() int t15[F(__is_standard_layout(CppStructNonStandardByBaseAr))]; int t16[F(__is_standard_layout(CppStructNonStandardBySameBase))]; int t17[F(__is_standard_layout(CppStructNonStandardBy2ndVirtBase))]; + + int t40[T(__is_standard_layout(ACompleteType))]; + int t41[F(__is_standard_layout(AnIncompleteType))]; // expected-error {{incomplete type}} + int t42[F(__is_standard_layout(AnIncompleteType[]))]; // expected-error {{incomplete type}} + int t43[F(__is_standard_layout(AnIncompleteType[1]))]; // expected-error {{incomplete type}} + int t44[F(__is_standard_layout(void))]; + int t45[F(__is_standard_layout(const volatile void))]; } void is_signed() @@ -2133,6 +2166,13 @@ void trivial_checks() TrivialMoveButNotCopy)))]; } { int arr[T((__is_assignable(TrivialMoveButNotCopy &, TrivialMoveButNotCopy &&)))]; } + + { int arr[T(__is_assignable(ACompleteType, ACompleteType))]; } + { int arr[F(__is_assignable(AnIncompleteType, AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_assignable(AnIncompleteType[], AnIncompleteType[]))]; } + { int arr[F(__is_assignable(AnIncompleteType[1], AnIncompleteType[1]))]; } // expected-error {{incomplete type}} + { int arr[F(__is_assignable(void, void))]; } + { int arr[F(__is_assignable(const volatile void, const volatile void))]; } } void constructible_checks() { @@ -2164,6 +2204,19 @@ void constructible_checks() { // PR25513 { int arr[F(__is_constructible(int(int)))]; } + + { int arr[T(__is_constructible(ACompleteType))]; } + { int arr[T(__is_nothrow_constructible(ACompleteType))]; } + { int arr[F(__is_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_nothrow_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_constructible(AnIncompleteType[]))]; } + { int arr[F(__is_nothrow_constructible(AnIncompleteType[]))]; } + { int arr[F(__is_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}} + { int arr[F(__is_nothrow_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}} + { int arr[F(__is_constructible(void))]; } + { int arr[F(__is_nothrow_constructible(void))]; } + { int arr[F(__is_constructible(const volatile void))]; } + { int arr[F(__is_nothrow_constructible(const volatile void))]; } } // Instantiation of __is_trivially_constructible @@ -2192,6 +2245,13 @@ void is_trivially_constructible_test() { { int arr[F((is_trivially_constructible::value))]; } { int arr[F((is_trivially_constructible::value))]; } { int arr[F((is_trivially_constructible::value))]; } // PR19178 + + { int arr[T(__is_trivially_constructible(ACompleteType))]; } + { int arr[F(__is_trivially_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_trivially_constructible(AnIncompleteType[]))]; } + { int arr[F(__is_trivially_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}} + { int arr[F(__is_trivially_constructible(void))]; } + { int arr[F(__is_trivially_constructible(const volatile void))]; } } void array_rank() { @@ -2218,6 +2278,13 @@ void is_destructible_test() { { int arr[F(__is_destructible(AllDeleted))]; } { int arr[T(__is_destructible(ThrowingDtor))]; } { int arr[T(__is_destructible(NoThrowDtor))]; } + + { int arr[T(__is_destructible(ACompleteType))]; } + { int arr[F(__is_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_destructible(AnIncompleteType[]))]; } + { int arr[F(__is_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}} + { int arr[F(__is_destructible(void))]; } + { int arr[F(__is_destructible(const volatile void))]; } } void is_nothrow_destructible_test() { @@ -2234,4 +2301,33 @@ void is_nothrow_destructible_test() { { int arr[F(__is_nothrow_destructible(ThrowingDtor))]; } { int arr[T(__is_nothrow_destructible(NoExceptDtor))]; } { int arr[T(__is_nothrow_destructible(NoThrowDtor))]; } + + { int arr[T(__is_nothrow_destructible(ACompleteType))]; } + { int arr[F(__is_nothrow_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_nothrow_destructible(AnIncompleteType[]))]; } + { int arr[F(__is_nothrow_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}} + { int arr[F(__is_nothrow_destructible(void))]; } + { int arr[F(__is_nothrow_destructible(const volatile void))]; } +} + +void is_trivially_destructible_test() { + { int arr[T(__is_trivially_destructible(int))]; } + { int arr[T(__is_trivially_destructible(int[2]))]; } + { int arr[F(__is_trivially_destructible(int[]))]; } + { int arr[F(__is_trivially_destructible(void))]; } + { int arr[T(__is_trivially_destructible(int &))]; } + { int arr[F(__is_trivially_destructible(HasDest))]; } + { int arr[F(__is_trivially_destructible(AllPrivate))]; } + { int arr[F(__is_trivially_destructible(SuperNonTrivialStruct))]; } + { int arr[T(__is_trivially_destructible(AllDefaulted))]; } + { int arr[F(__is_trivially_destructible(AllDeleted))]; } + { int arr[F(__is_trivially_destructible(ThrowingDtor))]; } + { int arr[F(__is_trivially_destructible(NoThrowDtor))]; } + + { int arr[T(__is_trivially_destructible(ACompleteType))]; } + { int arr[F(__is_trivially_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}} + { int arr[F(__is_trivially_destructible(AnIncompleteType[]))]; } + { int arr[F(__is_trivially_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}} + { int arr[F(__is_trivially_destructible(void))]; } + { int arr[F(__is_trivially_destructible(const volatile void))]; } } diff --git a/test/SemaObjC/attr-deprecated.m b/test/SemaObjC/attr-deprecated.m index b0613851ddaa..28031997af7a 100644 --- a/test/SemaObjC/attr-deprecated.m +++ b/test/SemaObjC/attr-deprecated.m @@ -83,7 +83,7 @@ int t5() { } -__attribute ((deprecated)) // expected-note 2 {{'DEPRECATED' has been explicitly marked deprecated here}} +__attribute ((deprecated)) // expected-note {{'DEPRECATED' has been explicitly marked deprecated here}} @interface DEPRECATED { @public int ivar; DEPRECATED *ivar2; // no warning. @@ -98,9 +98,17 @@ __attribute ((deprecated)) // expected-note 2 {{'DEPRECATED' has been explicitly @end @interface DEPRECATED (Category2) // no warning. +- (id)meth; @end -@implementation DEPRECATED (Category2) // expected-warning {{'DEPRECATED' is deprecated}} +__attribute__((deprecated)) +void depr_function(); + +@implementation DEPRECATED (Category2) // no warning +- (id)meth { + depr_function(); // no warning. + return 0; +} @end @interface NS : DEPRECATED // expected-warning {{'DEPRECATED' is deprecated}} diff --git a/test/SemaObjC/class-unavail-warning.m b/test/SemaObjC/class-unavail-warning.m index 268d51910b0c..f7d8f569ca67 100644 --- a/test/SemaObjC/class-unavail-warning.m +++ b/test/SemaObjC/class-unavail-warning.m @@ -2,7 +2,7 @@ // rdar://9092208 __attribute__((unavailable("not available"))) -@interface MyClass { // expected-note 8 {{'MyClass' has been explicitly marked unavailable here}} +@interface MyClass { // expected-note 7 {{'MyClass' has been explicitly marked unavailable here}} @public void *_test; MyClass *ivar; // no error. @@ -28,7 +28,7 @@ __attribute__((unavailable("not available"))) @interface MyClass (Cat2) // no error. @end -@implementation MyClass (Cat2) // expected-error {{unavailable}} +@implementation MyClass (Cat2) // no error. @end int main() { diff --git a/test/SemaObjC/warn-deprecated-implementations.m b/test/SemaObjC/warn-deprecated-implementations.m index 0c341165b0f0..df2557b9cd52 100644 --- a/test/SemaObjC/warn-deprecated-implementations.m +++ b/test/SemaObjC/warn-deprecated-implementations.m @@ -28,15 +28,14 @@ - (void) G {} // No warning, implementing its own deprecated method @end -__attribute__((deprecated)) // expected-note 2 {{'CL' has been explicitly marked deprecated here}} +__attribute__((deprecated)) // expected-note {{'CL' has been explicitly marked deprecated here}} @interface CL // expected-note 2 {{class declared here}} @end @implementation CL // expected-warning {{Implementing deprecated class}} @end -@implementation CL ( SomeCategory ) // expected-warning {{'CL' is deprecated}} \ - // expected-warning {{Implementing deprecated category}} +@implementation CL (SomeCategory) // expected-warning {{Implementing deprecated category}} @end @interface CL_SUB : CL // expected-warning {{'CL' is deprecated}} diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index d8f887f9c788..92a113111b6a 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -474,9 +474,8 @@ TEST_F(FormatTestJS, FormatsFreestandingFunctions) { "(function f() {\n" " var x = 1;\n" "}());\n"); - // Known issue: this should wrap after {}, but calculateBraceTypes - // misclassifies the first braces as a BK_BracedInit. - verifyFormat("function aFunction(){} {\n" + verifyFormat("function aFunction() {}\n" + "{\n" " let x = 1;\n" " console.log(x);\n" "}\n"); @@ -1233,6 +1232,10 @@ TEST_F(FormatTestJS, ClassDeclarations) { verifyFormat("class C {\n x: string = 12;\n}"); verifyFormat("class C {\n x(): string => 12;\n}"); verifyFormat("class C {\n ['x' + 2]: string = 12;\n}"); + verifyFormat("class C {\n" + " foo() {}\n" + " [bar]() {}\n" + "}\n"); verifyFormat("class C {\n private x: string = 12;\n}"); verifyFormat("class C {\n private static x: string = 12;\n}"); verifyFormat("class C {\n static x(): string {\n return 'asd';\n }\n}"); diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index edd3e38471be..b6d2988964b4 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -718,9 +718,9 @@ namespace { }; // Unique the enums, but maintain the original declaration ordering. - std::vector - uniqueEnumsInOrder(const std::vector &enums) { - std::vector uniques; + std::vector + uniqueEnumsInOrder(const std::vector &enums) { + std::vector uniques; SmallDenseSet unique_set; for (const auto &i : enums) { if (unique_set.insert(i).second) @@ -731,7 +731,8 @@ namespace { class EnumArgument : public Argument { std::string type; - std::vector values, enums, uniques; + std::vector values, enums, uniques; + public: EnumArgument(const Record &Arg, StringRef Attr) : Argument(Arg, Attr), type(Arg.getValueAsString("Type")), @@ -850,7 +851,7 @@ namespace { class VariadicEnumArgument: public VariadicArgument { std::string type, QualifiedTypeName; - std::vector values, enums, uniques; + std::vector values, enums, uniques; protected: void writeValueImpl(raw_ostream &OS) const override { @@ -1591,8 +1592,9 @@ struct AttributeSubjectMatchRule { } std::string getEnumValueName() const { - std::string Result = - "SubjectMatchRule_" + MetaSubject->getValueAsString("Name"); + SmallString<128> Result; + Result += "SubjectMatchRule_"; + Result += MetaSubject->getValueAsString("Name"); if (isSubRule()) { Result += "_"; if (isNegatedSubRule()) @@ -1601,7 +1603,7 @@ struct AttributeSubjectMatchRule { } if (isAbstractRule()) Result += "_abstract"; - return Result; + return Result.str(); } std::string getEnumValue() const { return "attr::" + getEnumValueName(); } @@ -2603,7 +2605,7 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { // append a unique suffix to distinguish this set of target checks from other // TargetSpecificAttr records. static void GenerateTargetSpecificAttrChecks(const Record *R, - std::vector &Arches, + std::vector &Arches, std::string &Test, std::string *FnName) { // It is assumed that there will be an llvm::Triple object @@ -2613,8 +2615,9 @@ static void GenerateTargetSpecificAttrChecks(const Record *R, Test += "("; for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) { - std::string Part = *I; - Test += "T.getArch() == llvm::Triple::" + Part; + StringRef Part = *I; + Test += "T.getArch() == llvm::Triple::"; + Test += Part; if (I + 1 != E) Test += " || "; if (FnName) @@ -2627,11 +2630,12 @@ static void GenerateTargetSpecificAttrChecks(const Record *R, // We know that there was at least one arch test, so we need to and in the // OS tests. Test += " && ("; - std::vector OSes = R->getValueAsListOfStrings("OSes"); + std::vector OSes = R->getValueAsListOfStrings("OSes"); for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) { - std::string Part = *I; + StringRef Part = *I; - Test += "T.getOS() == llvm::Triple::" + Part; + Test += "T.getOS() == llvm::Triple::"; + Test += Part; if (I + 1 != E) Test += " || "; if (FnName) @@ -2643,10 +2647,11 @@ static void GenerateTargetSpecificAttrChecks(const Record *R, // If one or more CXX ABIs are specified, check those as well. if (!R->isValueUnset("CXXABIs")) { Test += " && ("; - std::vector CXXABIs = R->getValueAsListOfStrings("CXXABIs"); + std::vector CXXABIs = R->getValueAsListOfStrings("CXXABIs"); for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) { - std::string Part = *I; - Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part; + StringRef Part = *I; + Test += "Target.getCXXABI().getKind() == TargetCXXABI::"; + Test += Part; if (I + 1 != E) Test += " || "; if (FnName) @@ -2684,7 +2689,7 @@ static void GenerateHasAttrSpellingStringSwitch( std::string Test; if (Attr->isSubClassOf("TargetSpecificAttr")) { const Record *R = Attr->getValueAsDef("Target"); - std::vector Arches = R->getValueAsListOfStrings("Arches"); + std::vector Arches = R->getValueAsListOfStrings("Arches"); GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr); // If this is the C++11 variety, also add in the LangOpts test. @@ -3323,7 +3328,7 @@ static std::string GenerateTargetRequirements(const Record &Attr, // Get the list of architectures to be tested for. const Record *R = Attr.getValueAsDef("Target"); - std::vector Arches = R->getValueAsListOfStrings("Arches"); + std::vector Arches = R->getValueAsListOfStrings("Arches"); if (Arches.empty()) { PrintError(Attr.getLoc(), "Empty list of target architectures for a " "target-specific attr"); @@ -3340,9 +3345,10 @@ static std::string GenerateTargetRequirements(const Record &Attr, std::string APK = Attr.getValueAsString("ParseKind"); for (const auto &I : Dupes) { if (I.first == APK) { - std::vector DA = I.second->getValueAsDef("Target") - ->getValueAsListOfStrings("Arches"); - std::move(DA.begin(), DA.end(), std::back_inserter(Arches)); + std::vector DA = + I.second->getValueAsDef("Target")->getValueAsListOfStrings( + "Arches"); + Arches.insert(Arches.end(), DA.begin(), DA.end()); } } } diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp index cad08afd846f..d9d99e0bb002 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -1277,8 +1277,8 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) { bool IsSynonym = GroupInfo.DiagsInGroup.empty() && GroupInfo.SubGroups.size() == 1; - writeHeader((IsRemarkGroup ? "-R" : "-W") + - G->getValueAsString("GroupName"), + writeHeader(((IsRemarkGroup ? "-R" : "-W") + + G->getValueAsString("GroupName")).str(), OS); if (!IsSynonym) { diff --git a/utils/TableGen/ClangOptionDocEmitter.cpp b/utils/TableGen/ClangOptionDocEmitter.cpp index aa7502e2c850..59314510e0ad 100644 --- a/utils/TableGen/ClangOptionDocEmitter.cpp +++ b/utils/TableGen/ClangOptionDocEmitter.cpp @@ -83,7 +83,7 @@ Documentation extractDocumentation(RecordKeeper &Records) { } // Pretend no-X and Xno-Y options are aliases of X and XY. - auto Name = R->getValueAsString("Name"); + std::string Name = R->getValueAsString("Name"); if (Name.size() >= 4) { if (Name.substr(0, 3) == "no-" && OptionsByName[Name.substr(3)]) { Aliases[OptionsByName[Name.substr(3)]].push_back(R); @@ -229,7 +229,7 @@ std::string getRSTStringWithTextFallback(const Record *R, StringRef Primary, } void emitOptionWithArgs(StringRef Prefix, const Record *Option, - ArrayRef Args, raw_ostream &OS) { + ArrayRef Args, raw_ostream &OS) { OS << Prefix << escapeRST(Option->getValueAsString("Name")); std::pair Separators = @@ -261,14 +261,15 @@ void emitOptionName(StringRef Prefix, const Record *Option, raw_ostream &OS) { } } - emitOptionWithArgs(Prefix, Option, Args, OS); + emitOptionWithArgs(Prefix, Option, std::vector(Args.begin(), Args.end()), OS); auto AliasArgs = Option->getValueAsListOfStrings("AliasArgs"); if (!AliasArgs.empty()) { Record *Alias = Option->getValueAsDef("Alias"); OS << " (equivalent to "; - emitOptionWithArgs(Alias->getValueAsListOfStrings("Prefixes").front(), - Alias, Option->getValueAsListOfStrings("AliasArgs"), OS); + emitOptionWithArgs( + Alias->getValueAsListOfStrings("Prefixes").front(), Alias, + AliasArgs, OS); OS << ")"; } } @@ -310,7 +311,7 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo, forEachOptionName(Option, DocInfo, [&](const Record *Option) { for (auto &Prefix : Option->getValueAsListOfStrings("Prefixes")) SphinxOptionIDs.push_back( - getSphinxOptionID(Prefix + Option->getValueAsString("Name"))); + getSphinxOptionID((Prefix + Option->getValueAsString("Name")).str())); }); assert(!SphinxOptionIDs.empty() && "no flags for option"); static std::map NextSuffix; diff --git a/utils/TableGen/ClangSACheckersEmitter.cpp b/utils/TableGen/ClangSACheckersEmitter.cpp index 115527ae3303..8f3de0b67d77 100644 --- a/utils/TableGen/ClangSACheckersEmitter.cpp +++ b/utils/TableGen/ClangSACheckersEmitter.cpp @@ -51,7 +51,8 @@ static std::string getParentPackageFullName(const Record *R) { static std::string getPackageFullName(const Record *R) { std::string name = getParentPackageFullName(R); if (!name.empty()) name += "."; - return name + R->getValueAsString("PackageName"); + name += R->getValueAsString("PackageName"); + return name; } static std::string getCheckerFullName(const Record *R) { From 06eabdc027f984611832945782f7c36800d0d397 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Thu, 1 Jun 2017 20:58:59 +0000 Subject: [PATCH 07/22] Vendor import of compiler-rt trunk r304460: https://llvm.org/svn/llvm-project/compiler-rt/trunk@304460 --- include/sanitizer/coverage_interface.h | 3 - lib/asan/asan_allocator.cc | 4 +- lib/asan/asan_allocator.h | 2 + lib/asan/asan_flags.cc | 4 + lib/asan/asan_interceptors.cc | 17 +++ lib/asan/tests/asan_str_test.cc | 27 ++++ lib/dfsan/done_abilist.txt | 2 - lib/lsan/lsan_interceptors.cc | 24 ++++ lib/msan/msan_allocator.cc | 96 +------------- lib/msan/msan_allocator.h | 97 ++++++++++++++ lib/msan/msan_interceptors.cc | 38 ++---- lib/msan/tests/msan_test.cc | 13 +- .../sanitizer_common_interceptors.inc | 42 +++++++ .../sanitizer_coverage_interface.inc | 5 - .../sanitizer_coverage_libcdep.cc | 47 +------ .../sanitizer_coverage_libcdep_new.cc | 4 +- lib/sanitizer_common/sanitizer_flags.inc | 3 + .../sanitizer_platform_interceptors.h | 14 +++ lib/sanitizer_common/scripts/sancov.py | 2 +- .../symbolizer/scripts/global_symbols.txt | 1 + .../tests/sanitizer_test_utils.h | 6 + lib/ubsan/ubsan_type_hash_itanium.cc | 2 +- test/asan/TestCases/Linux/coverage-missing.cc | 6 +- test/asan/TestCases/Posix/coverage-fork.cc | 10 +- .../Posix/coverage-module-unloaded.cc | 20 ++- .../TestCases/Posix/coverage-sandboxing.cc | 87 ------------- test/asan/TestCases/Posix/coverage.cc | 19 ++- test/asan/TestCases/Posix/strndup_oob_test.cc | 27 ++++ .../asan/TestCases/Posix/strndup_oob_test2.cc | 22 ++++ test/asan/TestCases/coverage-and-lsan.cc | 4 +- test/asan/TestCases/coverage-order-pcs.cc | 57 --------- test/msan/strndup.cc | 28 +++++ .../TestCases/Linux/allocator_fork_no_hang.cc | 118 ++++++++++++++++++ .../TestCases/sanitizer_coverage_symbolize.cc | 2 +- .../sanitizer_coverage_trace_pc_guard-dso.cc | 6 +- .../sanitizer_coverage_trace_pc_guard.cc | 2 +- test/ubsan/TestCases/TypeCheck/PR33221.cpp | 28 +++++ 37 files changed, 525 insertions(+), 364 deletions(-) delete mode 100644 test/asan/TestCases/Posix/coverage-sandboxing.cc create mode 100644 test/asan/TestCases/Posix/strndup_oob_test.cc create mode 100644 test/asan/TestCases/Posix/strndup_oob_test2.cc delete mode 100644 test/asan/TestCases/coverage-order-pcs.cc create mode 100644 test/msan/strndup.cc create mode 100644 test/sanitizer_common/TestCases/Linux/allocator_fork_no_hang.cc create mode 100644 test/ubsan/TestCases/TypeCheck/PR33221.cpp diff --git a/include/sanitizer/coverage_interface.h b/include/sanitizer/coverage_interface.h index 911a3e854b77..bdb113728b95 100644 --- a/include/sanitizer/coverage_interface.h +++ b/include/sanitizer/coverage_interface.h @@ -32,9 +32,6 @@ extern "C" { // descriptor. Returns -1 on failure, or if coverage dumping is disabled. // This is intended for use by sandboxing code. intptr_t __sanitizer_maybe_open_cov_file(const char *name); - // Get the number of unique covered blocks (or edges). - // This can be useful for coverage-directed in-process fuzzers. - uintptr_t __sanitizer_get_total_unique_coverage(); #ifdef __cplusplus } // extern "C" #endif diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc index 7010b6023614..db5a683e283d 100644 --- a/lib/asan/asan_allocator.cc +++ b/lib/asan/asan_allocator.cc @@ -47,8 +47,6 @@ static u32 RZSize2Log(u32 rz_size) { return res; } -static AsanAllocator &get_allocator(); - // The memory chunk allocated from the underlying allocator looks like this: // L L L L L L H H U U U U U U R R // L -- left redzone words (0 or more bytes) @@ -719,7 +717,7 @@ struct Allocator { static Allocator instance(LINKER_INITIALIZED); -static AsanAllocator &get_allocator() { +AsanAllocator &get_allocator() { return instance.allocator; } diff --git a/lib/asan/asan_allocator.h b/lib/asan/asan_allocator.h index ad1aeb58a86b..ce3e25dc5094 100644 --- a/lib/asan/asan_allocator.h +++ b/lib/asan/asan_allocator.h @@ -213,5 +213,7 @@ void asan_mz_force_unlock(); void PrintInternalAllocatorStats(); void AsanSoftRssLimitExceededCallback(bool exceeded); +AsanAllocator &get_allocator(); + } // namespace __asan #endif // ASAN_ALLOCATOR_H diff --git a/lib/asan/asan_flags.cc b/lib/asan/asan_flags.cc index c8ae3faed7c2..6be0d6e94b9a 100644 --- a/lib/asan/asan_flags.cc +++ b/lib/asan/asan_flags.cc @@ -194,6 +194,10 @@ void InitializeFlags() { Report("WARNING: strchr* interceptors are enabled even though " "replace_str=0. Use intercept_strchr=0 to disable them."); } + if (!f->replace_str && common_flags()->intercept_strndup) { + Report("WARNING: strndup* interceptors are enabled even though " + "replace_str=0. Use intercept_strndup=0 to disable them."); + } } } // namespace __asan diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index cb2214f966ea..e82a5a4a7e96 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -22,6 +22,7 @@ #include "asan_stats.h" #include "asan_suppressions.h" #include "lsan/lsan_common.h" +#include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_libc.h" #if SANITIZER_POSIX @@ -705,11 +706,27 @@ INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, #endif // ASAN_INTERCEPT___CXA_ATEXIT #if ASAN_INTERCEPT_FORK +static void BeforeFork() { + if (SANITIZER_LINUX) { + get_allocator().ForceLock(); + StackDepotLockAll(); + } +} + +static void AfterFork() { + if (SANITIZER_LINUX) { + StackDepotUnlockAll(); + get_allocator().ForceUnlock(); + } +} + INTERCEPTOR(int, fork, void) { ENSURE_ASAN_INITED(); + BeforeFork(); if (common_flags()->coverage) CovBeforeFork(); int pid = REAL(fork)(); if (common_flags()->coverage) CovAfterFork(pid); + AfterFork(); return pid; } #endif // ASAN_INTERCEPT_FORK diff --git a/lib/asan/tests/asan_str_test.cc b/lib/asan/tests/asan_str_test.cc index c790088f8f9e..964f6da0297d 100644 --- a/lib/asan/tests/asan_str_test.cc +++ b/lib/asan/tests/asan_str_test.cc @@ -154,6 +154,33 @@ TEST(AddressSanitizer, MAYBE_StrDupOOBTest) { free(str); } +#if SANITIZER_TEST_HAS_STRNDUP +TEST(AddressSanitizer, MAYBE_StrNDupOOBTest) { + size_t size = Ident(42); + char *str = MallocAndMemsetString(size); + char *new_str; + // Normal strndup calls. + str[size - 1] = '\0'; + new_str = strndup(str, size - 13); + free(new_str); + new_str = strndup(str + size - 1, 13); + free(new_str); + // Argument points to not allocated memory. + EXPECT_DEATH(Ident(strndup(str - 1, 13)), LeftOOBReadMessage(1)); + EXPECT_DEATH(Ident(strndup(str + size, 13)), RightOOBReadMessage(0)); + // Overwrite the terminating '\0' and hit unallocated memory. + str[size - 1] = 'z'; + EXPECT_DEATH(Ident(strndup(str, size + 13)), RightOOBReadMessage(0)); + // Check handling of non 0 terminated strings. + Ident(new_str = strndup(str + size - 1, 0)); + free(new_str); + Ident(new_str = strndup(str + size - 1, 1)); + free(new_str); + EXPECT_DEATH(Ident(strndup(str + size - 1, 2)), RightOOBReadMessage(0)); + free(str); +} +#endif // SANITIZER_TEST_HAS_STRNDUP + TEST(AddressSanitizer, StrCpyOOBTest) { size_t to_size = Ident(30); size_t from_size = Ident(6); // less than to_size diff --git a/lib/dfsan/done_abilist.txt b/lib/dfsan/done_abilist.txt index cbbedbc33601..a560cd7b477c 100644 --- a/lib/dfsan/done_abilist.txt +++ b/lib/dfsan/done_abilist.txt @@ -287,8 +287,6 @@ fun:__sanitizer_cov_with_check=uninstrumented fun:__sanitizer_cov_with_check=discard fun:__sanitizer_set_death_callback=uninstrumented fun:__sanitizer_set_death_callback=discard -fun:__sanitizer_get_total_unique_coverage=uninstrumented -fun:__sanitizer_get_total_unique_coverage=discard fun:__sanitizer_update_counter_bitset_and_clear_counters=uninstrumented fun:__sanitizer_update_counter_bitset_and_clear_counters=discard diff --git a/lib/lsan/lsan_interceptors.cc b/lib/lsan/lsan_interceptors.cc index 9e39a7d1944d..a0a59daa07ae 100644 --- a/lib/lsan/lsan_interceptors.cc +++ b/lib/lsan/lsan_interceptors.cc @@ -22,6 +22,7 @@ #include "sanitizer_common/sanitizer_platform_interceptors.h" #include "sanitizer_common/sanitizer_platform_limits_posix.h" #include "sanitizer_common/sanitizer_posix.h" +#include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" #include "lsan.h" #include "lsan_allocator.h" @@ -97,6 +98,28 @@ INTERCEPTOR(void*, valloc, uptr size) { } #endif +static void BeforeFork() { + if (SANITIZER_LINUX) { + LockAllocator(); + StackDepotLockAll(); + } +} + +static void AfterFork() { + if (SANITIZER_LINUX) { + StackDepotUnlockAll(); + UnlockAllocator(); + } +} + +INTERCEPTOR(int, fork, void) { + ENSURE_LSAN_INITED; + BeforeFork(); + int pid = REAL(fork)(); + AfterFork(); + return pid; +} + #if SANITIZER_INTERCEPT_MEMALIGN INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { ENSURE_LSAN_INITED; @@ -336,6 +359,7 @@ void InitializeInterceptors() { LSAN_MAYBE_INTERCEPT_MALLOPT; INTERCEPT_FUNCTION(pthread_create); INTERCEPT_FUNCTION(pthread_join); + INTERCEPT_FUNCTION(fork); if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { Report("LeakSanitizer: failed to create thread key.\n"); diff --git a/lib/msan/msan_allocator.cc b/lib/msan/msan_allocator.cc index 1be573faa412..f76b01de0924 100644 --- a/lib/msan/msan_allocator.cc +++ b/lib/msan/msan_allocator.cc @@ -12,8 +12,6 @@ // MemorySanitizer allocator. //===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_allocator.h" -#include "sanitizer_common/sanitizer_allocator_interface.h" #include "msan.h" #include "msan_allocator.h" #include "msan_origin.h" @@ -22,102 +20,12 @@ namespace __msan { -struct Metadata { - uptr requested_size; -}; - -struct MsanMapUnmapCallback { - void OnMap(uptr p, uptr size) const {} - void OnUnmap(uptr p, uptr size) const { - __msan_unpoison((void *)p, size); - - // We are about to unmap a chunk of user memory. - // Mark the corresponding shadow memory as not needed. - uptr shadow_p = MEM_TO_SHADOW(p); - ReleaseMemoryPagesToOS(shadow_p, shadow_p + size); - if (__msan_get_track_origins()) { - uptr origin_p = MEM_TO_ORIGIN(p); - ReleaseMemoryPagesToOS(origin_p, origin_p + size); - } - } -}; - -#if defined(__mips64) - static const uptr kMaxAllowedMallocSize = 2UL << 30; - static const uptr kRegionSizeLog = 20; - static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; - typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; - - struct AP32 { - static const uptr kSpaceBeg = 0; - static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; - static const uptr kMetadataSize = sizeof(Metadata); - typedef __sanitizer::CompactSizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = __msan::kRegionSizeLog; - typedef __msan::ByteMap ByteMap; - typedef MsanMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - }; - typedef SizeClassAllocator32 PrimaryAllocator; -#elif defined(__x86_64__) -#if SANITIZER_LINUX && !defined(MSAN_LINUX_X86_64_OLD_MAPPING) - static const uptr kAllocatorSpace = 0x700000000000ULL; -#else - static const uptr kAllocatorSpace = 0x600000000000ULL; -#endif - static const uptr kMaxAllowedMallocSize = 8UL << 30; - - struct AP64 { // Allocator64 parameters. Deliberately using a short name. - static const uptr kSpaceBeg = kAllocatorSpace; - static const uptr kSpaceSize = 0x40000000000; // 4T. - static const uptr kMetadataSize = sizeof(Metadata); - typedef DefaultSizeClassMap SizeClassMap; - typedef MsanMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - }; - - typedef SizeClassAllocator64 PrimaryAllocator; - -#elif defined(__powerpc64__) - static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G - - struct AP64 { // Allocator64 parameters. Deliberately using a short name. - static const uptr kSpaceBeg = 0x300000000000; - static const uptr kSpaceSize = 0x020000000000; // 2T. - static const uptr kMetadataSize = sizeof(Metadata); - typedef DefaultSizeClassMap SizeClassMap; - typedef MsanMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - }; - - typedef SizeClassAllocator64 PrimaryAllocator; -#elif defined(__aarch64__) - static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G - static const uptr kRegionSizeLog = 20; - static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; - typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; - - struct AP32 { - static const uptr kSpaceBeg = 0; - static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; - static const uptr kMetadataSize = sizeof(Metadata); - typedef __sanitizer::CompactSizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = __msan::kRegionSizeLog; - typedef __msan::ByteMap ByteMap; - typedef MsanMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - }; - typedef SizeClassAllocator32 PrimaryAllocator; -#endif -typedef SizeClassAllocatorLocalCache AllocatorCache; -typedef LargeMmapAllocator SecondaryAllocator; -typedef CombinedAllocator Allocator; - static Allocator allocator; static AllocatorCache fallback_allocator_cache; static SpinMutex fallback_mutex; +Allocator &get_allocator() { return allocator; } + void MsanAllocatorInit() { allocator.Init( common_flags()->allocator_may_return_null, diff --git a/lib/msan/msan_allocator.h b/lib/msan/msan_allocator.h index 407942e54c1a..abd4ea678523 100644 --- a/lib/msan/msan_allocator.h +++ b/lib/msan/msan_allocator.h @@ -15,9 +15,106 @@ #define MSAN_ALLOCATOR_H #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_allocator.h" +#include "sanitizer_common/sanitizer_allocator_interface.h" namespace __msan { +struct Metadata { + uptr requested_size; +}; + +struct MsanMapUnmapCallback { + void OnMap(uptr p, uptr size) const {} + void OnUnmap(uptr p, uptr size) const { + __msan_unpoison((void *)p, size); + + // We are about to unmap a chunk of user memory. + // Mark the corresponding shadow memory as not needed. + uptr shadow_p = MEM_TO_SHADOW(p); + ReleaseMemoryPagesToOS(shadow_p, shadow_p + size); + if (__msan_get_track_origins()) { + uptr origin_p = MEM_TO_ORIGIN(p); + ReleaseMemoryPagesToOS(origin_p, origin_p + size); + } + } +}; + +#if defined(__mips64) + static const uptr kMaxAllowedMallocSize = 2UL << 30; + static const uptr kRegionSizeLog = 20; + static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; + typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; + + struct AP32 { + static const uptr kSpaceBeg = 0; + static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; + static const uptr kMetadataSize = sizeof(Metadata); + typedef __sanitizer::CompactSizeClassMap SizeClassMap; + static const uptr kRegionSizeLog = __msan::kRegionSizeLog; + typedef __msan::ByteMap ByteMap; + typedef MsanMapUnmapCallback MapUnmapCallback; + static const uptr kFlags = 0; + }; + typedef SizeClassAllocator32 PrimaryAllocator; +#elif defined(__x86_64__) +#if SANITIZER_LINUX && !defined(MSAN_LINUX_X86_64_OLD_MAPPING) + static const uptr kAllocatorSpace = 0x700000000000ULL; +#else + static const uptr kAllocatorSpace = 0x600000000000ULL; +#endif + static const uptr kMaxAllowedMallocSize = 8UL << 30; + + struct AP64 { // Allocator64 parameters. Deliberately using a short name. + static const uptr kSpaceBeg = kAllocatorSpace; + static const uptr kSpaceSize = 0x40000000000; // 4T. + static const uptr kMetadataSize = sizeof(Metadata); + typedef DefaultSizeClassMap SizeClassMap; + typedef MsanMapUnmapCallback MapUnmapCallback; + static const uptr kFlags = 0; + }; + + typedef SizeClassAllocator64 PrimaryAllocator; + +#elif defined(__powerpc64__) + static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G + + struct AP64 { // Allocator64 parameters. Deliberately using a short name. + static const uptr kSpaceBeg = 0x300000000000; + static const uptr kSpaceSize = 0x020000000000; // 2T. + static const uptr kMetadataSize = sizeof(Metadata); + typedef DefaultSizeClassMap SizeClassMap; + typedef MsanMapUnmapCallback MapUnmapCallback; + static const uptr kFlags = 0; + }; + + typedef SizeClassAllocator64 PrimaryAllocator; +#elif defined(__aarch64__) + static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G + static const uptr kRegionSizeLog = 20; + static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; + typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; + + struct AP32 { + static const uptr kSpaceBeg = 0; + static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; + static const uptr kMetadataSize = sizeof(Metadata); + typedef __sanitizer::CompactSizeClassMap SizeClassMap; + static const uptr kRegionSizeLog = __msan::kRegionSizeLog; + typedef __msan::ByteMap ByteMap; + typedef MsanMapUnmapCallback MapUnmapCallback; + static const uptr kFlags = 0; + }; + typedef SizeClassAllocator32 PrimaryAllocator; +#endif +typedef SizeClassAllocatorLocalCache AllocatorCache; +typedef LargeMmapAllocator SecondaryAllocator; +typedef CombinedAllocator Allocator; + + +Allocator &get_allocator(); + struct MsanThreadLocalMallocStorage { uptr quarantine_cache[16]; // Allocator cache contains atomic_uint64_t which must be 8-byte aligned. diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index 15543bd912d6..fbc2ea4fec9d 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -341,33 +341,6 @@ INTERCEPTOR(char *, __strdup, char *src) { #define MSAN_MAYBE_INTERCEPT___STRDUP #endif -INTERCEPTOR(char *, strndup, char *src, SIZE_T n) { - ENSURE_MSAN_INITED(); - GET_STORE_STACK_TRACE; - // On FreeBSD strndup() leverages strnlen(). - InterceptorScope interceptor_scope; - SIZE_T copy_size = REAL(strnlen)(src, n); - char *res = REAL(strndup)(src, n); - CopyShadowAndOrigin(res, src, copy_size, &stack); - __msan_unpoison(res + copy_size, 1); // \0 - return res; -} - -#if !SANITIZER_FREEBSD -INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) { - ENSURE_MSAN_INITED(); - GET_STORE_STACK_TRACE; - SIZE_T copy_size = REAL(strnlen)(src, n); - char *res = REAL(__strndup)(src, n); - CopyShadowAndOrigin(res, src, copy_size, &stack); - __msan_unpoison(res + copy_size, 1); // \0 - return res; -} -#define MSAN_MAYBE_INTERCEPT___STRNDUP INTERCEPT_FUNCTION(__strndup) -#else -#define MSAN_MAYBE_INTERCEPT___STRNDUP -#endif - INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) { ENSURE_MSAN_INITED(); char *res = REAL(gcvt)(number, ndigit, buf); @@ -1228,6 +1201,7 @@ INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) { } static void BeforeFork() { + get_allocator().ForceLock(); StackDepotLockAll(); ChainedOriginDepotLockAll(); } @@ -1235,6 +1209,7 @@ static void BeforeFork() { static void AfterFork() { ChainedOriginDepotUnlockAll(); StackDepotUnlockAll(); + get_allocator().ForceUnlock(); } INTERCEPTOR(int, fork, void) { @@ -1371,6 +1346,13 @@ int OnExit() { return __msan_memcpy(to, from, size); \ } +#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \ + do { \ + GET_STORE_STACK_TRACE; \ + CopyShadowAndOrigin(to, from, size, &stack); \ + __msan_unpoison(to + size, 1); \ + } while (false) + #include "sanitizer_common/sanitizer_platform_interceptors.h" #include "sanitizer_common/sanitizer_common_interceptors.inc" @@ -1538,8 +1520,6 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(stpcpy); // NOLINT INTERCEPT_FUNCTION(strdup); MSAN_MAYBE_INTERCEPT___STRDUP; - INTERCEPT_FUNCTION(strndup); - MSAN_MAYBE_INTERCEPT___STRNDUP; INTERCEPT_FUNCTION(strncpy); // NOLINT INTERCEPT_FUNCTION(gcvt); INTERCEPT_FUNCTION(strcat); // NOLINT diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc index c7c91324aa0b..543a7eb98bcc 100644 --- a/lib/msan/tests/msan_test.cc +++ b/lib/msan/tests/msan_test.cc @@ -1581,19 +1581,28 @@ TEST(MemorySanitizer, strdup) { TEST(MemorySanitizer, strndup) { char buf[4] = "abc"; __msan_poison(buf + 2, sizeof(*buf)); - char *x = strndup(buf, 3); + char *x; + EXPECT_UMR(x = strndup(buf, 3)); EXPECT_NOT_POISONED(x[0]); EXPECT_NOT_POISONED(x[1]); EXPECT_POISONED(x[2]); EXPECT_NOT_POISONED(x[3]); free(x); + // Check handling of non 0 terminated strings. + buf[3] = 'z'; + __msan_poison(buf + 3, sizeof(*buf)); + EXPECT_UMR(x = strndup(buf + 3, 1)); + EXPECT_POISONED(x[0]); + EXPECT_NOT_POISONED(x[1]); + free(x); } TEST(MemorySanitizer, strndup_short) { char buf[4] = "abc"; __msan_poison(buf + 1, sizeof(*buf)); __msan_poison(buf + 2, sizeof(*buf)); - char *x = strndup(buf, 2); + char *x; + EXPECT_UMR(x = strndup(buf, 2)); EXPECT_NOT_POISONED(x[0]); EXPECT_POISONED(x[1]); EXPECT_NOT_POISONED(x[2]); diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index 53204b48e300..c0c08a031e9b 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -34,6 +34,8 @@ // COMMON_INTERCEPTOR_MEMSET_IMPL // COMMON_INTERCEPTOR_MEMMOVE_IMPL // COMMON_INTERCEPTOR_MEMCPY_IMPL +// COMMON_INTERCEPTOR_COPY_STRING +// COMMON_INTERCEPTOR_STRNDUP_IMPL //===----------------------------------------------------------------------===// #include "interception/interception.h" @@ -217,6 +219,24 @@ bool PlatformHasDifferentMemcpyAndMemmove(); } #endif +#ifndef COMMON_INTERCEPTOR_COPY_STRING +#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {} +#endif + +#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL +#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \ + COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \ + uptr copy_length = internal_strnlen(s, size); \ + char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \ + if (common_flags()->intercept_strndup) { \ + COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \ + } \ + COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \ + internal_memcpy(new_mem, s, copy_length); \ + new_mem[copy_length] = '\0'; \ + return new_mem; +#endif + struct FileMetadata { // For open_memstream(). char **addr; @@ -300,6 +320,26 @@ INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) { #define INIT_STRNLEN #endif +#if SANITIZER_INTERCEPT_STRNDUP +INTERCEPTOR(char*, strndup, const char *s, uptr size) { + void *ctx; + COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size); +} +#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup) +#else +#define INIT_STRNDUP +#endif // SANITIZER_INTERCEPT_STRNDUP + +#if SANITIZER_INTERCEPT___STRNDUP +INTERCEPTOR(char*, __strndup, const char *s, uptr size) { + void *ctx; + COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size); +} +#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup) +#else +#define INIT___STRNDUP +#endif // SANITIZER_INTERCEPT___STRNDUP + #if SANITIZER_INTERCEPT_TEXTDOMAIN INTERCEPTOR(char*, textdomain, const char *domainname) { void *ctx; @@ -6163,6 +6203,8 @@ static void InitializeCommonInterceptors() { INIT_TEXTDOMAIN; INIT_STRLEN; INIT_STRNLEN; + INIT_STRNDUP; + INIT___STRNDUP; INIT_STRCMP; INIT_STRNCMP; INIT_STRCASECMP; diff --git a/lib/sanitizer_common/sanitizer_coverage_interface.inc b/lib/sanitizer_common/sanitizer_coverage_interface.inc index 42b4d3aba01b..70c10e04b653 100644 --- a/lib/sanitizer_common/sanitizer_coverage_interface.inc +++ b/lib/sanitizer_common/sanitizer_coverage_interface.inc @@ -8,14 +8,9 @@ //===----------------------------------------------------------------------===// // Sanitizer Coverage interface list. //===----------------------------------------------------------------------===// -INTERFACE_FUNCTION(__sanitizer_cov) INTERFACE_FUNCTION(__sanitizer_cov_dump) -INTERFACE_FUNCTION(__sanitizer_cov_init) -INTERFACE_FUNCTION(__sanitizer_cov_module_init) -INTERFACE_FUNCTION(__sanitizer_cov_with_check) INTERFACE_FUNCTION(__sanitizer_dump_coverage) INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage) -INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage) INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file) INTERFACE_WEAK_FUNCTION(__sancov_default_options) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp) diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index 754ece9840ef..abfdf3d02088 100644 --- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -155,13 +155,6 @@ void CoverageData::DirectOpen() { void CoverageData::Init() { pc_fd = kInvalidFd; - - if (!common_flags()->coverage) return; - Printf("**\n***\n***\n"); - Printf("**WARNING: this implementation of SanitizerCoverage is deprecated\n"); - Printf("**WARNING: and will be removed in future versions\n"); - Printf("**WARNING: See https://clang.llvm.org/docs/SanitizerCoverage.html\n"); - Printf("**\n***\n***\n"); } void CoverageData::Enable() { @@ -495,6 +488,12 @@ static void GenerateHtmlReport(const InternalMmapVector &cov_files) { void CoverageData::DumpOffsets() { auto sym = Symbolizer::GetOrInit(); if (!common_flags()->coverage_pcs) return; + Printf("**\n***\n***\n"); + Printf("**WARNING: this implementation of SanitizerCoverage is deprecated\n"); + Printf("**WARNING: and will be removed in future versions\n"); + Printf("**WARNING: See https://clang.llvm.org/docs/SanitizerCoverage.html\n"); + Printf("**\n***\n***\n"); + CHECK_NE(sym, nullptr); InternalMmapVector offsets(0); InternalScopedString path(kMaxPathLength); @@ -607,47 +606,13 @@ void CoverageUpdateMapping() { } // namespace __sanitizer extern "C" { -SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(u32 *guard) { - coverage_data.Add(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()), - guard); -} -SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_with_check(u32 *guard) { - atomic_uint32_t *atomic_guard = reinterpret_cast(guard); - if (static_cast( - __sanitizer::atomic_load(atomic_guard, memory_order_relaxed)) < 0) - coverage_data.Add(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()), - guard); -} -SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() { - coverage_enabled = true; - coverage_dir = common_flags()->coverage_dir; - coverage_data.Init(); -} SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { - coverage_data.DumpAll(); __sanitizer_dump_trace_pc_guard_coverage(); } -SANITIZER_INTERFACE_ATTRIBUTE void -__sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters, - const char *comp_unit_name) { - coverage_data.InitializeGuards(guards, npcs, comp_unit_name, GET_CALLER_PC()); - if (!common_flags()->coverage_direct) return; - if (SANITIZER_ANDROID && coverage_enabled) { - // dlopen/dlclose interceptors do not work on Android, so we rely on - // Extend() calls to update .sancov.map. - CovUpdateMapping(coverage_dir, GET_CALLER_PC()); - } - coverage_data.Extend(npcs); -} SANITIZER_INTERFACE_ATTRIBUTE sptr __sanitizer_maybe_open_cov_file(const char *name) { return (sptr)MaybeOpenCovFile(name); } -SANITIZER_INTERFACE_ATTRIBUTE -uptr __sanitizer_get_total_unique_coverage() { - return atomic_load(&coverage_counter, memory_order_relaxed); -} - // Default empty implementations (weak). Users should redefine them. SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {} diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc index 6d8e3e041cc0..a98dde76e22a 100644 --- a/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc +++ b/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc @@ -49,7 +49,7 @@ static void WriteModuleCoverage(char* file_path, const char* module_name, WriteToFile(fd, &Magic, sizeof(Magic)); WriteToFile(fd, pcs, len * sizeof(*pcs)); CloseFile(fd); - Printf("SanitizerCoverage: %s %zd PCs written\n", file_path, len); + Printf("SanitizerCoverage: %s: %zd PCs written\n", file_path, len); } static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) { @@ -71,7 +71,7 @@ static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) { if (!pc) continue; if (!__sanitizer_get_module_and_offset_for_pc(pc, nullptr, 0, &pcs[i])) { - Printf("ERROR: bad pc %x\n", pc); + Printf("ERROR: unknown pc 0x%x (may happen if dlclose is used)\n", pc); continue; } uptr module_base = pc - pcs[i]; diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index 12c126fa707c..f87d8b6433ac 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -197,6 +197,9 @@ COMMON_FLAG(bool, intercept_strpbrk, true, COMMON_FLAG(bool, intercept_strlen, true, "If set, uses custom wrappers for strlen and strnlen functions " "to find more errors.") +COMMON_FLAG(bool, intercept_strndup, true, + "If set, uses custom wrappers for strndup functions " + "to find more errors.") COMMON_FLAG(bool, intercept_strchr, true, "If set, uses custom wrappers for strchr, strchrnul, and strrchr " "functions to find more errors.") diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h index e5644ef25e83..a95497467d61 100644 --- a/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -25,6 +25,12 @@ # define SI_NOT_WINDOWS 0 #endif +#if SANITIZER_POSIX +# define SI_POSIX 1 +#else +# define SI_POSIX 0 +#endif + #if SANITIZER_LINUX && !SANITIZER_ANDROID # define SI_LINUX_NOT_ANDROID 1 #else @@ -69,6 +75,12 @@ # define SI_UNIX_NOT_MAC 0 #endif +#if SANITIZER_LINUX && !SANITIZER_FREEBSD +# define SI_LINUX_NOT_FREEBSD 1 +# else +# define SI_LINUX_NOT_FREEBSD 0 +#endif + #define SANITIZER_INTERCEPT_STRLEN 1 #define SANITIZER_INTERCEPT_STRNLEN SI_NOT_MAC #define SANITIZER_INTERCEPT_STRCMP 1 @@ -86,6 +98,8 @@ #define SANITIZER_INTERCEPT_MEMMOVE 1 #define SANITIZER_INTERCEPT_MEMCPY 1 #define SANITIZER_INTERCEPT_MEMCMP 1 +#define SANITIZER_INTERCEPT_STRNDUP SI_POSIX +#define SANITIZER_INTERCEPT___STRNDUP SI_LINUX_NOT_FREEBSD #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 # define SI_MAC_DEPLOYMENT_BELOW_10_7 1 diff --git a/lib/sanitizer_common/scripts/sancov.py b/lib/sanitizer_common/scripts/sancov.py index e2eba36a802f..35606396b78e 100755 --- a/lib/sanitizer_common/scripts/sancov.py +++ b/lib/sanitizer_common/scripts/sancov.py @@ -194,7 +194,7 @@ def GetInstrumentedPCs(binary): # - with call or callq, # - directly or via PLT. cmd = "objdump -d %s | " \ - "grep '^\s\+[0-9a-f]\+:.*\scall\(q\|\)\s\+[0-9a-f]\+ <__sanitizer_cov\(_with_check\|\)\(@plt\|\)>' | " \ + "grep '^\s\+[0-9a-f]\+:.*\scall\(q\|\)\s\+[0-9a-f]\+ <__sanitizer_cov\(_with_check\|\|_trace_pc_guard\)\(@plt\|\)>' | " \ "grep '^\s\+[0-9a-f]\+' -o" % binary proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) diff --git a/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt b/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt index 737f9459d240..a23c9534701d 100644 --- a/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt +++ b/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt @@ -59,6 +59,7 @@ getpagesize U getpid U gettimeofday U ioctl U +isalpha U isatty U isprint U isupper U diff --git a/lib/sanitizer_common/tests/sanitizer_test_utils.h b/lib/sanitizer_common/tests/sanitizer_test_utils.h index 9c162a66f547..b7728d9ea25e 100644 --- a/lib/sanitizer_common/tests/sanitizer_test_utils.h +++ b/lib/sanitizer_common/tests/sanitizer_test_utils.h @@ -124,4 +124,10 @@ static inline uint32_t my_rand() { # define SANITIZER_TEST_HAS_PRINTF_L 0 #endif +#if !defined(_MSC_VER) +# define SANITIZER_TEST_HAS_STRNDUP 1 +#else +# define SANITIZER_TEST_HAS_STRNDUP 0 +#endif + #endif // SANITIZER_TEST_UTILS_H diff --git a/lib/ubsan/ubsan_type_hash_itanium.cc b/lib/ubsan/ubsan_type_hash_itanium.cc index 5ae5ae0dc849..729c4a0f3739 100644 --- a/lib/ubsan/ubsan_type_hash_itanium.cc +++ b/lib/ubsan/ubsan_type_hash_itanium.cc @@ -197,7 +197,7 @@ struct VtablePrefix { }; VtablePrefix *getVtablePrefix(void *Vtable) { VtablePrefix *Vptr = reinterpret_cast(Vtable); - if (!Vptr) + if (!IsAccessibleMemoryRange((uptr)Vptr, sizeof(VtablePrefix))) return nullptr; VtablePrefix *Prefix = Vptr - 1; if (!Prefix->TypeInfo) diff --git a/test/asan/TestCases/Linux/coverage-missing.cc b/test/asan/TestCases/Linux/coverage-missing.cc index 16093498fa2c..585aee69a029 100644 --- a/test/asan/TestCases/Linux/coverage-missing.cc +++ b/test/asan/TestCases/Linux/coverage-missing.cc @@ -1,7 +1,7 @@ // Test for "sancov.py missing ...". // First case: coverage from executable. main() is called on every code path. -// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t -DFOOBAR -DMAIN +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t -DFOOBAR -DMAIN // RUN: rm -rf %T/coverage-missing // RUN: mkdir -p %T/coverage-missing // RUN: cd %T/coverage-missing @@ -27,8 +27,8 @@ // Second case: coverage from DSO. // cd %T -// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %dynamiclib -DFOOBAR -shared -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=func %s %dynamiclib -o %t -DMAIN +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %dynamiclib -DFOOBAR -shared -fPIC +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %dynamiclib -o %t -DMAIN // RUN: cd .. // RUN: rm -rf %T/coverage-missing // RUN: mkdir -p %T/coverage-missing diff --git a/test/asan/TestCases/Posix/coverage-fork.cc b/test/asan/TestCases/Posix/coverage-fork.cc index 40ce72ef5003..da6e3c2c1b38 100644 --- a/test/asan/TestCases/Posix/coverage-fork.cc +++ b/test/asan/TestCases/Posix/coverage-fork.cc @@ -1,9 +1,13 @@ -// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t // RUN: rm -rf %T/coverage-fork // RUN: mkdir -p %T/coverage-fork && cd %T/coverage-fork -// RUN: %env_asan_opts=coverage=1:coverage_direct=0:verbosity=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s // // UNSUPPORTED: android +// +// Ideally a forked-subprocess should only report it's own coverage, +// not parent's one. But trace-pc-guard currently does nothing special for fork, +// and thus this test is relaxed. #include #include @@ -32,6 +36,6 @@ int main(int argc, char **argv) { } // CHECK-DAG: Child PID: [[ChildPID:[0-9]+]] -// CHECK-DAG: [[ChildPID]].sancov: 1 PCs written +// CHECK-DAG: [[ChildPID]].sancov: {{.*}} PCs written // CHECK-DAG: Parent PID: [[ParentPID:[0-9]+]] // CHECK-DAG: [[ParentPID]].sancov: 3 PCs written diff --git a/test/asan/TestCases/Posix/coverage-module-unloaded.cc b/test/asan/TestCases/Posix/coverage-module-unloaded.cc index db27283a62c6..322a1bad1c99 100644 --- a/test/asan/TestCases/Posix/coverage-module-unloaded.cc +++ b/test/asan/TestCases/Posix/coverage-module-unloaded.cc @@ -1,12 +1,11 @@ // Check that unloading a module doesn't break coverage dumping for remaining // modules. -// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib1 -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib2 -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=func %s %libdl -o %t -// RUN: mkdir -p %T/coverage-module-unloaded && cd %T/coverage-module-unloaded -// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t %dynamiclib1 %dynamiclib2 2>&1 | FileCheck %s -// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t %dynamiclib1 %dynamiclib2 foo 2>&1 | FileCheck %s -// RUN: rm -r %T/coverage-module-unloaded +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib1 -fPIC +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib2 -fPIC +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %libdl -o %t.exe +// RUN: mkdir -p %t.tmp/coverage-module-unloaded && cd %t.tmp/coverage-module-unloaded +// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t.exe %dynamiclib1 %dynamiclib2 2>&1 | FileCheck %s +// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t.exe %dynamiclib1 %dynamiclib2 foo 2>&1 | FileCheck %s // // https://code.google.com/p/address-sanitizer/issues/detail?id=263 // XFAIL: android @@ -48,8 +47,5 @@ int main(int argc, char **argv) { #endif // CHECK: PID: [[PID:[0-9]+]] -// CHECK: [[PID]].sancov: 1 PCs written -// CHECK: coverage-module-unloaded{{.*}}1.[[PID]] -// CHECK: coverage-module-unloaded{{.*}}2.[[PID]] -// Even though we've unloaded one of the libs we still dump the coverage file -// for that lib (although the data will be inaccurate, if at all useful) +// CHECK-DAG: exe{{.*}}[[PID]].sancov: {{.*}}PCs written +// CHECK-DAG: dynamic{{.*}}[[PID]].sancov: {{.*}}PCs written diff --git a/test/asan/TestCases/Posix/coverage-sandboxing.cc b/test/asan/TestCases/Posix/coverage-sandboxing.cc deleted file mode 100644 index 354070708a7d..000000000000 --- a/test/asan/TestCases/Posix/coverage-sandboxing.cc +++ /dev/null @@ -1,87 +0,0 @@ -// RUN: %clangxx_asan -fsanitize-coverage=bb -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so -// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t %ld_flags_rpath_exe - -// RUN: rm -rf %T/coverage_sandboxing_test -// RUN: mkdir %T/coverage_sandboxing_test && cd %T/coverage_sandboxing_test -// RUN: mkdir vanilla && cd vanilla -// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-vanilla -// RUN: mkdir ../sandbox1 && cd ../sandbox1 -// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t a 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox -// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed -// RUN: mkdir ../sandbox2 && cd ../sandbox2 -// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t a b 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox -// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed -// RUN: cd .. -// RUN: %sancov print vanilla/%xdynamiclib_filename*.sancov > vanilla.txt -// RUN: %sancov print sandbox1/%xdynamiclib_filename*.sancov > sandbox1.txt -// RUN: %sancov print sandbox2/%xdynamiclib_filename*.sancov > sandbox2.txt -// RUN: diff vanilla.txt sandbox1.txt -// RUN: diff vanilla.txt sandbox2.txt -// RUN: rm -r %T/coverage_sandboxing_test - -// https://code.google.com/p/address-sanitizer/issues/detail?id=263 -// XFAIL: android -// UNSUPPORTED: ios - -#include -#include -#include -#include -#include - -#include - -#define bb0(n) \ - case n: \ - fprintf(stderr, "foo: %d\n", n); \ - break; - -#define bb1(n) bb0(n) bb0(n + 1) -#define bb2(n) bb1(n) bb1(n + 2) -#define bb3(n) bb2(n) bb2(n + 4) -#define bb4(n) bb3(n) bb3(n + 8) -#define bb5(n) bb4(n) bb4(n + 16) -#define bb6(n) bb5(n) bb5(n + 32) -#define bb7(n) bb6(n) bb6(n + 64) -#define bb8(n) bb7(n) bb7(n + 128) - -#ifdef SHARED -void foo(int i) { - switch(i) { - // 256 basic blocks - bb8(0) - } -} -#else -extern void foo(int i); - -int main(int argc, char **argv) { - assert(argc <= 3); - for (int i = 0; i < 256; i++) foo(i); - fprintf(stderr, "PID: %d\n", getpid()); - if (argc == 1) { - // Vanilla mode, dump to individual files. - return 0; - } - // Dump to packed file. - int fd = creat("coverage_sandboxing_test.sancov.packed", 0660); - __sanitizer_sandbox_arguments args = {0}; - args.coverage_sandboxed = 1; - args.coverage_fd = fd; - if (argc == 2) - // Write to packed file, do not split into blocks. - args.coverage_max_block_size = 0; - else if (argc == 3) - // Write to packed file, split into blocks (as if writing to a socket). - args.coverage_max_block_size = 100; - __sanitizer_sandbox_on_notify(&args); - return 0; -} -#endif - -// CHECK-vanilla: PID: [[PID:[0-9]+]] -// CHECK-vanilla: .so.[[PID]].sancov: 257 PCs written -// CHECK-vanilla: [[PID]].sancov: 1 PCs written - -// CHECK-sandbox: PID: [[PID:[0-9]+]] -// CHECK-sandbox: 257 PCs written to packed file diff --git a/test/asan/TestCases/Posix/coverage.cc b/test/asan/TestCases/Posix/coverage.cc index bff060968483..a78560a72a00 100644 --- a/test/asan/TestCases/Posix/coverage.cc +++ b/test/asan/TestCases/Posix/coverage.cc @@ -1,5 +1,5 @@ -// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so -// RUN: %clangxx_asan -fsanitize-coverage=func %s %ld_flags_rpath_exe -o %t +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %ld_flags_rpath_exe -o %t // RUN: rm -rf %T/coverage && mkdir -p %T/coverage && cd %T/coverage // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main // RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1 @@ -20,7 +20,6 @@ // XFAIL: android // UNSUPPORTED: ios -#include #include #include #include @@ -38,12 +37,8 @@ int G[4]; int main(int argc, char **argv) { fprintf(stderr, "PID: %d\n", getpid()); for (int i = 1; i < argc; i++) { - if (!strcmp(argv[i], "foo")) { - uintptr_t old_coverage = __sanitizer_get_total_unique_coverage(); + if (!strcmp(argv[i], "foo")) foo(); - uintptr_t new_coverage = __sanitizer_get_total_unique_coverage(); - assert(new_coverage > old_coverage); - } if (!strcmp(argv[i], "bar")) bar(); } @@ -64,12 +59,12 @@ int main(int argc, char **argv) { // CHECK-foo-NOT: .so.[[PID]] // // CHECK-bar: PID: [[PID:[0-9]+]] -// CHECK-bar: .so.[[PID]].sancov: 1 PCs written -// CHECK-bar: [[PID]].sancov: 1 PCs written +// CHECK-bar-DAG: .so.[[PID]].sancov: 1 PCs written +// CHECK-bar-DAG: [[PID]].sancov: 1 PCs written // // CHECK-foo-bar: PID: [[PID:[0-9]+]] -// CHECK-foo-bar: so.[[PID]].sancov: 1 PCs written -// CHECK-foo-bar: [[PID]].sancov: 2 PCs written +// CHECK-foo-bar-DAG: so.[[PID]].sancov: 1 PCs written +// CHECK-foo-bar-DAG: [[PID]].sancov: 2 PCs written // // CHECK-report: AddressSanitizer: global-buffer-overflow // CHECK-report: PCs written diff --git a/test/asan/TestCases/Posix/strndup_oob_test.cc b/test/asan/TestCases/Posix/strndup_oob_test.cc new file mode 100644 index 000000000000..7ea0b7a33400 --- /dev/null +++ b/test/asan/TestCases/Posix/strndup_oob_test.cc @@ -0,0 +1,27 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// When built as C on Linux, strndup is transformed to __strndup. +// RUN: %clangxx_asan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck %s + +// Unwind problem on arm: "main" is missing from the allocation stack trace. +// UNSUPPORTED: win32,s390,armv7l-unknown-linux-gnueabihf + +#include + +char kString[] = "foo"; + +int main(int argc, char **argv) { + char *copy = strndup(kString, 2); + int x = copy[2 + argc]; // BOOM + // CHECK: AddressSanitizer: heap-buffer-overflow + // CHECK: #0 {{.*}}main {{.*}}strndup_oob_test.cc:[[@LINE-2]] + // CHECK-LABEL: allocated by thread T{{.*}} here: + // CHECK: #{{[01]}} {{.*}}strndup + // CHECK: #{{.*}}main {{.*}}strndup_oob_test.cc:[[@LINE-6]] + // CHECK-LABEL: SUMMARY + // CHECK: strndup_oob_test.cc:[[@LINE-7]] + return x; +} diff --git a/test/asan/TestCases/Posix/strndup_oob_test2.cc b/test/asan/TestCases/Posix/strndup_oob_test2.cc new file mode 100644 index 000000000000..903f5e65f98f --- /dev/null +++ b/test/asan/TestCases/Posix/strndup_oob_test2.cc @@ -0,0 +1,22 @@ +// RUN: %clang_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clang_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clang_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clang_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// When built as C on Linux, strndup is transformed to __strndup. +// RUN: %clang_asan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck %s + +// Unwind problem on arm: "main" is missing from the allocation stack trace. +// UNSUPPORTED: win32,s390,armv7l-unknown-linux-gnueabihf + +#include + +char kChars[] = { 'f', 'o', 'o' }; + +int main(int argc, char **argv) { + char *copy = strndup(kChars, 3); + copy = strndup(kChars, 10); + // CHECK: AddressSanitizer: global-buffer-overflow + // CHECK: {{.*}}main {{.*}}.cc:[[@LINE-2]] + return *copy; +} \ No newline at end of file diff --git a/test/asan/TestCases/coverage-and-lsan.cc b/test/asan/TestCases/coverage-and-lsan.cc index 081f493ee80d..591b4e93fac7 100644 --- a/test/asan/TestCases/coverage-and-lsan.cc +++ b/test/asan/TestCases/coverage-and-lsan.cc @@ -1,6 +1,6 @@ // Make sure coverage is dumped even if there are reported leaks. // -// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t +// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t // // RUN: rm -rf %T/coverage-and-lsan // @@ -17,4 +17,4 @@ int main(int argc, char **argv) { } // CHECK: LeakSanitizer: detected memory leaks -// CHECK: CovDump: +// CHECK: SanitizerCoverage: {{.*}}PCs written diff --git a/test/asan/TestCases/coverage-order-pcs.cc b/test/asan/TestCases/coverage-order-pcs.cc deleted file mode 100644 index e81c91045455..000000000000 --- a/test/asan/TestCases/coverage-order-pcs.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Test coverage_order_pcs=1 flag which orders the PCs by their appearance. -// RUN: DIR=%T/coverage-order-pcs -// RUN: rm -rf $DIR -// RUN: mkdir $DIR -// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t -// RUN: %env_asan_opts=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %run %t -// RUN: mv $DIR/*sancov $DIR/A - -// RUN: %env_asan_opts=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %run %t 1 -// RUN: mv $DIR/*sancov $DIR/B - -// RUN: %env_asan_opts=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %run %t -// RUN: mv $DIR/*sancov $DIR/C - -// RUN: %env_asan_opts=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %run %t 1 -// RUN: mv $DIR/*sancov $DIR/D -// -// RUN: (%sancov print $DIR/A; %sancov print $DIR/B; %sancov print $DIR/C; %sancov print $DIR/D) | FileCheck %s -// -// RUN: rm -rf $DIR -// Ordering works only in 64-bit mode for now. -// REQUIRES: asan-64-bits, shell -// UNSUPPORTED: android -#include - -void foo() { fprintf(stderr, "FOO\n"); } -void bar() { fprintf(stderr, "BAR\n"); } - -int main(int argc, char **argv) { - if (argc == 2) { - foo(); - bar(); - } else { - bar(); - foo(); - } -} - -// Run A: no ordering -// CHECK: [[FOO:0x[0-9a-f]*]] -// CHECK-NEXT: [[BAR:0x[0-9a-f]*]] -// CHECK-NEXT: [[MAIN:0x[0-9a-f]*]] -// -// Run B: still no ordering -// CHECK-NEXT: [[FOO]] -// CHECK-NEXT: [[BAR]] -// CHECK-NEXT: [[MAIN]] -// -// Run C: MAIN, BAR, FOO -// CHECK-NEXT: [[MAIN]] -// CHECK-NEXT: [[BAR]] -// CHECK-NEXT: [[FOO]] -// -// Run D: MAIN, FOO, BAR -// CHECK-NEXT: [[MAIN]] -// CHECK-NEXT: [[FOO]] -// CHECK-NEXT: [[BAR]] diff --git a/test/msan/strndup.cc b/test/msan/strndup.cc new file mode 100644 index 000000000000..d4b9af1a9a6e --- /dev/null +++ b/test/msan/strndup.cc @@ -0,0 +1,28 @@ +// RUN: %clangxx_msan %s -o %t && not %run %t 2>&1 | FileCheck --check-prefix=ON %s +// RUN: %clangxx_msan %s -o %t && MSAN_OPTIONS=intercept_strndup=0 %run %t 2>&1 | FileCheck --check-prefix=OFF --allow-empty %s + +// When built as C on Linux, strndup is transformed to __strndup. +// RUN: %clangxx_msan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck --check-prefix=ON %s + +// UNSUPPORTED: win32 + +#include +#include +#include +#include + +int main(int argc, char **argv) { + char kString[4] = "abc"; + __msan_poison(kString + 2, 1); + char *copy = strndup(kString, 4); // BOOM + assert(__msan_test_shadow(copy, 4) == 2); // Poisoning is preserved. + free(copy); + return 0; + // ON: Uninitialized bytes in __interceptor_{{(__)?}}strndup at offset 2 inside [{{.*}}, 4) + // ON: MemorySanitizer: use-of-uninitialized-value + // ON: #0 {{.*}}main {{.*}}strndup.cc:[[@LINE-6]] + // ON-LABEL: SUMMARY + // ON: {{.*}}strndup.cc:[[@LINE-8]] + // OFF-NOT: MemorySanitizer +} + diff --git a/test/sanitizer_common/TestCases/Linux/allocator_fork_no_hang.cc b/test/sanitizer_common/TestCases/Linux/allocator_fork_no_hang.cc new file mode 100644 index 000000000000..d159d85ee2d6 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/allocator_fork_no_hang.cc @@ -0,0 +1,118 @@ +// https://github.com/google/sanitizers/issues/774 +// Test that sanitizer allocator is fork-safe. +// Run a number of threads that perform memory allocation/deallocation, then fork +// and verify that malloc/free do not deadlock in the child process. + +// RUN: %clangxx -std=c++11 -O0 %s -o %t +// RUN: ASAN_OPTIONS=detect_leaks=0 %run %t 2>&1 | FileCheck %s + +// Fun fact: if test output is redirected to a file (as opposed to +// being piped directly to FileCheck), we may lose some "done"s due to +// a kernel bug: +// https://lkml.org/lkml/2014/2/17/324 + +// UNSUPPORTED: tsan + +// Flaky on PPC64. +// UNSUPPORTED: powerpc64-target-arch +// UNSUPPORTED: powerpc64le-target-arch + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int done; + +void *worker(void *arg) { + while (true) { + void *p = malloc(4); + if (__atomic_load_n(&done, __ATOMIC_RELAXED)) + return 0; + } + return 0; +} + +// Run through malloc/free in the child process. +// This can deadlock on allocator cache refilling. +void child() { + for (int i = 0; i < 10000; ++i) { + void *p = malloc(4); + } + write(2, "done\n", 5); +} + +void test() { + const int kThreads = 10; + pthread_t t[kThreads]; + for (int i = 0; i < kThreads; ++i) + pthread_create(&t[i], NULL, worker, (void*)(long)i); + usleep(100000); + pid_t pid = fork(); + if (pid) { + // parent + __atomic_store_n(&done, 1, __ATOMIC_RELAXED); + pid_t p; + while ((p = wait(NULL)) == -1) { } + } else { + // child + child(); + } +} + +int main() { + const int kChildren = 30; + for (int i = 0; i < kChildren; ++i) { + pid_t pid = fork(); + if (pid) { + // parent + } else { + test(); + exit(0); + } + } + + for (int i = 0; i < kChildren; ++i) { + pid_t p; + while ((p = wait(NULL)) == -1) { } + } + + return 0; +} + +// Expect 30 (== kChildren) "done" messages. +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done +// CHECK: done diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc index 266dc3f0e976..28e237802b21 100644 --- a/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc +++ b/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cc @@ -25,4 +25,4 @@ int main() { } // CHECK: main -// CHECK: SanitizerCoverage: ./sanitizer_coverage_symbolize.{{.*}}.sancov 2 PCs written +// CHECK: SanitizerCoverage: ./sanitizer_coverage_symbolize.{{.*}}.sancov: 2 PCs written diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc index 68459b19a159..6185177a169a 100644 --- a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc +++ b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc @@ -62,9 +62,9 @@ int baz() { // CHECK-NEXT: foo // CHECK-NEXT: bar // CHECK-NEXT: baz -// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}.sancov 2 PCs written -// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_2.so.{{.*}}.sancov 1 PCs written -// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_1.so.{{.*}}.sancov 1 PCs written +// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}.sancov: 2 PCs written +// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_2.so.{{.*}}.sancov: 1 PCs written +// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_1.so.{{.*}}.sancov: 1 PCs written // // CHECK-SANCOV: Ignoring {{.*}}_1.so and its coverage because __sanitizer_cov* functions were not found. // CHECK-SANCOV: Ignoring {{.*}}_2.so and its coverage because __sanitizer_cov* functions were not found. diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc index 9dcbe6fa0387..2d6d00b6a0cd 100644 --- a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc +++ b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc @@ -34,7 +34,7 @@ int main() { // CHECK: main // CHECK-NEXT: foo // CHECK-NEXT: foo -// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov 2 PCs written +// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov: 2 PCs written // // CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cc:23 foo // CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cc:28 main diff --git a/test/ubsan/TestCases/TypeCheck/PR33221.cpp b/test/ubsan/TestCases/TypeCheck/PR33221.cpp new file mode 100644 index 000000000000..09411aa509b8 --- /dev/null +++ b/test/ubsan/TestCases/TypeCheck/PR33221.cpp @@ -0,0 +1,28 @@ +// RUN: %clangxx -frtti -fsanitize=vptr -g %s -O3 -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +// REQUIRES: cxxabi + +#include + +class Base { +public: + int i; + virtual void print() {} +}; + +class Derived : public Base { +public: + void print() {} +}; + +int main() { + char *c = new char[sizeof(Derived)]; + memset((void *)c, 0, sizeof(Derived)); + Derived *list = (Derived *)c; + +// CHECK: PR33221.cpp:[[@LINE+2]]:19: runtime error: member access within address {{.*}} which does not point to an object of type 'Base' +// CHECK-NEXT: invalid vptr + int foo = list->i; + return 0; +} From aaf9a7aadf355bb6cb3b33631502f4f77ab43e13 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Thu, 1 Jun 2017 20:59:29 +0000 Subject: [PATCH 08/22] Vendor import of lldb trunk r304460: https://llvm.org/svn/llvm-project/lldb/trunk@304460 --- cmake/modules/LLDBConfig.cmake | 38 +++++++++---------- .../lang/cpp/namespace_conflicts/Makefile | 3 ++ .../TestNamespaceConflicts.py | 7 ++++ .../lang/cpp/namespace_conflicts/main.cpp | 29 ++++++++++++++ tools/lldb-mi/MICmdCmdVar.cpp | 26 ++++++------- www/projects.html | 19 ++++++++++ 6 files changed, 88 insertions(+), 34 deletions(-) create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/main.cpp diff --git a/cmake/modules/LLDBConfig.cmake b/cmake/modules/LLDBConfig.cmake index 609851f46e49..79512941fd8d 100644 --- a/cmake/modules/LLDBConfig.cmake +++ b/cmake/modules/LLDBConfig.cmake @@ -334,28 +334,26 @@ if (HAVE_LIBDL) list(APPEND system_libs ${CMAKE_DL_LIBS}) endif() -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - # Check for syscall used by lldb-server on linux. - # If these are not found, it will fall back to ptrace (slow) for memory reads. - check_cxx_source_compiles(" - #include - int main() { process_vm_readv(0, nullptr, 0, nullptr, 0, 0); return 0; }" - HAVE_PROCESS_VM_READV) +# Check for syscall used by lldb-server on linux. +# If these are not found, it will fall back to ptrace (slow) for memory reads. +check_cxx_source_compiles(" + #include + int main() { process_vm_readv(0, nullptr, 0, nullptr, 0, 0); return 0; }" + HAVE_PROCESS_VM_READV) - if (HAVE_PROCESS_VM_READV) - add_definitions(-DHAVE_PROCESS_VM_READV) - else() - # If we don't have the syscall wrapper function, but we know the syscall number, we can - # still issue the syscall manually - check_cxx_source_compiles(" - #include - int main() { return __NR_process_vm_readv; }" - HAVE_NR_PROCESS_VM_READV) +if (HAVE_PROCESS_VM_READV) + add_definitions(-DHAVE_PROCESS_VM_READV) +else() + # If we don't have the syscall wrapper function, but we know the syscall number, we can + # still issue the syscall manually + check_cxx_source_compiles(" + #include + int main() { return __NR_process_vm_readv; }" + HAVE_NR_PROCESS_VM_READV) - if (HAVE_NR_PROCESS_VM_READV) - add_definitions(-DHAVE_NR_PROCESS_VM_READV) - endif() - endif() + if (HAVE_NR_PROCESS_VM_READV) + add_definitions(-DHAVE_NR_PROCESS_VM_READV) + endif() endif() # Figure out if lldb could use lldb-server. If so, then we'll diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/Makefile b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/Makefile new file mode 100644 index 000000000000..99bfa7e03b47 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py new file mode 100644 index 000000000000..af362f5be5d7 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py @@ -0,0 +1,7 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest( + __file__, globals(), [ + decorators.expectedFailureAll( + oslist=["windows"], bugnumber="llvm.org/pr24764")]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/main.cpp new file mode 100644 index 000000000000..5dfca5b7f996 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/main.cpp @@ -0,0 +1,29 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +namespace n { + struct D { + int i; + static int anInt() { return 2; } + int dump() { return i; } + }; +} + +using namespace n; + +int foo(D* D) { + return D->dump(); //% self.expect("expression -- D->dump()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["int", "2"]) +} + +int main (int argc, char const *argv[]) +{ + D myD { D::anInt() }; + foo(&myD); + return 0; +} diff --git a/tools/lldb-mi/MICmdCmdVar.cpp b/tools/lldb-mi/MICmdCmdVar.cpp index 3396b7231c5c..66b392be6bed 100644 --- a/tools/lldb-mi/MICmdCmdVar.cpp +++ b/tools/lldb-mi/MICmdCmdVar.cpp @@ -510,22 +510,20 @@ bool CMICmdCmdVarUpdate::ExamineSBValueForChange(lldb::SBValue &vrwValue, } lldb::SBType valueType = vrwValue.GetType(); - if (!valueType.IsPointerType() && !valueType.IsReferenceType()) { - const MIuint nChildren = vrwValue.GetNumChildren(); - for (MIuint i = 0; i < nChildren; ++i) { - lldb::SBValue member = vrwValue.GetChildAtIndex(i); - if (!member.IsValid()) - continue; - if (member.GetValueDidChange()) { - vrwbChanged = true; - return MIstatus::success; - } else if (ExamineSBValueForChange(member, vrwbChanged) && vrwbChanged) - // Handle composite types (i.e. struct or arrays) - return MIstatus::success; - } + const MIuint nChildren = vrwValue.GetNumChildren(); + for (MIuint i = 0; i < nChildren; ++i) { + lldb::SBValue member = vrwValue.GetChildAtIndex(i); + if (!member.IsValid()) + continue; + + if (member.GetValueDidChange()) { + vrwbChanged = true; + return MIstatus::success; + } else if (ExamineSBValueForChange(member, vrwbChanged) && vrwbChanged) + // Handle composite types (i.e. struct or arrays) + return MIstatus::success; } - vrwbChanged = false; return MIstatus::success; } diff --git a/www/projects.html b/www/projects.html index b1aeb1021eca..e375eb9cc3d2 100755 --- a/www/projects.html +++ b/www/projects.html @@ -243,6 +243,25 @@

+
  • + Reimplement the command interpreter commands using the SB API +

    + Currently, all the CommandObject::DoExecute methods are implemented + using the lldb_private API's. That generally means that there's code + that gets duplicated between the CommandObject and the SB API that does + roughly the same thing. We would reduce this code duplication, present a + single coherent face to the users of lldb, and keep + ourselves more honest about what we need in the SB API's if we implemented + the CommandObjects::DoExecute methods using the SB API's. +

    +

    + BTW, it is only the way it was much easier to develop lldb if it had a functioning + command-line early on. So we did that first, and developed the SB API's when lldb + was more mature. There's no good technical reason to have the commands use the + lldb_private API's. +

    +
  • +
  • Documentation and better examples From 551c698530debaae81139c7c76a29fb762793362 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 3 Jun 2017 15:20:48 +0000 Subject: [PATCH 09/22] Vendor import of clang trunk r304659: https://llvm.org/svn/llvm-project/cfe/trunk@304659 --- docs/Modules.rst | 25 +- include/clang/Basic/DiagnosticLexKinds.td | 6 + include/clang/Basic/DiagnosticSemaKinds.td | 4 +- .../Basic/DiagnosticSerializationKinds.td | 12 +- include/clang/Basic/Module.h | 10 +- include/clang/Basic/Sanitizers.h | 10 +- include/clang/Driver/CC1Options.td | 3 + include/clang/Frontend/CodeGenOptions.def | 1 + include/clang/Lex/ModuleMap.h | 45 ++- lib/ARCMigrate/TransRetainReleaseDealloc.cpp | 1 + lib/ARCMigrate/TransformActions.cpp | 1 + lib/AST/ASTContext.cpp | 2 + lib/AST/ASTDiagnostic.cpp | 1 + lib/AST/ASTStructuralEquivalence.cpp | 1 + lib/AST/DeclPrinter.cpp | 6 +- lib/AST/Expr.cpp | 2 + lib/AST/ExprConstant.cpp | 3 + lib/AST/ItaniumMangle.cpp | 23 +- lib/AST/NestedNameSpecifier.cpp | 1 + lib/Analysis/PrintfFormatString.cpp | 1 + lib/Analysis/PseudoConstantAnalysis.cpp | 1 + lib/Analysis/ScanfFormatString.cpp | 2 + lib/Basic/IdentifierTable.cpp | 1 + lib/Basic/LangOptions.cpp | 4 +- lib/Basic/Module.cpp | 21 +- lib/Basic/TargetInfo.cpp | 2 + lib/CodeGen/BackendUtil.cpp | 25 +- lib/CodeGen/CGBuiltin.cpp | 3 + lib/CodeGen/CGCall.cpp | 1 + lib/CodeGen/CGCoroutine.cpp | 1 + lib/CodeGen/CGDebugInfo.cpp | 8 +- lib/CodeGen/CGDebugInfo.h | 2 +- lib/CodeGen/CGExpr.cpp | 4 +- lib/CodeGen/CGExprScalar.cpp | 2 +- lib/CodeGen/CodeGenFunction.cpp | 2 +- lib/CodeGen/CodeGenModule.cpp | 1 + lib/Driver/SanitizerArgs.cpp | 10 +- lib/Edit/RewriteObjCFoundationAPI.cpp | 4 + lib/Frontend/CompilerInstance.cpp | 1 + lib/Frontend/CompilerInvocation.cpp | 9 + lib/Frontend/FrontendAction.cpp | 26 +- lib/Frontend/FrontendActions.cpp | 7 +- lib/Frontend/InitHeaderSearch.cpp | 2 + lib/Frontend/Rewrite/FrontendActions.cpp | 7 +- lib/Frontend/Rewrite/InclusionRewriter.cpp | 7 +- lib/Frontend/SerializedDiagnosticReader.cpp | 1 + lib/Lex/HeaderSearch.cpp | 2 + lib/Lex/Lexer.cpp | 2 + lib/Lex/LiteralSupport.cpp | 15 +- lib/Lex/ModuleMap.cpp | 334 +++++++++++++----- lib/Lex/PPDirectives.cpp | 2 + lib/Parse/ParseDecl.cpp | 4 + lib/Parse/ParseDeclCXX.cpp | 1 + lib/Parse/ParseExpr.cpp | 5 +- lib/Parse/ParseInit.cpp | 3 +- lib/Parse/ParseOpenMP.cpp | 4 + lib/Parse/ParseStmt.cpp | 1 + lib/Parse/ParseTentative.cpp | 2 + lib/Parse/Parser.cpp | 2 + lib/Rewrite/HTMLRewrite.cpp | 1 + lib/Sema/CoroutineStmtBuilder.h | 3 + lib/Sema/SemaCodeComplete.cpp | 2 + lib/Sema/SemaCoroutine.cpp | 19 +- lib/Sema/SemaDecl.cpp | 5 +- lib/Sema/SemaDeclCXX.cpp | 1 + lib/Sema/SemaExpr.cpp | 2 + lib/Sema/SemaLambda.cpp | 1 + lib/Sema/SemaLookup.cpp | 1 + lib/Sema/SemaStmt.cpp | 47 ++- lib/Sema/SemaStmtAsm.cpp | 1 + lib/Sema/SemaTemplateDeduction.cpp | 4 +- lib/Sema/SemaType.cpp | 50 ++- lib/Sema/TreeTransform.h | 2 + lib/Serialization/ASTReader.cpp | 29 ++ lib/Serialization/ASTWriter.cpp | 157 +++++--- .../Checkers/DeadStoresChecker.cpp | 1 + lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + lib/StaticAnalyzer/Core/SValBuilder.cpp | 1 + lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 1 + test/CodeGen/pr26099.c | 12 + test/CodeGen/thin_link_bitcode.c | 5 + test/CodeGen/ubsan-pointer-overflow.m | 12 +- test/CodeGenCXX/pr33080.cpp | 33 ++ .../unaligned-duplicated-mangle-name.cpp | 20 -- .../CodeGenCXX/unaligned-member-qualifier.cpp | 20 ++ test/CodeGenCoroutines/coro-params.cpp | 34 ++ test/CodeGenObjCXX/arc-mangle.mm | 10 + test/Driver/fsanitize-coverage.c | 3 + test/Frontend/rewrite-includes-filenotfound.c | 6 + test/Integration/carbon.c | 1 + test/Integration/cocoa-pch.m | 1 + test/Integration/cocoa.m | 1 + test/Misc/ast-print-objectivec.m | 15 +- .../check-for-sanitizer-feature/check.h | 5 + .../Inputs/check-for-sanitizer-feature/map | 3 + test/Modules/Inputs/header-attribs/bar.h | 1 + test/Modules/Inputs/header-attribs/baz.h | 1 + test/Modules/Inputs/header-attribs/foo.h | 1 + .../Inputs/header-attribs/modular.modulemap | 5 + .../Inputs/header-attribs/textual.modulemap | 5 + test/Modules/check-for-sanitizer-feature.cpp | 66 ++++ test/Modules/diagnostics.modulemap | 14 +- test/Modules/header-attribs.cpp | 10 + test/Modules/lookup.m | 4 +- test/Modules/preprocess-missing.modulemap | 7 + test/Modules/preprocess-module.cpp | 15 +- test/Sema/warn-strict-prototypes.m | 11 +- test/SemaCXX/coroutines.cpp | 13 + test/SemaOpenCL/func.cl | 7 + test/SemaTemplate/deduction-crash.cpp | 36 +- test/lit.cfg | 3 + unittests/AST/DeclPrinterTest.cpp | 2 +- 112 files changed, 1099 insertions(+), 301 deletions(-) create mode 100644 test/CodeGen/pr26099.c create mode 100644 test/CodeGenCXX/pr33080.cpp delete mode 100644 test/CodeGenCXX/unaligned-duplicated-mangle-name.cpp create mode 100644 test/CodeGenCXX/unaligned-member-qualifier.cpp create mode 100644 test/Frontend/rewrite-includes-filenotfound.c create mode 100644 test/Modules/Inputs/check-for-sanitizer-feature/check.h create mode 100644 test/Modules/Inputs/check-for-sanitizer-feature/map create mode 100644 test/Modules/Inputs/header-attribs/bar.h create mode 100644 test/Modules/Inputs/header-attribs/baz.h create mode 100644 test/Modules/Inputs/header-attribs/foo.h create mode 100644 test/Modules/Inputs/header-attribs/modular.modulemap create mode 100644 test/Modules/Inputs/header-attribs/textual.modulemap create mode 100644 test/Modules/check-for-sanitizer-feature.cpp create mode 100644 test/Modules/header-attribs.cpp create mode 100644 test/Modules/preprocess-missing.modulemap diff --git a/docs/Modules.rst b/docs/Modules.rst index 7bd2adf8af52..ed6f81715731 100644 --- a/docs/Modules.rst +++ b/docs/Modules.rst @@ -469,9 +469,16 @@ A header declaration specifies that a particular header is associated with the e .. parsed-literal:: *header-declaration*: - ``private``:sub:`opt` ``textual``:sub:`opt` ``header`` *string-literal* - ``umbrella`` ``header`` *string-literal* - ``exclude`` ``header`` *string-literal* + ``private``:sub:`opt` ``textual``:sub:`opt` ``header`` *string-literal* *header-attrs*:sub:`opt` + ``umbrella`` ``header`` *string-literal* *header-attrs*:sub:`opt` + ``exclude`` ``header`` *string-literal* *header-attrs*:sub:`opt` + + *header-attrs*: + '{' *header-attr** '}' + + *header-attr*: + ``size`` *integer-literal* + ``mtime`` *integer-literal* A header declaration that does not contain ``exclude`` nor ``textual`` specifies a header that contributes to the enclosing module. Specifically, when the module is built, the named header will be parsed and its declarations will be (logically) placed into the enclosing submodule. @@ -504,6 +511,18 @@ A header with the ``exclude`` specifier is excluded from the module. It will not A given header shall not be referenced by more than one *header-declaration*. +Two *header-declaration*\s, or a *header-declaration* and a ``#include``, are +considered to refer to the same file if the paths resolve to the same file +and the specified *header-attr*\s (if any) match the attributes of that file, +even if the file is named differently (for instance, by a relative path or +via symlinks). + +.. note:: + The use of *header-attr*\s avoids the need for Clang to speculatively + ``stat`` every header referenced by a module map. It is recommended that + *header-attr*\s only be used in machine-generated module maps, to avoid + mismatches between attribute values and the corresponding files. + Umbrella directory declaration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ An umbrella directory declaration specifies that all of the headers in the specified directory should be included within the module. diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index b393ce5f1545..447f06945660 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -664,6 +664,12 @@ def warn_mmap_mismatched_top_level_private : Warning< InGroup; def note_mmap_rename_top_level_private_as_submodule : Note< "make '%0' a submodule of '%1' to ensure it can be found by name">; +def err_mmap_duplicate_header_attribute : Error< + "header attribute '%0' specified multiple times">; +def err_mmap_invalid_header_attribute_value : Error< + "expected integer literal as value for header attribute '%0'">; +def err_mmap_expected_header_attribute : Error< + "expected a header attribute name ('size' or 'mtime')">; def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4de4f47b8a5a..a5a5c74afe69 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4584,7 +4584,7 @@ def warn_missing_prototype : Warning< def note_declaration_not_a_prototype : Note< "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">; def warn_strict_prototypes : Warning< - "this %select{function declaration is not|" + "this %select{function declaration is not|block declaration is not|" "old-style function definition is not preceded by}0 a prototype">, InGroup>, DefaultIgnore; def warn_missing_variable_declarations : Warning< @@ -7268,7 +7268,7 @@ def err_invalid_conversion_between_vector_and_integer : Error< "invalid conversion between vector type %0 and integer type %1 " "of different size">; -def err_opencl_function_pointer_variable : Error< +def err_opencl_function_pointer : Error< "pointers to functions are not allowed">; def err_opencl_taking_function_address : Error< diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 35e2f67e24b6..f9e7b8fa9b56 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -174,10 +174,6 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "method %2 with %ordinal3 parameter of type %4%select{| decayed from %6}5|" "method %2 with %ordinal3 parameter named %4}1">; -def warn_module_uses_date_time : Warning< - "%select{precompiled header|module}0 uses __DATE__ or __TIME__">, - InGroup>; - def warn_duplicate_module_file_extension : Warning< "duplicate module file extension block name '%0'">, InGroup; @@ -186,7 +182,15 @@ def warn_module_system_bit_conflict : Warning< "module file '%0' was validated as a system module and is now being imported " "as a non-system module; any difference in diagnostic options will be ignored">, InGroup; +} // let CategoryName +let CategoryName = "AST Serialization Issue" in { +def warn_module_uses_date_time : Warning< + "%select{precompiled header|module}0 uses __DATE__ or __TIME__">, + InGroup>; +def err_module_no_size_mtime_for_header : Error< + "cannot emit module %0: %select{size|mtime}1 must be explicitly specified " + "for missing header file \"%2\"">; } // let CategoryName } // let Component diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 326d84eeb6c2..1e52b29367b2 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -154,11 +154,19 @@ class Module { /// \brief Stored information about a header directive that was found in the /// module map file but has not been resolved to a file. struct UnresolvedHeaderDirective { + HeaderKind Kind = HK_Normal; SourceLocation FileNameLoc; std::string FileName; - bool IsUmbrella; + bool IsUmbrella = false; + bool HasBuiltinHeader = false; + Optional Size; + Optional ModTime; }; + /// Headers that are mentioned in the module map file but that we have not + /// yet attempted to resolve to a file on the file system. + SmallVector UnresolvedHeaders; + /// \brief Headers that are mentioned in the module map file but could not be /// found on the file system. SmallVector MissingHeaders; diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h index bfa8e516edd3..5317720095e0 100644 --- a/include/clang/Basic/Sanitizers.h +++ b/include/clang/Basic/Sanitizers.h @@ -61,8 +61,8 @@ struct SanitizerSet { Mask = Value ? (Mask | K) : (Mask & ~K); } - /// \brief Disable all sanitizers. - void clear() { Mask = 0; } + /// Disable the sanitizers specified in \p K. + void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; } /// \brief Returns true if at least one sanitizer is enabled. bool empty() const { return Mask == 0; } @@ -79,6 +79,12 @@ SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups); /// this group enables. SanitizerMask expandSanitizerGroups(SanitizerMask Kinds); +/// Return the sanitizers which do not affect preprocessing. +static inline SanitizerMask getPPTransparentSanitizers() { + return SanitizerKind::CFI | SanitizerKind::Integer | + SanitizerKind::Nullability | SanitizerKind::Undefined; +} + } // end namespace clang #endif diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index b55289dc35a1..1132d1345f60 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -293,6 +293,9 @@ def fsanitize_coverage_trace_gep def fsanitize_coverage_8bit_counters : Flag<["-"], "fsanitize-coverage-8bit-counters">, HelpText<"Enable frequency counters in sanitizer coverage">; +def fsanitize_coverage_inline_8bit_counters + : Flag<["-"], "fsanitize-coverage-inline-8bit-counters">, + HelpText<"Enable inline 8-bit counters in sanitizer coverage">; def fsanitize_coverage_trace_pc : Flag<["-"], "fsanitize-coverage-trace-pc">, HelpText<"Enable PC tracing in sanitizer coverage">; diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 9a13854671d2..d7cd805fa10a 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -163,6 +163,7 @@ CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters. CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning. CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index c05faa4a8201..11506939f9b1 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -26,6 +26,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/Twine.h" #include #include @@ -116,6 +117,11 @@ class ModuleMap { // Adjust ModuleMap::addHeader. }; + /// Convert a header kind to a role. Requires Kind to not be HK_Excluded. + static ModuleHeaderRole headerKindToRole(Module::HeaderKind Kind); + /// Convert a header role to a kind. + static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role); + /// \brief A header that is known to reside within a given module, /// whether it was included or excluded. class KnownHeader { @@ -165,7 +171,13 @@ class ModuleMap { /// \brief Mapping from each header to the module that owns the contents of /// that header. HeadersMap Headers; - + + /// Map from file sizes to modules with lazy header directives of that size. + mutable llvm::DenseMap> LazyHeadersBySize; + /// Map from mtimes to modules with lazy header directives with those mtimes. + mutable llvm::DenseMap> + LazyHeadersByModTime; + /// \brief Mapping from directories with umbrella headers to the module /// that is generated from the umbrella header. /// @@ -257,22 +269,30 @@ class ModuleMap { /// resolved. Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const; - /// Resolve the given header directive to an actual header file. + /// Add an unresolved header to a module. + void addUnresolvedHeader(Module *Mod, + Module::UnresolvedHeaderDirective Header); + + /// Look up the given header directive to find an actual header file. /// /// \param M The module in which we're resolving the header directive. /// \param Header The header directive to resolve. /// \param RelativePathName Filled in with the relative path name from the /// module to the resolved header. /// \return The resolved file, if any. - const FileEntry *resolveHeader(Module *M, - Module::UnresolvedHeaderDirective Header, - SmallVectorImpl &RelativePathName); + const FileEntry *findHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header, + SmallVectorImpl &RelativePathName); + + /// Resolve the given header directive. + void resolveHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header); /// Attempt to resolve the specified header directive as naming a builtin /// header. - const FileEntry * - resolveAsBuiltinHeader(Module *M, Module::UnresolvedHeaderDirective Header, - SmallVectorImpl &BuiltinPathName); + /// \return \c true if a corresponding builtin header was found. + bool resolveAsBuiltinHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header); /// \brief Looks up the modules that \p File corresponds to. /// @@ -368,6 +388,15 @@ class ModuleMap { /// the preferred module for the header. ArrayRef findAllModulesForHeader(const FileEntry *File) const; + /// Resolve all lazy header directives for the specified file. + /// + /// This ensures that the HeaderFileInfo on HeaderSearch is up to date. This + /// is effectively internal, but is exposed so HeaderSearch can call it. + void resolveHeaderDirectives(const FileEntry *File) const; + + /// Resolve all lazy header directives for the specified module. + void resolveHeaderDirectives(Module *Mod) const; + /// \brief Reports errors if a module must not include a specific file. /// /// \param RequestingModule The module including a file. diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp index f81133f3aad3..389f3655aa52 100644 --- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -78,6 +78,7 @@ class RetainReleaseDeallocRemover : } } // Pass through. + LLVM_FALLTHROUGH; case OMF_retain: case OMF_release: if (E->getReceiverKind() == ObjCMessageExpr::Instance) diff --git a/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp index c628b54ed414..4f3fb5845925 100644 --- a/lib/ARCMigrate/TransformActions.cpp +++ b/lib/ARCMigrate/TransformActions.cpp @@ -539,6 +539,7 @@ void TransformActionsImpl::addRemoval(CharSourceRange range) { return; case Range_Contains: RI->End = newRange.End; + LLVM_FALLTHROUGH; case Range_ExtendsBegin: newRange.End = RI->End; Removals.erase(RI); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 29d970e66d71..34c4d2617ec9 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -6240,6 +6240,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += "{objc_class=}"; return; } + // TODO: Double check to make sure this intentially falls through. + LLVM_FALLTHROUGH; } case Type::ObjCInterface: { diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 03e6115a0dba..b43c28deb362 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -360,6 +360,7 @@ void clang::FormatASTNodeDiagnosticArgument( Modifier = StringRef(); Argument = StringRef(); // Fall through + LLVM_FALLTHROUGH; } case DiagnosticsEngine::ak_qualtype: { assert(Modifier.empty() && Argument.empty() && diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index 9376ee1d4ee4..eff1aa5e323d 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -424,6 +424,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; // Fall through to check the bits common with FunctionNoProtoType. + LLVM_FALLTHROUGH; } case Type::FunctionNoProto: { diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index bc8a34c93653..6eeba88e4033 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -1189,7 +1189,9 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { for (const auto *PI : OMD->parameters()) { // FIXME: selector is missing here! pos = name.find_first_of(':', lastPos); - Out << " " << name.substr(lastPos, pos - lastPos) << ':'; + if (lastPos != 0) + Out << " "; + Out << name.substr(lastPos, pos - lastPos) << ':'; PrintObjCMethodType(OMD->getASTContext(), PI->getObjCDeclQualifier(), PI->getType()); @@ -1198,7 +1200,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { } if (OMD->param_begin() == OMD->param_end()) - Out << " " << name; + Out << name; if (OMD->isVariadic()) Out << ", ..."; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index d523a0f93cf6..c21cd3f65bd4 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1576,6 +1576,7 @@ bool CastExpr::CastConsistency() const { getSubExpr()->getType()->isBlockPointerType()); assert(getType()->getPointeeType().getAddressSpace() != getSubExpr()->getType()->getPointeeType().getAddressSpace()); + LLVM_FALLTHROUGH; // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: @@ -2102,6 +2103,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, } // Fallthrough for generic call handling. + LLVM_FALLTHROUGH; } case CallExprClass: case CXXMemberCallExprClass: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index c19812e341c0..17d0ce67dcf9 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -736,6 +736,7 @@ namespace { if (!HasFoldFailureDiagnostic) break; // We've already failed to fold something. Keep that diagnostic. + LLVM_FALLTHROUGH; case EM_ConstantExpression: case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: @@ -10374,6 +10375,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { } // OffsetOf falls through here. + LLVM_FALLTHROUGH; } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using @@ -10476,6 +10478,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { return Worst(LHSResult, RHSResult); } } + LLVM_FALLTHROUGH; } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 7db0b4d8e4ff..c9bb45a37eb5 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1459,8 +1459,6 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); - // __unaligned is not currently mangled in any way, so remove it. - MethodQuals.removeUnaligned(); mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); } @@ -2140,7 +2138,8 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { } void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { - // Vendor qualifiers come first. + // Vendor qualifiers come first and if they are order-insensitive they must + // be emitted in reversed alphabetical order, see Itanium ABI 5.1.5. // Address space qualifiers start with an ordinary letter. if (Quals.hasAddressSpace()) { @@ -2176,17 +2175,28 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { } // The ARC ownership qualifiers start with underscores. - switch (Quals.getObjCLifetime()) { // Objective-C ARC Extension: // // ::= U "__strong" // ::= U "__weak" // ::= U "__autoreleasing" + // + // Note: we emit __weak first to preserve the order as + // required by the Itanium ABI. + if (Quals.getObjCLifetime() == Qualifiers::OCL_Weak) + mangleVendorQualifier("__weak"); + + // __unaligned (from -fms-extensions) + if (Quals.hasUnaligned()) + mangleVendorQualifier("__unaligned"); + + // Remaining ARC ownership qualifiers. + switch (Quals.getObjCLifetime()) { case Qualifiers::OCL_None: break; case Qualifiers::OCL_Weak: - mangleVendorQualifier("__weak"); + // Do nothing as we already handled this case above. break; case Qualifiers::OCL_Strong: @@ -3775,6 +3785,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { Out << "v1U" << Kind.size() << Kind; } // Fall through to mangle the cast itself. + LLVM_FALLTHROUGH; case Expr::CStyleCastExprClass: mangleCastExpression(E, "cv"); @@ -4327,7 +4338,7 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { /// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { Qualifiers Qs = T.getQualifiers(); - return Qs.getCVRQualifiers() || Qs.hasAddressSpace(); + return Qs.getCVRQualifiers() || Qs.hasAddressSpace() || Qs.hasUnaligned(); } bool CXXNameMangler::mangleSubstitution(QualType T) { diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index 514c7c9f5b33..e2e0dbeec0dd 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -290,6 +290,7 @@ NestedNameSpecifier::print(raw_ostream &OS, case TypeSpecWithTemplate: OS << "template "; // Fall through to print the type. + LLVM_FALLTHROUGH; case TypeSpec: { const Type *T = getAsType(); diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index ed7193ecb437..60556697113a 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -441,6 +441,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return Ctx.IntTy; + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp index 614f676fb193..83b545a7be83 100644 --- a/lib/Analysis/PseudoConstantAnalysis.cpp +++ b/lib/Analysis/PseudoConstantAnalysis.cpp @@ -109,6 +109,7 @@ void PseudoConstantAnalysis::RunAnalysis() { // Do not visit the children continue; + LLVM_FALLTHROUGH; } case BO_AddAssign: case BO_SubAssign: diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp index 3b93f1a57f1f..534225985460 100644 --- a/lib/Analysis/ScanfFormatString.cpp +++ b/lib/Analysis/ScanfFormatString.cpp @@ -341,6 +341,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return ArgType::PtrTo(ArgType::AnyCharTy); + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } @@ -357,6 +358,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsShort: if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) return ArgType::PtrTo(ArgType::AnyCharTy); + LLVM_FALLTHROUGH; default: return ArgType::Invalid(); } diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 74c85376c7db..372e0c417fd4 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -551,6 +551,7 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) { case 's': if (startsWithWord(name, "shared")) return OIT_ReturnsSelf; if (startsWithWord(name, "standard")) return OIT_Singleton; + break; case 'i': if (startsWithWord(name, "init")) return OIT_Init; default: diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index c8a774311efe..db81507aa209 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -29,9 +29,7 @@ void LangOptions::resetNonModularOptions() { Name = Default; #include "clang/Basic/LangOptions.def" - // FIXME: This should not be reset; modules can be different with different - // sanitizer options (this affects __has_feature(address_sanitizer) etc). - Sanitize.clear(); + // These options do not affect AST generation. SanitizerBlacklistFiles.clear(); XRayAlwaysInstrumentFiles.clear(); XRayNeverInstrumentFiles.clear(); diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index ac3d7c559679..83c524877ab0 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -394,11 +394,30 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { {"exclude ", HK_Excluded}}; for (auto &K : Kinds) { + assert(&K == &Kinds[K.Kind] && "kinds in wrong order"); for (auto &H : Headers[K.Kind]) { OS.indent(Indent + 2); OS << K.Prefix << "header \""; OS.write_escaped(H.NameAsWritten); - OS << "\"\n"; + OS << "\" { size " << H.Entry->getSize() + << " mtime " << H.Entry->getModificationTime() << " }\n"; + } + } + for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) { + for (auto &U : *Unresolved) { + OS.indent(Indent + 2); + OS << Kinds[U.Kind].Prefix << "header \""; + OS.write_escaped(U.FileName); + OS << "\""; + if (U.Size || U.ModTime) { + OS << " {"; + if (U.Size) + OS << " size " << *U.Size; + if (U.ModTime) + OS << " mtime " << *U.ModTime; + OS << " }"; + } + OS << "\n"; } } diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index e19404dc54cb..8cfd8bde9cbb 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -143,9 +143,11 @@ const char *TargetInfo::getTypeConstantSuffix(IntType T) const { case UnsignedChar: if (getCharWidth() < getIntWidth()) return ""; + LLVM_FALLTHROUGH; case UnsignedShort: if (getShortWidth() < getIntWidth()) return ""; + LLVM_FALLTHROUGH; case UnsignedInt: return "U"; case UnsignedLong: return "UL"; case UnsignedLongLong: return "ULL"; diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 0f07169ac8b0..fd193bcf1a69 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -49,6 +49,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" @@ -186,6 +187,7 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, Opts.TracePC = CGOpts.SanitizeCoverageTracePC; Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard; Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune; + Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters; PM.add(createSanitizerCoverageModulePass(Opts)); } @@ -897,6 +899,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( // create that pass manager here and use it as needed below. legacy::PassManager CodeGenPasses; bool NeedCodeGen = false; + Optional ThinLinkOS; // Append any output we need to the pass manager. switch (Action) { @@ -904,9 +907,24 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( break; case Backend_EmitBC: - MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - CodeGenOpts.EmitSummaryIndex, - CodeGenOpts.EmitSummaryIndex)); + if (CodeGenOpts.EmitSummaryIndex) { + if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { + std::error_code EC; + ThinLinkOS.emplace(CodeGenOpts.ThinLinkBitcodeFile, EC, + llvm::sys::fs::F_None); + if (EC) { + Diags.Report(diag::err_fe_unable_to_open_output) + << CodeGenOpts.ThinLinkBitcodeFile << EC.message(); + return; + } + } + MPM.addPass( + ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &*ThinLinkOS : nullptr)); + } else { + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + CodeGenOpts.EmitSummaryIndex, + CodeGenOpts.EmitSummaryIndex)); + } break; case Backend_EmitLL: @@ -1029,6 +1047,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, Conf.CGOptLevel = getCGOptLevel(CGOpts); initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); Conf.SampleProfile = std::move(SampleProfile); + Conf.UseNewPM = CGOpts.ExperimentalNewPassManager; switch (Action) { case Backend_EmitNothing: Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) { diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 2134fb9e03e4..3b4f8854a9ca 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -2659,6 +2659,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), llvm::ArrayRef(Args))); } + LLVM_FALLTHROUGH; } // OpenCL v2.0 s6.13.17.6 - Kernel query functions need bitcast of block // parameter. @@ -3813,6 +3814,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vcalt_v: case NEON::BI__builtin_neon_vcaltq_v: std::swap(Ops[0], Ops[1]); + LLVM_FALLTHROUGH; case NEON::BI__builtin_neon_vcage_v: case NEON::BI__builtin_neon_vcageq_v: case NEON::BI__builtin_neon_vcagt_v: @@ -5056,6 +5058,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vsri_n_v: case NEON::BI__builtin_neon_vsriq_n_v: rightShift = true; + LLVM_FALLTHROUGH; case NEON::BI__builtin_neon_vsli_n_v: case NEON::BI__builtin_neon_vsliq_n_v: Ops[2] = EmitNeonShiftVector(Ops[2], Ty, rightShift); diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 8f405eee6e52..079064733585 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -4259,6 +4259,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Builder.CreateStore(elt, eltAddr); } // FALLTHROUGH + LLVM_FALLTHROUGH; } case ABIArgInfo::InAlloca: diff --git a/lib/CodeGen/CGCoroutine.cpp b/lib/CodeGen/CGCoroutine.cpp index f65fb5b9232a..bc5f6327c9a0 100644 --- a/lib/CodeGen/CGCoroutine.cpp +++ b/lib/CodeGen/CGCoroutine.cpp @@ -625,6 +625,7 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_id has" " been used earlier in this function"); // Fallthrough to the next case to add TokenNone as the first argument. + LLVM_FALLTHROUGH; } // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first // argument. diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 0a1dc09211c2..02db79159b58 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -2781,6 +2781,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { // them distinct if they are ODR-uniqued. if (FullName.empty()) break; + LLVM_FALLTHROUGH; case llvm::dwarf::DW_TAG_structure_type: case llvm::dwarf::DW_TAG_union_type: @@ -3263,7 +3264,7 @@ void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) { void CGDebugInfo::EmitInlineFunctionEnd(CGBuilderTy &Builder) { assert(CurInlinedAt && "unbalanced inline scope stack"); - EmitFunctionEnd(Builder); + EmitFunctionEnd(Builder, nullptr); setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt()); } @@ -3332,7 +3333,7 @@ void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, LexicalBlockStack.pop_back(); } -void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { +void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn) { assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); unsigned RCount = FnBeginRegionCount.back(); assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch"); @@ -3344,6 +3345,9 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { LexicalBlockStack.pop_back(); } FnBeginRegionCount.pop_back(); + + if (Fn && Fn->getSubprogram()) + DBuilder.finalizeSubprogram(Fn->getSubprogram()); } llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 7de48f278994..39249c7cf4da 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -367,7 +367,7 @@ class CGDebugInfo { void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType); /// Constructs the debug code for exiting a function. - void EmitFunctionEnd(CGBuilderTy &Builder); + void EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn); /// Emit metadata to indicate the beginning of a new lexical block /// and push the block onto the stack. diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 84ce896506d5..2aa045879213 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1487,9 +1487,9 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, // Handle vectors differently to get better performance. if (Ty->isVectorType()) { llvm::Type *SrcTy = Value->getType(); - auto *VecTy = cast(SrcTy); + auto *VecTy = dyn_cast(SrcTy); // Handle vec3 special. - if (VecTy->getNumElements() == 3) { + if (VecTy && VecTy->getNumElements() == 3) { // Our source is a vec3, do a shuffle vector to make it a vec4. llvm::Constant *Mask[] = {Builder.getInt32(0), Builder.getInt32(1), Builder.getInt32(2), diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index d604b4130a23..f9d1fe468748 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -3887,7 +3887,7 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, /// Return the result of the given binary operation. auto eval = [&](BinaryOperator::Opcode Opcode, llvm::Value *LHS, llvm::Value *RHS) -> llvm::Value * { - assert(Opcode == BO_Add || Opcode == BO_Mul && "Can't eval binop"); + assert((Opcode == BO_Add || Opcode == BO_Mul) && "Can't eval binop"); // If the operands are constants, return a constant result. if (auto *LHSCI = dyn_cast(LHS)) { diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 85da3ae47db0..b6d7f0255017 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -348,7 +348,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // Emit debug descriptor for function end. if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitFunctionEnd(Builder); + DI->EmitFunctionEnd(Builder, CurFn); // Reset the debug location to that of the simple 'return' expression, if any // rather than that of the end of the function's scope '}'. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index c61a5f6ffa71..dde8f2e36920 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -3841,6 +3841,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { // Skip variable templates if (cast(D)->getDescribedVarTemplate()) return; + LLVM_FALLTHROUGH; case Decl::VarTemplateSpecialization: EmitGlobal(cast(D)); if (auto *DD = dyn_cast(D)) diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 9ab2e176845c..ad2b4ada9a83 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -48,13 +48,14 @@ enum CoverageFeature { CoverageBB = 1 << 1, CoverageEdge = 1 << 2, CoverageIndirCall = 1 << 3, - CoverageTraceBB = 1 << 4, + CoverageTraceBB = 1 << 4, // Deprecated. CoverageTraceCmp = 1 << 5, CoverageTraceDiv = 1 << 6, CoverageTraceGep = 1 << 7, - Coverage8bitCounters = 1 << 8, + Coverage8bitCounters = 1 << 8, // Deprecated. CoverageTracePC = 1 << 9, CoverageTracePCGuard = 1 << 10, + CoverageInline8bitCounters = 1 << 12, CoverageNoPrune = 1 << 11, }; @@ -530,7 +531,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, } // trace-pc w/o func/bb/edge implies edge. - if ((CoverageFeatures & (CoverageTracePC | CoverageTracePCGuard)) && + if ((CoverageFeatures & + (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters)) && !(CoverageFeatures & InsertionPointTypes)) CoverageFeatures |= CoverageEdge; @@ -637,6 +639,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"), std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"), std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"), + std::make_pair(CoverageInline8bitCounters, "-fsanitize-coverage-inline-8bit-counters"), std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune")}; for (auto F : CoverageFlags) { if (CoverageFeatures & F.first) @@ -798,6 +801,7 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) { .Case("trace-pc", CoverageTracePC) .Case("trace-pc-guard", CoverageTracePCGuard) .Case("no-prune", CoverageNoPrune) + .Case("inline-8bit-counters", CoverageInline8bitCounters) .Default(0); if (F == 0) D.Diag(clang::diag::err_drv_unsupported_option_argument) diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp index 2148316532de..dc501b564eea 100644 --- a/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -798,24 +798,28 @@ static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, case NSAPI::NSNumberWithUnsignedInt: case NSAPI::NSNumberWithUnsignedInteger: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithInt: case NSAPI::NSNumberWithInteger: break; case NSAPI::NSNumberWithUnsignedLong: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithLong: CallIsLong = true; break; case NSAPI::NSNumberWithUnsignedLongLong: CallIsUnsigned = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithLongLong: CallIsLongLong = true; break; case NSAPI::NSNumberWithDouble: CallIsDouble = true; + LLVM_FALLTHROUGH; case NSAPI::NSNumberWithFloat: CallIsFloating = true; break; diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index a7b5fa7dfd29..e92672a785da 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -1727,6 +1727,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, diag::warn_module_config_mismatch) << ModuleFileName; // Fall through to error out. + LLVM_FALLTHROUGH; case ASTReader::VersionMismatch: case ASTReader::HadErrors: ModuleLoader::HadFatalFailure = true; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 47c763d29357..adb15f1730bf 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -768,6 +768,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeCoverageTracePCGuard = Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard); Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune); + Opts.SanitizeCoverageInline8bitCounters = + Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeMemoryUseAfterDtor = @@ -2700,6 +2702,13 @@ std::string CompilerInvocation::getModuleHash() const { code = ext->hashExtension(code); } + // Extend the signature with the enabled sanitizers, if at least one is + // enabled. Sanitizers which cannot affect AST generation aren't hashed. + SanitizerSet SanHash = LangOpts->Sanitize; + SanHash.clear(getPPTransparentSanitizers()); + if (!SanHash.empty()) + code = hash_combine(code, SanHash.Mask); + return llvm::APInt(64, code).toString(36, /*Signed=*/false); } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index cd67e469ddad..e2fbe965349f 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -289,14 +289,28 @@ static void addHeaderInclude(StringRef HeaderName, /// /// \param Includes Will be augmented with the set of \#includes or \#imports /// needed to load all of the named headers. -static std::error_code -collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, - ModuleMap &ModMap, clang::Module *Module, - SmallVectorImpl &Includes) { +static std::error_code collectModuleHeaderIncludes( + const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag, + ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl &Includes) { // Don't collect any headers for unavailable modules. if (!Module->isAvailable()) return std::error_code(); + // Resolve all lazy header directives to header files. + ModMap.resolveHeaderDirectives(Module); + + // If any headers are missing, we can't build this module. In most cases, + // diagnostics for this should have already been produced; we only get here + // if explicit stat information was provided. + // FIXME: If the name resolves to a file with different stat information, + // produce a better diagnostic. + if (!Module->MissingHeaders.empty()) { + auto &MissingHeader = Module->MissingHeaders.front(); + Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) + << MissingHeader.IsUmbrella << MissingHeader.FileName; + return std::error_code(); + } + // Add includes for each of these headers. for (auto HK : {Module::HK_Normal, Module::HK_Private}) { for (Module::Header &H : Module->Headers[HK]) { @@ -367,7 +381,7 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, SubEnd = Module->submodule_end(); Sub != SubEnd; ++Sub) if (std::error_code Err = collectModuleHeaderIncludes( - LangOpts, FileMgr, ModMap, *Sub, Includes)) + LangOpts, FileMgr, Diag, ModMap, *Sub, Includes)) return Err; return std::error_code(); @@ -494,7 +508,7 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) { addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, CI.getLangOpts(), M->IsExternC); Err = collectModuleHeaderIncludes( - CI.getLangOpts(), FileMgr, + CI.getLangOpts(), FileMgr, CI.getDiagnostics(), CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M, HeaderContents); diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index baaf93b167bc..89ac385ca45d 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -546,8 +546,11 @@ void PrintPreprocessedAction::ExecuteAction() { // module itself before switching to the input buffer. auto &Input = getCurrentInput(); if (Input.getKind().getFormat() == InputKind::ModuleMap) { - if (Input.isFile()) - (*OS) << "# 1 \"" << Input.getFile() << "\"\n"; + if (Input.isFile()) { + (*OS) << "# 1 \""; + OS->write_escaped(Input.getFile()); + (*OS) << "\"\n"; + } // FIXME: Include additional information here so that we don't need the // original source files to exist on disk. getCurrentModule()->print(*OS); diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index d50fb6d788a4..1d7c8a0c871b 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -221,6 +221,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, case llvm::Triple::Win32: if (triple.getEnvironment() != llvm::Triple::Cygnus) break; + LLVM_FALLTHROUGH; default: // FIXME: temporary hack: hard-coded paths. AddPath("/usr/local/include", System, false); @@ -343,6 +344,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, AddPath(BaseSDKPath + "/target/include", System, false); if (triple.isPS4CPU()) AddPath(BaseSDKPath + "/target/include_common", System, false); + LLVM_FALLTHROUGH; } default: AddPath("/usr/include", ExternCSystem, false); diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp index 8c5eb161b5ab..b2dfd2941130 100644 --- a/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/lib/Frontend/Rewrite/FrontendActions.cpp @@ -200,8 +200,11 @@ void RewriteIncludesAction::ExecuteAction() { // module itself before switching to the input buffer. auto &Input = getCurrentInput(); if (Input.getKind().getFormat() == InputKind::ModuleMap) { - if (Input.isFile()) - (*OS) << "# 1 \"" << Input.getFile() << "\"\n"; + if (Input.isFile()) { + (*OS) << "# 1 \""; + OS->write_escaped(Input.getFile()); + (*OS) << "\"\n"; + } // FIXME: Include additional information here so that we don't need the // original source files to exist on disk. getCurrentModule()->print(*OS); diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp index d45cbc01df8c..3564cebba8a8 100644 --- a/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -177,7 +177,9 @@ void InclusionRewriter::FileSkipped(const FileEntry &/*SkippedFile*/, /// directives. It does not say whether the file has been included, but it /// provides more information about the directive (hash location instead /// of location inside the included file). It is assumed that the matching -/// FileChanged() or FileSkipped() is called after this. +/// FileChanged() or FileSkipped() is called after this (or neither is +/// called if this #include results in an error or does not textually include +/// anything). void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, const Token &/*IncludeTok*/, StringRef /*FileName*/, @@ -187,9 +189,6 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, StringRef /*SearchPath*/, StringRef /*RelativePath*/, const Module *Imported) { - assert(LastInclusionLocation.isInvalid() && - "Another inclusion directive was found before the previous one " - "was processed"); if (Imported) { auto P = ModuleIncludes.insert( std::make_pair(HashLoc.getRawEncoding(), Imported)); diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp index c4461d452e7b..8a8161488f44 100644 --- a/lib/Frontend/SerializedDiagnosticReader.cpp +++ b/lib/Frontend/SerializedDiagnosticReader.cpp @@ -125,6 +125,7 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { case Cursor::BlockBegin: if (Stream.SkipBlock()) return SDError::MalformedMetadataBlock; + LLVM_FALLTHROUGH; case Cursor::BlockEnd: if (!VersionChecked) return SDError::MissingVersion; diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 9084bc352f76..1ebcc0a1c657 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -1114,6 +1114,8 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, auto TryEnterImported = [&](void) -> bool { if (!ModulesEnabled) return false; + // Ensure FileInfo bits are up to date. + ModMap.resolveHeaderDirectives(File); // Modules with builtins are special; multiple modules use builtins as // modular headers, example: // diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index f5a35e97d6e1..447ff212f06e 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -2498,6 +2498,7 @@ void Lexer::ReadToEndOfLine(SmallVectorImpl *Result) { break; } // FALL THROUGH. + LLVM_FALLTHROUGH; case '\r': case '\n': // Okay, we found the end of the line. First, back up past the \0, \r, \n. @@ -3247,6 +3248,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) { return LexCharConstant(Result, ConsumeChar(CurPtr, SizeTmp, Result), tok::wide_char_constant); // FALL THROUGH, treating L like the start of an identifier. + LLVM_FALLTHROUGH; // C99 6.4.2: Identifiers. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index 1e2cbde825f5..a598a467816a 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -456,10 +456,17 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, // Finally, we write the bytes into ResultBuf. ResultBuf += bytesToWrite; switch (bytesToWrite) { // note: everything falls through. - case 4: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 3: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 2: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 1: *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); + case 4: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 3: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 2: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 1: + *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); } // Update the buffer. ResultBuf += bytesToWrite; diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 8c57931e47b7..018d59e5e871 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -36,6 +36,37 @@ #endif using namespace clang; +Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { + switch ((int)Role) { + default: llvm_unreachable("unknown header role"); + case NormalHeader: + return Module::HK_Normal; + case PrivateHeader: + return Module::HK_Private; + case TextualHeader: + return Module::HK_Textual; + case PrivateHeader | TextualHeader: + return Module::HK_PrivateTextual; + } +} + +ModuleMap::ModuleHeaderRole +ModuleMap::headerKindToRole(Module::HeaderKind Kind) { + switch ((int)Kind) { + case Module::HK_Normal: + return NormalHeader; + case Module::HK_Private: + return PrivateHeader; + case Module::HK_Textual: + return TextualHeader; + case Module::HK_PrivateTextual: + return ModuleHeaderRole(PrivateHeader | TextualHeader); + case Module::HK_Excluded: + llvm_unreachable("unexpected header kind"); + } + llvm_unreachable("unknown header kind"); +} + Module::ExportDecl ModuleMap::resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, @@ -104,12 +135,22 @@ static void appendSubframeworkPaths(Module *Mod, } const FileEntry * -ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, - SmallVectorImpl &RelativePathName) { +ModuleMap::findHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header, + SmallVectorImpl &RelativePathName) { + auto GetFile = [&](StringRef Filename) -> const FileEntry * { + auto *File = SourceMgr.getFileManager().getFile(Filename); + if (!File || + (Header.Size && File->getSize() != *Header.Size) || + (Header.ModTime && File->getModificationTime() != *Header.ModTime)) + return nullptr; + return File; + }; + if (llvm::sys::path::is_absolute(Header.FileName)) { RelativePathName.clear(); RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); - return SourceMgr.getFileManager().getFile(Header.FileName); + return GetFile(Header.FileName); } // Search for the header file within the module's home directory. @@ -124,7 +165,7 @@ ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, // Check whether this file is in the public headers. llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - if (auto *File = SourceMgr.getFileManager().getFile(FullPathName)) + if (auto *File = GetFile(FullPathName)) return File; // Check whether this file is in the private headers. @@ -141,31 +182,74 @@ ModuleMap::resolveHeader(Module *M, Module::UnresolvedHeaderDirective Header, llvm::sys::path::append(RelativePathName, "PrivateHeaders", Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - return SourceMgr.getFileManager().getFile(FullPathName); + return GetFile(FullPathName); } // Lookup for normal headers. llvm::sys::path::append(RelativePathName, Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - return SourceMgr.getFileManager().getFile(FullPathName); + return GetFile(FullPathName); } -const FileEntry * -ModuleMap::resolveAsBuiltinHeader(Module *M, - Module::UnresolvedHeaderDirective Header, - SmallVectorImpl &BuiltinPathName) { - if (llvm::sys::path::is_absolute(Header.FileName) || M->isPartOfFramework() || - !M->IsSystem || Header.IsUmbrella || !BuiltinIncludeDir || - BuiltinIncludeDir == M->Directory || !isBuiltinHeader(Header.FileName)) - return nullptr; +void ModuleMap::resolveHeader(Module *Mod, + const Module::UnresolvedHeaderDirective &Header) { + SmallString<128> RelativePathName; + if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { + if (Header.IsUmbrella) { + const DirectoryEntry *UmbrellaDir = File->getDir(); + if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) + Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) + << UmbrellaMod->getFullModuleName(); + else + // Record this umbrella header. + setUmbrellaHeader(Mod, File, RelativePathName.str()); + } else { + Module::Header H = {RelativePathName.str(), File}; + if (Header.Kind == Module::HK_Excluded) + excludeHeader(Mod, H); + else + addHeader(Mod, H, headerKindToRole(Header.Kind)); + } + } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { + // There's a builtin header but no corresponding on-disk header. Assume + // this was supposed to modularize the builtin header alone. + } else if (Header.Kind == Module::HK_Excluded) { + // Ignore missing excluded header files. They're optional anyway. + } else { + // If we find a module that has a missing header, we mark this module as + // unavailable and store the header directive for displaying diagnostics. + Mod->MissingHeaders.push_back(Header); + // A missing header with stat information doesn't make the module + // unavailable; this keeps our behavior consistent as headers are lazily + // resolved. (Such a module still can't be built though, except from + // preprocessed source.) + if (!Header.Size && !Header.ModTime) + Mod->markUnavailable(); + } +} + +bool ModuleMap::resolveAsBuiltinHeader( + Module *Mod, const Module::UnresolvedHeaderDirective &Header) { + if (Header.Kind == Module::HK_Excluded || + llvm::sys::path::is_absolute(Header.FileName) || + Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || + !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || + !isBuiltinHeader(Header.FileName)) + return false; // This is a system module with a top-level header. This header // may have a counterpart (or replacement) in the set of headers // supplied by Clang. Find that builtin header. - llvm::sys::path::append(BuiltinPathName, BuiltinIncludeDir->getName(), - Header.FileName); - return SourceMgr.getFileManager().getFile( - StringRef(BuiltinPathName.data(), BuiltinPathName.size())); + SmallString<128> Path; + llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); + auto *File = SourceMgr.getFileManager().getFile(Path); + if (!File) + return false; + + auto Role = headerKindToRole(Header.Kind); + Module::Header H = {Path.str(), File}; + addHeader(Mod, H, Role); + return true; } ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, @@ -246,6 +330,7 @@ bool ModuleMap::isBuiltinHeader(StringRef FileName) { ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(const FileEntry *File) { + resolveHeaderDirectives(File); HeadersMap::iterator Known = Headers.find(File); if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && Known == Headers.end() && File->getDir() == BuiltinIncludeDir && @@ -328,8 +413,10 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) return; - if (RequestingModule) + if (RequestingModule) { resolveUses(RequestingModule, /*Complain=*/false); + resolveHeaderDirectives(RequestingModule); + } bool Excluded = false; Module *Private = nullptr; @@ -511,6 +598,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { ArrayRef ModuleMap::findAllModulesForHeader(const FileEntry *File) const { + resolveHeaderDirectives(File); auto It = Headers.find(File); if (It == Headers.end()) return None; @@ -524,6 +612,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { bool ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, const Module *RequestingModule) const { + resolveHeaderDirectives(Header); HeadersMap::const_iterator Known = Headers.find(Header); if (Known != Headers.end()) { for (SmallVectorImpl::const_iterator @@ -896,18 +985,63 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, UmbrellaDirs[UmbrellaDir] = Mod; } -static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) { - switch ((int)Role) { - default: llvm_unreachable("unknown header role"); - case ModuleMap::NormalHeader: - return Module::HK_Normal; - case ModuleMap::PrivateHeader: - return Module::HK_Private; - case ModuleMap::TextualHeader: - return Module::HK_Textual; - case ModuleMap::PrivateHeader | ModuleMap::TextualHeader: - return Module::HK_PrivateTextual; +void ModuleMap::addUnresolvedHeader(Module *Mod, + Module::UnresolvedHeaderDirective Header) { + // If there is a builtin counterpart to this file, add it now so it can + // wrap the system header. + if (resolveAsBuiltinHeader(Mod, Header)) { + // If we have both a builtin and system version of the file, the + // builtin version may want to inject macros into the system header, so + // force the system header to be treated as a textual header in this + // case. + Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( + headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); + Header.HasBuiltinHeader = true; } + + // If possible, don't stat the header until we need to. This requires the + // user to have provided us with some stat information about the file. + // FIXME: Add support for lazily stat'ing umbrella headers and excluded + // headers. + if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && + Header.Kind != Module::HK_Excluded) { + // We expect more variation in mtime than size, so if we're given both, + // use the mtime as the key. + if (Header.ModTime) + LazyHeadersByModTime[*Header.ModTime].push_back(Mod); + else + LazyHeadersBySize[*Header.Size].push_back(Mod); + Mod->UnresolvedHeaders.push_back(Header); + return; + } + + // We don't have stat information or can't defer looking this file up. + // Perform the lookup now. + resolveHeader(Mod, Header); +} + +void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { + auto BySize = LazyHeadersBySize.find(File->getSize()); + if (BySize != LazyHeadersBySize.end()) { + for (auto *M : BySize->second) + resolveHeaderDirectives(M); + LazyHeadersBySize.erase(BySize); + } + + auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); + if (ByModTime != LazyHeadersByModTime.end()) { + for (auto *M : ByModTime->second) + resolveHeaderDirectives(M); + LazyHeadersByModTime.erase(ByModTime); + } +} + +void ModuleMap::resolveHeaderDirectives(Module *Mod) const { + for (auto &Header : Mod->UnresolvedHeaders) + // This operation is logically const; we're just changing how we represent + // the header information for this file. + const_cast(this)->resolveHeader(Mod, Header); + Mod->UnresolvedHeaders.clear(); } void ModuleMap::addHeader(Module *Mod, Module::Header Header, @@ -1063,6 +1197,7 @@ namespace clang { RequiresKeyword, Star, StringLiteral, + IntegerLiteral, TextualKeyword, LBrace, RBrace, @@ -1072,7 +1207,12 @@ namespace clang { unsigned Location; unsigned StringLength; - const char *StringData; + union { + // If Kind != IntegerLiteral. + const char *StringData; + // If Kind == IntegerLiteral. + uint64_t IntegerValue; + }; void clear() { Kind = EndOfFile; @@ -1086,9 +1226,14 @@ namespace clang { SourceLocation getLocation() const { return SourceLocation::getFromRawEncoding(Location); } + + uint64_t getInteger() const { + return Kind == IntegerLiteral ? IntegerValue : 0; + } StringRef getString() const { - return StringRef(StringData, StringLength); + return Kind == IntegerLiteral ? StringRef() + : StringRef(StringData, StringLength); } }; @@ -1278,6 +1423,25 @@ SourceLocation ModuleMapParser::consumeToken() { Tok.StringLength = Length; break; } + + case tok::numeric_constant: { + // We don't support any suffixes or other complications. + SmallString<32> SpellingBuffer; + SpellingBuffer.resize(LToken.getLength() + 1); + const char *Start = SpellingBuffer.data(); + unsigned Length = + Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); + uint64_t Value; + if (StringRef(Start, Length).getAsInteger(0, Value)) { + Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); + HadError = true; + goto retry; + } + + Tok.Kind = MMToken::IntegerLiteral; + Tok.IntegerValue = Value; + break; + } case tok::comment: goto retry; @@ -1904,6 +2068,9 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, Header.FileName = Tok.getString(); Header.FileNameLoc = consumeToken(); Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; + Header.Kind = + (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded + : Map.headerRoleToKind(Role)); // Check whether we already have an umbrella. if (Header.IsUmbrella && ActiveModule->Umbrella) { @@ -1913,64 +2080,62 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, return; } - // Look for this file by name if we don't have any stat information. - SmallString<128> RelativePathName, BuiltinPathName; - const FileEntry *File = - Map.resolveHeader(ActiveModule, Header, RelativePathName); - const FileEntry *BuiltinFile = - Map.resolveAsBuiltinHeader(ActiveModule, Header, BuiltinPathName); + // If we were given stat information, parse it so we can skip looking for + // the file. + if (Tok.is(MMToken::LBrace)) { + SourceLocation LBraceLoc = consumeToken(); - // If Clang supplies this header but the underlying system does not, - // just silently swap in our builtin version. Otherwise, we'll end - // up adding both (later). - if (BuiltinFile && !File) { - RelativePathName = BuiltinPathName; - File = BuiltinFile; - BuiltinFile = nullptr; - } + while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { + enum Attribute { Size, ModTime, Unknown }; + StringRef Str = Tok.getString(); + SourceLocation Loc = consumeToken(); + switch (llvm::StringSwitch(Str) + .Case("size", Size) + .Case("mtime", ModTime) + .Default(Unknown)) { + case Size: + if (Header.Size) + Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; + if (!Tok.is(MMToken::IntegerLiteral)) { + Diags.Report(Tok.getLocation(), + diag::err_mmap_invalid_header_attribute_value) << Str; + skipUntil(MMToken::RBrace); + break; + } + Header.Size = Tok.getInteger(); + consumeToken(); + break; - // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. - // Come up with a lazy way to do this. - if (File) { - if (Header.IsUmbrella) { - const DirectoryEntry *UmbrellaDir = File->getDir(); - if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { - Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash) - << UmbrellaModule->getFullModuleName(); - HadError = true; - } else { - // Record this umbrella header. - Map.setUmbrellaHeader(ActiveModule, File, RelativePathName.str()); + case ModTime: + if (Header.ModTime) + Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; + if (!Tok.is(MMToken::IntegerLiteral)) { + Diags.Report(Tok.getLocation(), + diag::err_mmap_invalid_header_attribute_value) << Str; + skipUntil(MMToken::RBrace); + break; + } + Header.ModTime = Tok.getInteger(); + consumeToken(); + break; + + case Unknown: + Diags.Report(Loc, diag::err_mmap_expected_header_attribute); + skipUntil(MMToken::RBrace); + break; } - } else if (LeadingToken == MMToken::ExcludeKeyword) { - Module::Header H = {RelativePathName.str(), File}; - Map.excludeHeader(ActiveModule, H); - } else { - // If there is a builtin counterpart to this file, add it now so it can - // wrap the system header. - if (BuiltinFile) { - Module::Header H = { BuiltinPathName.str(), BuiltinFile }; - Map.addHeader(ActiveModule, H, Role); - - // If we have both a builtin and system version of the file, the - // builtin version may want to inject macros into the system header, so - // force the system header to be treated as a textual header in this - // case. - Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); - } - - // Record this header. - Module::Header H = { RelativePathName.str(), File }; - Map.addHeader(ActiveModule, H, Role); } - } else if (LeadingToken != MMToken::ExcludeKeyword) { - // Ignore excluded header files. They're optional anyway. - // If we find a module that has a missing header, we mark this module as - // unavailable and store the header directive for displaying diagnostics. - ActiveModule->markUnavailable(); - ActiveModule->MissingHeaders.push_back(Header); + if (Tok.is(MMToken::RBrace)) + consumeToken(); + else { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); + Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); + HadError = true; + } } + + Map.addUnresolvedHeader(ActiveModule, std::move(Header)); } static int compareModuleHeaders(const Module::Header *A, @@ -2521,6 +2686,7 @@ bool ModuleMapParser::parseModuleMapFile() { case MMToken::RequiresKeyword: case MMToken::Star: case MMToken::StringLiteral: + case MMToken::IntegerLiteral: case MMToken::TextualKeyword: case MMToken::UmbrellaKeyword: case MMToken::UseKeyword: diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 8b5877934f61..2d3ad690987e 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -689,6 +689,8 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, while (!Loc.isInvalid() && !SM.isInMainFile(Loc)) { auto ID = SM.getFileID(SM.getExpansionLoc(Loc)); auto *FE = SM.getFileEntryForID(ID); + if (!FE) + break; bool InTextualHeader = false; for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b785f5f7d2e6..22696a957a10 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2552,6 +2552,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, } } // Fall through. + LLVM_FALLTHROUGH; } case tok::comma: case tok::equal: @@ -3678,6 +3679,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = true; break; }; + LLVM_FALLTHROUGH; case tok::kw___private: case tok::kw___global: case tok::kw___local: @@ -5045,6 +5047,7 @@ void Parser::ParseTypeQualifierListOpt( if (TryKeywordIdentFallback(false)) continue; } + LLVM_FALLTHROUGH; case tok::kw___sptr: case tok::kw___w64: case tok::kw___ptr64: @@ -5094,6 +5097,7 @@ void Parser::ParseTypeQualifierListOpt( continue; // do *not* consume the next token! } // otherwise, FALL THROUGH! + LLVM_FALLTHROUGH; default: DoneWithTypeQuals: // If this is not a type-qualifier token, we're done reading type diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 527d45b1e203..4c117f531ef1 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -4215,6 +4215,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. + LLVM_FALLTHROUGH; case IEB_Skip: Braces.skipToEnd(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index c739a50f0b38..aacb00e8be64 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1314,6 +1314,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } // Fall through to treat the template-id as an id-expression. + LLVM_FALLTHROUGH; } case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id @@ -1484,9 +1485,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { nullptr, LHS.get()); break; } - // Fall through; this isn't a message send. - + LLVM_FALLTHROUGH; + default: // Not a postfix-expression suffix. return LHS; case tok::l_square: { // postfix-expression: p-e '[' expression ']' diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index f48d01e0f630..90f3561cb963 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -501,7 +501,8 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. - + LLVM_FALLTHROUGH; + case IEB_Skip: Braces.skipToEnd(); return false; diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index b925dd7053dc..2e5e36242ed5 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -192,6 +192,7 @@ static DeclarationName parseOpenMPReductionId(Parser &P) { case tok::identifier: // identifier if (!WithOperator) break; + LLVM_FALLTHROUGH; default: P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, @@ -869,6 +870,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( // pseudo-clause OMPFlushClause. PP.EnterToken(Tok); } + LLVM_FALLTHROUGH; case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -883,6 +885,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( } HasAssociatedStatement = false; // Fall through for further analysis. + LLVM_FALLTHROUGH; case OMPD_parallel: case OMPD_simd: case OMPD_for: @@ -1184,6 +1187,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } + LLVM_FALLTHROUGH; case OMPC_if: Clause = ParseOpenMPSingleExprWithArgClause(CKind); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index d147ab0a5674..b1fbb20c721b 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -203,6 +203,7 @@ Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts, } // Fall through + LLVM_FALLTHROUGH; } default: { diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 0d783131dd6e..d6684c39aa73 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -1450,6 +1450,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::False; } // If that succeeded, fallthrough into the generic simple-type-id case. + LLVM_FALLTHROUGH; // The ambiguity resides in a simple-type-specifier/typename-specifier // followed by a '('. The '(' could either be the start of: @@ -1492,6 +1493,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::True; } + LLVM_FALLTHROUGH; case tok::kw_char: case tok::kw_wchar_t: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4fe038d271ad..af29b5e9c673 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -763,6 +763,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, } // This must be 'export template'. Parse it so we can diagnose our lack // of support. + LLVM_FALLTHROUGH; case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -1875,6 +1876,7 @@ bool Parser::isTokenEqualOrEqualTypo() { Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal) << Kind << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); + LLVM_FALLTHROUGH; case tok::equal: return true; } diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp index 27bb976a6e1a..9e307f31be11 100644 --- a/lib/Rewrite/HTMLRewrite.cpp +++ b/lib/Rewrite/HTMLRewrite.cpp @@ -409,6 +409,7 @@ void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) { ++TokOffs; --TokLen; // FALL THROUGH to chop the 8 + LLVM_FALLTHROUGH; case tok::wide_string_literal: case tok::utf16_string_literal: case tok::utf32_string_literal: diff --git a/lib/Sema/CoroutineStmtBuilder.h b/lib/Sema/CoroutineStmtBuilder.h index 954a0f100ebb..33a368d92ff4 100644 --- a/lib/Sema/CoroutineStmtBuilder.h +++ b/lib/Sema/CoroutineStmtBuilder.h @@ -51,6 +51,9 @@ class CoroutineStmtBuilder : public CoroutineBodyStmt::CtorArgs { /// name lookup. bool buildDependentStatements(); + /// \brief Build just parameter moves. To use for rebuilding in TreeTransform. + bool buildParameterMoves(); + bool isInvalid() const { return !this->IsValid; } private: diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 8fb2f4139236..224d9e9a0ee2 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1866,6 +1866,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, case Sema::PCC_Condition: AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); // Fall through: conditions and statements can have expressions. + LLVM_FALLTHROUGH; case Sema::PCC_ParenthesizedExpression: if (SemaRef.getLangOpts().ObjCAutoRefCount && @@ -1895,6 +1896,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); } // Fall through + LLVM_FALLTHROUGH; case Sema::PCC_Expression: { if (SemaRef.getLangOpts().CPlusPlus) { diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index 8a548c0ab861..06ae66076e8a 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -832,6 +832,12 @@ bool CoroutineStmtBuilder::buildDependentStatements() { return this->IsValid; } +bool CoroutineStmtBuilder::buildParameterMoves() { + assert(this->IsValid && "coroutine already invalid"); + assert(this->ParamMoves.empty() && "param moves already built"); + return this->IsValid = makeParamMoves(); +} + bool CoroutineStmtBuilder::makePromiseStmt() { // Form a declaration statement for the promise declaration, so that AST // visitors can more easily find it. @@ -1244,14 +1250,13 @@ static Expr *castForMoving(Sema &S, Expr *E, QualType T = QualType()) { .get(); } + /// \brief Build a variable declaration for move parameter. static VarDecl *buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, - StringRef Name) { - DeclContext *DC = S.CurContext; - IdentifierInfo *II = &S.PP.getIdentifierTable().get(Name); + IdentifierInfo *II) { TypeSourceInfo *TInfo = S.Context.getTrivialTypeSourceInfo(Type, Loc); VarDecl *Decl = - VarDecl::Create(S.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); + VarDecl::Create(S.Context, S.CurContext, Loc, Loc, II, Type, TInfo, SC_None); Decl->setImplicit(); return Decl; } @@ -1264,9 +1269,6 @@ bool CoroutineStmtBuilder::makeParamMoves() { // No need to copy scalars, llvm will take care of them. if (Ty->getAsCXXRecordDecl()) { - if (!paramDecl->getIdentifier()) - continue; - ExprResult ParamRef = S.BuildDeclRefExpr(paramDecl, paramDecl->getType(), ExprValueKind::VK_LValue, Loc); // FIXME: scope? @@ -1275,8 +1277,7 @@ bool CoroutineStmtBuilder::makeParamMoves() { Expr *RCast = castForMoving(S, ParamRef.get()); - auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()->getName()); - + auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()); S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true); // Convert decl to a statement. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ea1f7526a832..ef6dfaa2f28c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -404,6 +404,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, } } // If typo correction failed or was not performed, fall through + LLVM_FALLTHROUGH; case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: Result.suppressDiagnostics(); @@ -6160,7 +6161,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( QualType NR = R; while (NR->isPointerType()) { if (NR->isFunctionPointerType()) { - Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer_variable); + Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); D.setInvalidType(); break; } @@ -12309,7 +12310,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, TypeSourceInfo *TI = FD->getTypeSourceInfo(); TypeLoc TL = TI->getTypeLoc(); FunctionTypeLoc FTL = TL.getAsAdjusted(); - Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1; + Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 2; } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d9528be2d383..acacdc263c08 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -14639,6 +14639,7 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { case EST_ComputedNoexcept: if (!Finder.TraverseStmt(Proto->getNoexceptExpr())) return true; + LLVM_FALLTHROUGH; case EST_Dynamic: for (const auto &E : Proto->exceptions()) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index b1a07ffb7206..4e7fb19b282b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -11462,6 +11462,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BO_And: checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc); + LLVM_FALLTHROUGH; case BO_Xor: case BO_Or: ResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc); @@ -11504,6 +11505,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, case BO_AndAssign: case BO_OrAssign: // fallthrough DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc); + LLVM_FALLTHROUGH; case BO_XorAssign: CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc); CompLHSTy = CompResultTy; diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 4b1d7fd3cf23..a6239283b47b 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -337,6 +337,7 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC, return nullptr; } // Fall through to get the current context. + LLVM_FALLTHROUGH; case DataMember: // -- the in-class initializers of class members diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index c97da740e4d2..1d32e5796812 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2594,6 +2594,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { for (const auto &Arg : Proto->param_types()) Queue.push_back(Arg.getTypePtr()); // fallthrough + LLVM_FALLTHROUGH; } case Type::FunctionNoProto: { const FunctionType *FnType = cast(T); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 33a8f9c4afa3..dcb2c11c73c7 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1288,17 +1288,22 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, } namespace { + // Use SetVector since the diagnostic cares about the ordering of the Decl's. + using DeclSetVector = + llvm::SetVector, + llvm::SmallPtrSet>; + // This visitor will traverse a conditional statement and store all // the evaluated decls into a vector. Simple is set to true if none // of the excluded constructs are used. class DeclExtractor : public EvaluatedExprVisitor { - llvm::SmallPtrSetImpl &Decls; + DeclSetVector &Decls; SmallVectorImpl &Ranges; bool Simple; public: typedef EvaluatedExprVisitor Inherited; - DeclExtractor(Sema &S, llvm::SmallPtrSetImpl &Decls, + DeclExtractor(Sema &S, DeclSetVector &Decls, SmallVectorImpl &Ranges) : Inherited(S.Context), Decls(Decls), @@ -1370,14 +1375,13 @@ namespace { // DeclMatcher checks to see if the decls are used in a non-evaluated // context. class DeclMatcher : public EvaluatedExprVisitor { - llvm::SmallPtrSetImpl &Decls; + DeclSetVector &Decls; bool FoundDecl; public: typedef EvaluatedExprVisitor Inherited; - DeclMatcher(Sema &S, llvm::SmallPtrSetImpl &Decls, - Stmt *Statement) : + DeclMatcher(Sema &S, DeclSetVector &Decls, Stmt *Statement) : Inherited(S.Context), Decls(Decls), FoundDecl(false) { if (!Statement) return; @@ -1459,7 +1463,7 @@ namespace { return; PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body); - llvm::SmallPtrSet Decls; + DeclSetVector Decls; SmallVector Ranges; DeclExtractor DE(S, Decls, Ranges); DE.Visit(Second); @@ -1471,11 +1475,9 @@ namespace { if (Decls.size() == 0) return; // Don't warn on volatile, static, or global variables. - for (llvm::SmallPtrSetImpl::iterator I = Decls.begin(), - E = Decls.end(); - I != E; ++I) - if ((*I)->getType().isVolatileQualified() || - (*I)->hasGlobalStorage()) return; + for (auto *VD : Decls) + if (VD->getType().isVolatileQualified() || VD->hasGlobalStorage()) + return; if (DeclMatcher(S, Decls, Second).FoundDeclInUse() || DeclMatcher(S, Decls, Third).FoundDeclInUse() || @@ -1483,25 +1485,16 @@ namespace { return; // Load decl names into diagnostic. - if (Decls.size() > 4) + if (Decls.size() > 4) { PDiag << 0; - else { - PDiag << Decls.size(); - for (llvm::SmallPtrSetImpl::iterator I = Decls.begin(), - E = Decls.end(); - I != E; ++I) - PDiag << (*I)->getDeclName(); + } else { + PDiag << (unsigned)Decls.size(); + for (auto *VD : Decls) + PDiag << VD->getDeclName(); } - // Load SourceRanges into diagnostic if there is room. - // Otherwise, load the SourceRange of the conditional expression. - if (Ranges.size() <= PartialDiagnostic::MaxArguments) - for (SmallVectorImpl::iterator I = Ranges.begin(), - E = Ranges.end(); - I != E; ++I) - PDiag << *I; - else - PDiag << Second->getSourceRange(); + for (auto Range : Ranges) + PDiag << Range; S.Diag(Ranges.begin()->getBegin(), PDiag); } diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 5f91cac14a38..c182b35bfad4 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -277,6 +277,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); + LLVM_FALLTHROUGH; default: return StmtError(Diag(OutputExpr->getLocStart(), diag::err_asm_invalid_lvalue_in_output) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index ebdf6dd57fc5..75b69ae04f56 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2383,7 +2383,8 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( bool HasDefaultArg = false; TemplateDecl *TD = dyn_cast(Template); if (!TD) { - assert(isa(Template)); + assert(isa(Template) || + isa(Template)); return Sema::TDK_Incomplete; } @@ -5093,6 +5094,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, cast(T)->getSizeExpr(), OnlyDeduced, Depth, Used); // Fall through to check the element type + LLVM_FALLTHROUGH; case Type::ConstantArray: case Type::IncompleteArray: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index e7315934b515..c189112e3455 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -643,6 +643,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough + LLVM_FALLTHROUGH; FUNCTION_TYPE_ATTRS_CASELIST: distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType); @@ -1881,6 +1882,11 @@ QualType Sema::BuildPointerType(QualType T, return QualType(); } + if (T->isFunctionType() && getLangOpts().OpenCL) { + Diag(Loc, diag::err_opencl_function_pointer); + return QualType(); + } + if (checkQualifiedFunction(*this, T, Loc, QFK_Pointer)) return QualType(); @@ -4347,19 +4353,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (FTI.isAmbiguous) warnAboutAmbiguousFunction(S, D, DeclType, T); - // GNU warning -Wstrict-prototypes - // Warn if a function declaration is without a prototype. - // This warning is issued for all kinds of unprototyped function - // declarations (i.e. function type typedef, function pointer etc.) - // C99 6.7.5.3p14: - // The empty list in a function declarator that is not part of a - // definition of that function specifies that no information - // about the number or types of the parameters is supplied. - if (D.getFunctionDefinitionKind() == FDK_Declaration && - FTI.NumParams == 0 && !LangOpts.CPlusPlus) - S.Diag(DeclType.Loc, diag::warn_strict_prototypes) - << 0 << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void"); - FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) { @@ -4602,6 +4595,36 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, const_cast(DeclType.getAttrs())); } + // GNU warning -Wstrict-prototypes + // Warn if a function declaration is without a prototype. + // This warning is issued for all kinds of unprototyped function + // declarations (i.e. function type typedef, function pointer etc.) + // C99 6.7.5.3p14: + // The empty list in a function declarator that is not part of a definition + // of that function specifies that no information about the number or types + // of the parameters is supplied. + if (!LangOpts.CPlusPlus && D.getFunctionDefinitionKind() == FDK_Declaration) { + bool IsBlock = false; + for (const DeclaratorChunk &DeclType : D.type_objects()) { + switch (DeclType.Kind) { + case DeclaratorChunk::BlockPointer: + IsBlock = true; + break; + case DeclaratorChunk::Function: { + const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + if (FTI.NumParams == 0) + S.Diag(DeclType.Loc, diag::warn_strict_prototypes) + << IsBlock + << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void"); + IsBlock = false; + break; + } + default: + break; + } + } + } + assert(!T.isNull() && "T must not be null after this point"); if (LangOpts.CPlusPlus && T->isFunctionType()) { @@ -6925,6 +6948,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough into the function attrs + LLVM_FALLTHROUGH; FUNCTION_TYPE_ATTRS_CASELIST: attr.setUsedAsTypeAttr(); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index a65584e3c912..7aa8f64d5081 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -6959,6 +6959,8 @@ TreeTransform::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { Builder.ReturnStmt = Res.get(); } } + if (!Builder.buildParameterMoves()) + return StmtError(); return getDerived().RebuildCoroutineBodyStmt(Builder); } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index b7bbb9dc7be1..e16a9b3ee3b5 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -292,6 +292,33 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, return true; } + // Sanitizer feature mismatches are treated as compatible differences. If + // compatible differences aren't allowed, we still only want to check for + // mismatches of non-modular sanitizers (the only ones which can affect AST + // generation). + if (!AllowCompatibleDifferences) { + SanitizerMask ModularSanitizers = getPPTransparentSanitizers(); + SanitizerSet ExistingSanitizers = ExistingLangOpts.Sanitize; + SanitizerSet ImportedSanitizers = LangOpts.Sanitize; + ExistingSanitizers.clear(ModularSanitizers); + ImportedSanitizers.clear(ModularSanitizers); + if (ExistingSanitizers.Mask != ImportedSanitizers.Mask) { + const std::string Flag = "-fsanitize="; + if (Diags) { +#define SANITIZER(NAME, ID) \ + { \ + bool InExistingModule = ExistingSanitizers.has(SanitizerKind::ID); \ + bool InImportedModule = ImportedSanitizers.has(SanitizerKind::ID); \ + if (InExistingModule != InImportedModule) \ + Diags->Report(diag::err_pch_targetopt_feature_mismatch) \ + << InExistingModule << (Flag + NAME); \ + } +#include "clang/Basic/Sanitizers.def" + } + return true; + } + } + return false; } @@ -3670,6 +3697,8 @@ static void updateModuleTimestamp(ModuleFile &MF) { if (EC) return; OS << "Timestamp file\n"; + OS.close(); + OS.clear_error(); // Avoid triggering a fatal error. } /// \brief Given a cursor at the start of an AST file, scan ahead and drop the diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 95cb54f944e4..044a26433a93 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1856,24 +1856,31 @@ namespace { // Trait used for the on-disk hash table of header search information. class HeaderFileInfoTrait { ASTWriter &Writer; - const HeaderSearch &HS; // Keep track of the framework names we've used during serialization. SmallVector FrameworkStringData; llvm::StringMap FrameworkNameOffset; public: - HeaderFileInfoTrait(ASTWriter &Writer, const HeaderSearch &HS) - : Writer(Writer), HS(HS) { } - + HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {} + struct key_type { - const FileEntry *FE; StringRef Filename; + off_t Size; + time_t ModTime; }; typedef const key_type &key_type_ref; + + using UnresolvedModule = + llvm::PointerIntPair; - typedef HeaderFileInfo data_type; + struct data_type { + const HeaderFileInfo &HFI; + ArrayRef KnownHeaders; + UnresolvedModule Unresolved; + }; typedef const data_type &data_type_ref; + typedef unsigned hash_value_type; typedef unsigned offset_type; @@ -1881,8 +1888,7 @@ namespace { // The hash is based only on size/time of the file, so that the reader can // match even when symlinking or excess path elements ("foo/../", "../") // change the form of the name. However, complete path is still the key. - return llvm::hash_combine(key.FE->getSize(), - Writer.getTimestampForOutput(key.FE)); + return llvm::hash_combine(key.Size, key.ModTime); } std::pair @@ -1892,68 +1898,74 @@ namespace { unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; - for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) + for (auto ModInfo : Data.KnownHeaders) if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) DataLen += 4; + if (Data.Unresolved.getPointer()) + DataLen += 4; LE.write(DataLen); return std::make_pair(KeyLen, DataLen); } - + void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { using namespace llvm::support; endian::Writer LE(Out); - LE.write(key.FE->getSize()); + LE.write(key.Size); KeyLen -= 8; - LE.write(Writer.getTimestampForOutput(key.FE)); + LE.write(key.ModTime); KeyLen -= 8; Out.write(key.Filename.data(), KeyLen); } - + void EmitData(raw_ostream &Out, key_type_ref key, data_type_ref Data, unsigned DataLen) { using namespace llvm::support; endian::Writer LE(Out); uint64_t Start = Out.tell(); (void)Start; - unsigned char Flags = (Data.isImport << 4) - | (Data.isPragmaOnce << 3) - | (Data.DirInfo << 1) - | Data.IndexHeaderMapHeader; + unsigned char Flags = (Data.HFI.isImport << 4) + | (Data.HFI.isPragmaOnce << 3) + | (Data.HFI.DirInfo << 1) + | Data.HFI.IndexHeaderMapHeader; LE.write(Flags); - LE.write(Data.NumIncludes); + LE.write(Data.HFI.NumIncludes); - if (!Data.ControllingMacro) - LE.write(Data.ControllingMacroID); + if (!Data.HFI.ControllingMacro) + LE.write(Data.HFI.ControllingMacroID); else - LE.write(Writer.getIdentifierRef(Data.ControllingMacro)); - + LE.write(Writer.getIdentifierRef(Data.HFI.ControllingMacro)); + unsigned Offset = 0; - if (!Data.Framework.empty()) { + if (!Data.HFI.Framework.empty()) { // If this header refers into a framework, save the framework name. llvm::StringMap::iterator Pos - = FrameworkNameOffset.find(Data.Framework); + = FrameworkNameOffset.find(Data.HFI.Framework); if (Pos == FrameworkNameOffset.end()) { Offset = FrameworkStringData.size() + 1; - FrameworkStringData.append(Data.Framework.begin(), - Data.Framework.end()); + FrameworkStringData.append(Data.HFI.Framework.begin(), + Data.HFI.Framework.end()); FrameworkStringData.push_back(0); - FrameworkNameOffset[Data.Framework] = Offset; + FrameworkNameOffset[Data.HFI.Framework] = Offset; } else Offset = Pos->second; } LE.write(Offset); - // FIXME: If the header is excluded, we should write out some - // record of that fact. - for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) { - if (uint32_t ModID = - Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) { - uint32_t Value = (ModID << 2) | (unsigned)ModInfo.getRole(); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { + if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { + uint32_t Value = (ModID << 2) | (unsigned)Role; assert((Value >> 2) == ModID && "overflow in header module info"); LE.write(Value); } - } + }; + + // FIXME: If the header is excluded, we should write out some + // record of that fact. + for (auto ModInfo : Data.KnownHeaders) + EmitModule(ModInfo.getModule(), ModInfo.getRole()); + if (Data.Unresolved.getPointer()) + EmitModule(Data.Unresolved.getPointer(), Data.Unresolved.getInt()); assert(Out.tell() - Start == DataLen && "Wrong data length"); } @@ -1968,16 +1980,72 @@ namespace { /// /// \param HS The header search structure to save. void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { + HeaderFileInfoTrait GeneratorTrait(*this); + llvm::OnDiskChainedHashTableGenerator Generator; + SmallVector SavedStrings; + unsigned NumHeaderSearchEntries = 0; + + // Find all unresolved headers for the current module. We generally will + // have resolved them before we get here, but not necessarily: we might be + // compiling a preprocessed module, where there is no requirement for the + // original files to exist any more. + const HeaderFileInfo Empty; // So we can take a reference. + if (WritingModule) { + llvm::SmallVector Worklist(1, WritingModule); + while (!Worklist.empty()) { + Module *M = Worklist.pop_back_val(); + if (!M->isAvailable()) + continue; + + // Map to disk files where possible, to pick up any missing stat + // information. This also means we don't need to check the unresolved + // headers list when emitting resolved headers in the first loop below. + // FIXME: It'd be preferable to avoid doing this if we were given + // sufficient stat information in the module map. + HS.getModuleMap().resolveHeaderDirectives(M); + + // If the file didn't exist, we can still create a module if we were given + // enough information in the module map. + for (auto U : M->MissingHeaders) { + // Check that we were given enough information to build a module + // without this file existing on disk. + if (!U.Size || (!U.ModTime && IncludeTimestamps)) { + PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header) + << WritingModule->getFullModuleName() << U.Size.hasValue() + << U.FileName; + continue; + } + + // Form the effective relative pathname for the file. + SmallString<128> Filename(M->Directory->getName()); + llvm::sys::path::append(Filename, U.FileName); + PreparePathForOutput(Filename); + + StringRef FilenameDup = strdup(Filename.c_str()); + SavedStrings.push_back(FilenameDup.data()); + + HeaderFileInfoTrait::key_type Key = { + FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0 + }; + HeaderFileInfoTrait::data_type Data = { + Empty, {}, {M, ModuleMap::headerKindToRole(U.Kind)} + }; + // FIXME: Deal with cases where there are multiple unresolved header + // directives in different submodules for the same header. + Generator.insert(Key, Data, GeneratorTrait); + ++NumHeaderSearchEntries; + } + + Worklist.append(M->submodule_begin(), M->submodule_end()); + } + } + SmallVector FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); if (FilesByUID.size() > HS.header_file_size()) FilesByUID.resize(HS.header_file_size()); - - HeaderFileInfoTrait GeneratorTrait(*this, HS); - llvm::OnDiskChainedHashTableGenerator Generator; - SmallVector SavedStrings; - unsigned NumHeaderSearchEntries = 0; + for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { const FileEntry *File = FilesByUID[UID]; if (!File) @@ -2004,11 +2072,16 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { SavedStrings.push_back(Filename.data()); } - HeaderFileInfoTrait::key_type key = { File, Filename }; - Generator.insert(key, *HFI, GeneratorTrait); + HeaderFileInfoTrait::key_type Key = { + Filename, File->getSize(), getTimestampForOutput(File) + }; + HeaderFileInfoTrait::data_type Data = { + *HFI, HS.getModuleMap().findAllModulesForHeader(File), {} + }; + Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; } - + // Create the on-disk hash table in a buffer. SmallString<4096> TableData; uint32_t BucketOffset; diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index 8ca2a24cffe7..f7b5f61cfb8a 100644 --- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -189,6 +189,7 @@ class DeadStoreObs : public LiveVariables::Observer { case DeadIncrement: BugType = "Dead increment"; + LLVM_FALLTHROUGH; case Standard: if (!BugType) BugType = "Dead assignment"; os << "Value stored to '" << *V << "' is never read"; diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 8ee34190891a..f84c0ee800a3 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1176,6 +1176,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, } } // FALLTHROUGH + LLVM_FALLTHROUGH; } case Stmt::CallExprClass: case Stmt::CXXMemberCallExprClass: diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index ffaa0eda918a..04452e3e7cc2 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -325,6 +325,7 @@ Optional SValBuilder::getConstantVal(const Expr *E) { } } // FALLTHROUGH + LLVM_FALLTHROUGH; } // If we don't have a special case, fall back to the AST's constant evaluator. diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 82ce8b45fe78..9c28457b2139 100644 --- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -163,6 +163,7 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { return nonloc::SymbolVal(SymR->getSymbol()); // FALL-THROUGH + LLVM_FALLTHROUGH; } case loc::GotoLabelKind: diff --git a/test/CodeGen/pr26099.c b/test/CodeGen/pr26099.c new file mode 100644 index 000000000000..15b73b832e9d --- /dev/null +++ b/test/CodeGen/pr26099.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -ffreestanding %s -triple=i686-apple-darwin -target-feature +mmx -emit-llvm -o - -Wall -Werror +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +mmx -emit-llvm -o - -Wall -Werror +// REQUIRES: asserts + +#include + +int __attribute__ ((__vector_size__ (8))) b; + +void bar(int a) +{ + b = __builtin_ia32_vec_init_v2si (0, a); +} \ No newline at end of file diff --git a/test/CodeGen/thin_link_bitcode.c b/test/CodeGen/thin_link_bitcode.c index 4cb5f798a568..52c5715ba561 100644 --- a/test/CodeGen/thin_link_bitcode.c +++ b/test/CodeGen/thin_link_bitcode.c @@ -1,6 +1,11 @@ +// REQUIRES: x86-registered-target +// // RUN: %clang_cc1 -o %t -flto=thin -fthin-link-bitcode=%t.nodebug -triple x86_64-unknown-linux-gnu -emit-llvm-bc -debug-info-kind=limited %s // RUN: llvm-bcanalyzer -dump %t | FileCheck %s // RUN: llvm-bcanalyzer -dump %t.nodebug | FileCheck %s --check-prefix=NO_DEBUG +// RUN: %clang_cc1 -o %t.newpm -flto=thin -fexperimental-new-pass-manager -fthin-link-bitcode=%t.newpm.nodebug -triple x86_64-unknown-linux-gnu -emit-llvm-bc -debug-info-kind=limited %s +// RUN: llvm-bcanalyzer -dump %t.newpm | FileCheck %s +// RUN: llvm-bcanalyzer -dump %t.newpm.nodebug | FileCheck %s --check-prefix=NO_DEBUG int main (void) { return 0; } diff --git a/test/CodeGen/ubsan-pointer-overflow.m b/test/CodeGen/ubsan-pointer-overflow.m index c83d527e624e..56df95baff55 100644 --- a/test/CodeGen/ubsan-pointer-overflow.m +++ b/test/CodeGen/ubsan-pointer-overflow.m @@ -37,9 +37,9 @@ void binary_arith(char *p, int i) { // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize - // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize - // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize - // CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize + // CHECK-DAG: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize + // CHECK-DAG: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize + // CHECK: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize p + i; @@ -62,9 +62,9 @@ void fixed_len_array(int k) { // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize - // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize - // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize - // CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize + // CHECK-DAG: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize + // CHECK-DAG: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize + // CHECK: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize diff --git a/test/CodeGenCXX/pr33080.cpp b/test/CodeGenCXX/pr33080.cpp new file mode 100644 index 000000000000..a744bca18986 --- /dev/null +++ b/test/CodeGenCXX/pr33080.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -fms-extensions -emit-llvm -o- %s | FileCheck %s + +void fa(__unaligned struct A *) {} +// CHECK: define void @_Z2faPU11__unaligned1A( + +void ga(struct A *, struct A *) {} +// CHECK: define void @_Z2gaP1AS0_( + +void gb(__unaligned struct A *, struct A *) {} +// CHECK: define void @_Z2gbPU11__unaligned1APS_( + +void gc(struct A *, __unaligned struct A *) {} +// CHECK: define void @_Z2gcP1APU11__unalignedS_( + +void gd(__unaligned struct A *, __unaligned struct A *) {} +// CHECK: define void @_Z2gdPU11__unaligned1AS1_( + +void hb(__unaligned struct A *, __unaligned const struct A *) {} +// CHECK: define void @_Z2hbPU11__unaligned1APU11__unalignedKS_( + +void ja(__unaligned struct A *, __unaligned struct A *__unaligned *, __unaligned struct A *__unaligned *__unaligned *) {} +// CHECK: define void @_Z2jaPU11__unaligned1APU11__unalignedS1_PU11__unalignedS3_( + +void jb(__unaligned struct A *, __unaligned struct A **, __unaligned struct A *__unaligned *__unaligned *) {} +// CHECK: @_Z2jbPU11__unaligned1APS1_PU11__unalignedPU11__unalignedS1_( + +template +void ta(T &, Q *) {} + +void ia(__unaligned struct A &a) { + ta(a, &a); +} +// CHECK: @_Z2taIU11__unaligned1AS1_EvRT_PT0_( diff --git a/test/CodeGenCXX/unaligned-duplicated-mangle-name.cpp b/test/CodeGenCXX/unaligned-duplicated-mangle-name.cpp deleted file mode 100644 index a23e6a47ab05..000000000000 --- a/test/CodeGenCXX/unaligned-duplicated-mangle-name.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -fms-extensions -emit-llvm-only %s -verify - -struct A -{ - int x; - void foo() __unaligned; - void foo(); -}; - -void A::foo() __unaligned -{ - this->x++; -} - -void A::foo() // expected-error {{definition with same mangled name as another definition}} - // expected-note@-6 {{previous definition is here}} -{ - this->x++; -} - diff --git a/test/CodeGenCXX/unaligned-member-qualifier.cpp b/test/CodeGenCXX/unaligned-member-qualifier.cpp new file mode 100644 index 000000000000..0d326a666830 --- /dev/null +++ b/test/CodeGenCXX/unaligned-member-qualifier.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -fms-extensions -emit-llvm %s -o- | FileCheck %s + +struct A { + void foo() __unaligned; + void foo() const __unaligned; + void foo() volatile __unaligned; + void foo() const volatile __unaligned; +}; + +void A::foo() __unaligned {} +// CHECK: define [[THISCALL:(x86_thiscallcc )?]]void @_ZNU11__unaligned1A3fooEv( + +void A::foo() const __unaligned {} +// CHECK: define [[THISCALL]]void @_ZNU11__unalignedK1A3fooEv( + +void A::foo() volatile __unaligned {} +// CHECK: define [[THISCALL]]void @_ZNU11__unalignedV1A3fooEv( + +void A::foo() const volatile __unaligned {} +// CHECK: define [[THISCALL]]void @_ZNU11__unalignedVK1A3fooEv( diff --git a/test/CodeGenCoroutines/coro-params.cpp b/test/CodeGenCoroutines/coro-params.cpp index c88e503a651c..540f84585c8e 100644 --- a/test/CodeGenCoroutines/coro-params.cpp +++ b/test/CodeGenCoroutines/coro-params.cpp @@ -93,3 +93,37 @@ void f(int val, MoveOnly moParam, MoveAndCopy mcParam) { // CHECK-NEXT: call void @_ZN8MoveOnlyD1Ev(%struct.MoveOnly* %[[MoCopy]] // CHECK-NEXT: call i8* @llvm.coro.free( } + +// CHECK-LABEL: void @_Z16dependent_paramsI1A1BEvT_T0_S3_(%struct.A* %x, %struct.B*, %struct.B* %y) +template +void dependent_params(T x, U, U y) { + // CHECK: %[[x_copy:.+]] = alloca %struct.A + // CHECK-NEXT: %[[unnamed_copy:.+]] = alloca %struct.B + // CHECK-NEXT: %[[y_copy:.+]] = alloca %struct.B + + // CHECK: call i8* @llvm.coro.begin + // CHECK-NEXT: call void @_ZN1AC1EOS_(%struct.A* %[[x_copy]], %struct.A* dereferenceable(512) %x) + // CHECK-NEXT: call void @_ZN1BC1EOS_(%struct.B* %[[unnamed_copy]], %struct.B* dereferenceable(512) %0) + // CHECK-NEXT: call void @_ZN1BC1EOS_(%struct.B* %[[y_copy]], %struct.B* dereferenceable(512) %y) + // CHECK-NEXT: invoke void @_ZNSt12experimental16coroutine_traitsIJv1A1BS2_EE12promise_typeC1Ev( + + co_return; +} + +struct A { + int WontFitIntoRegisterForSure[128]; + A(); + A(A&&) noexcept; + ~A(); +}; + +struct B { + int WontFitIntoRegisterForSure[128]; + B(); + B(B&&) noexcept; + ~B(); +}; + +void call_dependent_params() { + dependent_params(A{}, B{}, B{}); +} diff --git a/test/CodeGenObjCXX/arc-mangle.mm b/test/CodeGenObjCXX/arc-mangle.mm index 82e37556ec30..b39aa7bbbf00 100644 --- a/test/CodeGenObjCXX/arc-mangle.mm +++ b/test/CodeGenObjCXX/arc-mangle.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -triple %itanium_abi_triple -emit-llvm -fblocks -o - %s | FileCheck %s +// RUN: %clang_cc1 -DTEST_UNALIGNED -fms-extensions -fobjc-arc -fobjc-runtime-has-weak -triple %itanium_abi_triple -emit-llvm -fblocks -o - %s | FileCheck %s --check-prefix=UNALIGNED // CHECK-LABEL: define {{.*}}void @_Z1fPU8__strongP11objc_object(i8**) void f(__strong id *) {} @@ -32,3 +33,12 @@ template struct unsigned_c { }; // CHECK-LABEL: define weak_odr {{.*}}void @_Z1gIKvEvP10unsigned_cIXplszv1U8__bridgecvPT_v1U8__bridgecvP11objc_objectcvS3_Li0ELi1EEE templatevoid g(unsigned_c*) {} template void g(unsigned_c *); + +#if TEST_UNALIGNED +// UNALIGNED-LABEL: define {{.*}}void @_Z1gPU6__weakU11__unalignedP11objc_object(i8**) +void g(__weak __unaligned id *) {} +// UNALIGNED-LABEL: define {{.*}}void @_Z1gPU11__unalignedU8__strongP11objc_object(i8**) +void g(__strong __unaligned id *) {} +// UNALIGNED-LABEL: define {{.*}}void @_Z1gPU11__unalignedU15__autoreleasingP11objc_object(i8**) +void g(__autoreleasing __unaligned id *) {} +#endif // TEST_UNALIGNED diff --git a/test/Driver/fsanitize-coverage.c b/test/Driver/fsanitize-coverage.c index cf0941477bba..0516b6db524c 100644 --- a/test/Driver/fsanitize-coverage.c +++ b/test/Driver/fsanitize-coverage.c @@ -84,6 +84,9 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=no-prune,func,trace-pc-guard %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_NOPRUNE // CHECK_NOPRUNE: -fsanitize-coverage-no-prune +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=inline-8bit-counters %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_INLINE8BIT +// CHECK_INLINE8BIT: -fsanitize-coverage-inline-8bit-counters + // RUN: %clang_cl --target=i386-pc-win32 -fsanitize=address -fsanitize-coverage=func,trace-pc-guard -c -### -- %s 2>&1 | FileCheck %s -check-prefix=CLANG-CL-COVERAGE // CLANG-CL-COVERAGE-NOT: error: // CLANG-CL-COVERAGE-NOT: warning: diff --git a/test/Frontend/rewrite-includes-filenotfound.c b/test/Frontend/rewrite-includes-filenotfound.c new file mode 100644 index 000000000000..203dbde54516 --- /dev/null +++ b/test/Frontend/rewrite-includes-filenotfound.c @@ -0,0 +1,6 @@ +// RUN: not %clang_cc1 -E -frewrite-includes %s -o - 2>&1 | FileCheck %s + +#include "this file does not exist.foo" +#include "this file also does not exist.foo" + +CHECK: fatal error: {{.*}} file not found diff --git a/test/Integration/carbon.c b/test/Integration/carbon.c index 0498116dd181..3cae39122685 100644 --- a/test/Integration/carbon.c +++ b/test/Integration/carbon.c @@ -1,4 +1,5 @@ // RUN: %clang -fsyntax-only %s +// REQUIRES: macos-sdk-10.12 #ifdef __APPLE__ #include #endif diff --git a/test/Integration/cocoa-pch.m b/test/Integration/cocoa-pch.m index 0159b3201492..fa3ccea37896 100644 --- a/test/Integration/cocoa-pch.m +++ b/test/Integration/cocoa-pch.m @@ -1,6 +1,7 @@ // RUN: %clang -arch x86_64 -x objective-c-header %s -o %t.h.pch // RUN: touch %t.empty.m // RUN: %clang -arch x86_64 -fsyntax-only %t.empty.m -include %t.h -Xclang -ast-dump 2>&1 > /dev/null +// REQUIRES: macos-sdk-10.12 #ifdef __APPLE__ #include #endif diff --git a/test/Integration/cocoa.m b/test/Integration/cocoa.m index d814b3ee21bc..91d868250845 100644 --- a/test/Integration/cocoa.m +++ b/test/Integration/cocoa.m @@ -1,4 +1,5 @@ // RUN: %clang -arch x86_64 %s -fsyntax-only -Xclang -print-stats +// REQUIRES: macos-sdk-10.12 #ifdef __APPLE__ #include #endif diff --git a/test/Misc/ast-print-objectivec.m b/test/Misc/ast-print-objectivec.m index e419237bbbac..cb5aacc06a49 100644 --- a/test/Misc/ast-print-objectivec.m +++ b/test/Misc/ast-print-objectivec.m @@ -17,25 +17,30 @@ @implementation I - (void)MethP __attribute__((availability(macosx,introduced=10.1.0,deprecated=10.2))) {} - (void)MethI __attribute__((availability(macosx,introduced=10.1.0,deprecated=10.2))) {} + +- (void)methodWithArg:(int)x andAnotherOne:(int)y { } @end // CHECK: @protocol P -// CHECK: - (void) MethP __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))); +// CHECK: - (void)MethP __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))); // CHECK: @end // CHECK: @interface I : NSObject

    -// CHECK: - (void) MethI __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))); +// CHECK: - (void)MethI __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))); // CHECK: @end // CHECK: @interface I(CAT) -// CHECK: - (void) MethCAT __attribute__((availability(macos, introduced=10_1_0, deprecated=10_2))); +// CHECK: - (void)MethCAT __attribute__((availability(macos, introduced=10_1_0, deprecated=10_2))); // CHECK: @end // CHECK: @implementation I -// CHECK: - (void) MethP __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))) { +// CHECK: - (void)MethP __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))) { // CHECK: } -// CHECK: - (void) MethI __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))) { +// CHECK: - (void)MethI __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))) { +// CHECK: } + +// CHECK: - (void)methodWithArg:(int)x andAnotherOne:(int)y { // CHECK: } // CHECK: @end diff --git a/test/Modules/Inputs/check-for-sanitizer-feature/check.h b/test/Modules/Inputs/check-for-sanitizer-feature/check.h new file mode 100644 index 000000000000..74b4628d1230 --- /dev/null +++ b/test/Modules/Inputs/check-for-sanitizer-feature/check.h @@ -0,0 +1,5 @@ +#if __has_feature(address_sanitizer) +#define HAS_ASAN 1 +#else +#define HAS_ASAN 0 +#endif diff --git a/test/Modules/Inputs/check-for-sanitizer-feature/map b/test/Modules/Inputs/check-for-sanitizer-feature/map new file mode 100644 index 000000000000..95f2da95020e --- /dev/null +++ b/test/Modules/Inputs/check-for-sanitizer-feature/map @@ -0,0 +1,3 @@ +module check_feature { + header "check.h" +} diff --git a/test/Modules/Inputs/header-attribs/bar.h b/test/Modules/Inputs/header-attribs/bar.h new file mode 100644 index 000000000000..796b4ebcc731 --- /dev/null +++ b/test/Modules/Inputs/header-attribs/bar.h @@ -0,0 +1 @@ +extern int b; diff --git a/test/Modules/Inputs/header-attribs/baz.h b/test/Modules/Inputs/header-attribs/baz.h new file mode 100644 index 000000000000..566a522b2474 --- /dev/null +++ b/test/Modules/Inputs/header-attribs/baz.h @@ -0,0 +1 @@ +extern int c; diff --git a/test/Modules/Inputs/header-attribs/foo.h b/test/Modules/Inputs/header-attribs/foo.h new file mode 100644 index 000000000000..a54d4a7067ee --- /dev/null +++ b/test/Modules/Inputs/header-attribs/foo.h @@ -0,0 +1 @@ +extern int a; \ No newline at end of file diff --git a/test/Modules/Inputs/header-attribs/modular.modulemap b/test/Modules/Inputs/header-attribs/modular.modulemap new file mode 100644 index 000000000000..945d7150fd2f --- /dev/null +++ b/test/Modules/Inputs/header-attribs/modular.modulemap @@ -0,0 +1,5 @@ +module A { + header "foo.h" { size 13 } + header "bar.h" { size 1000 } + header "baz.h" { mtime 1 } +} diff --git a/test/Modules/Inputs/header-attribs/textual.modulemap b/test/Modules/Inputs/header-attribs/textual.modulemap new file mode 100644 index 000000000000..b73f3698aa02 --- /dev/null +++ b/test/Modules/Inputs/header-attribs/textual.modulemap @@ -0,0 +1,5 @@ +module A { + textual header "foo.h" { size 13 } + textual header "bar.h" { size 1000 } + textual header "baz.h" { mtime 1 } +} diff --git a/test/Modules/check-for-sanitizer-feature.cpp b/test/Modules/check-for-sanitizer-feature.cpp new file mode 100644 index 000000000000..40ae46c64684 --- /dev/null +++ b/test/Modules/check-for-sanitizer-feature.cpp @@ -0,0 +1,66 @@ +// RUN: rm -rf %t.1 %t.2 +// RUN: mkdir %t.1 %t.2 + +// Build and use an ASan-enabled module. +// RUN: %clang_cc1 -fsanitize=address -fmodules -fmodules-cache-path=%t.1 \ +// RUN: -fmodule-map-file=%S/Inputs/check-for-sanitizer-feature/map \ +// RUN: -I %S/Inputs/check-for-sanitizer-feature -verify %s +// RUN: ls %t.1 | count 2 + +// Force a module rebuild by disabling ASan. +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t.1 \ +// RUN: -fmodule-map-file=%S/Inputs/check-for-sanitizer-feature/map \ +// RUN: -I %S/Inputs/check-for-sanitizer-feature -verify %s +// RUN: ls %t.1 | count 3 + +// Enable ASan again: check that there is no import failure, and no rebuild. +// RUN: %clang_cc1 -fsanitize=address -fmodules -fmodules-cache-path=%t.1 \ +// RUN: -fmodule-map-file=%S/Inputs/check-for-sanitizer-feature/map \ +// RUN: -I %S/Inputs/check-for-sanitizer-feature -verify %s +// RUN: ls %t.1 | count 3 + +// Some sanitizers can not affect AST generation when enabled. Check that +// module rebuilds don't occur when these sanitizers are enabled. +// +// First, build without any sanitization. +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t.2 \ +// RUN: -fmodule-map-file=%S/Inputs/check-for-sanitizer-feature/map \ +// RUN: -I %S/Inputs/check-for-sanitizer-feature -verify %s +// RUN: ls %t.2 | count 2 +// +// Next, build with sanitization, and check that a new module isn't built. +// RUN: %clang_cc1 -fsanitize=cfi-vcall,unsigned-integer-overflow,nullability-arg,null -fmodules \ +// RUN: -fmodules-cache-path=%t.2 \ +// RUN: -fmodule-map-file=%S/Inputs/check-for-sanitizer-feature/map \ +// RUN: -I %S/Inputs/check-for-sanitizer-feature -verify %s +// RUN: ls %t.2 | count 2 + +// Finally, test that including enabled sanitizers in the module hash isn't +// required to ensure correctness of module imports. +// +// Emit a PCH with ASan enabled. +// RUN: %clang_cc1 -x c -fsanitize=address %S/Inputs/check-for-sanitizer-feature/check.h -emit-pch -o %t.asan_pch +// +// Import the PCH without ASan enabled (we expect an error). +// RUN: not %clang_cc1 -x c -include-pch %t.asan_pch %s -verify 2>&1 | FileCheck %s --check-prefix=PCH_MISMATCH +// PCH_MISMATCH: AST file was compiled with the target feature'-fsanitize=address' but the current translation unit is not +// +// Emit a PCH with UBSan enabled. +// RUN: %clang_cc1 -x c -fsanitize=null %S/Inputs/check-for-sanitizer-feature/check.h -emit-pch -o %t.ubsan_pch +// +// Import the PCH without UBSan enabled (should work just fine). +// RUN: %clang_cc1 -x c -include-pch %t.ubsan_pch %s -I %S/Inputs/check-for-sanitizer-feature -verify + +#include "check.h" + +#if __has_feature(address_sanitizer) +#if HAS_ASAN != 1 +#error Module doesn't have the address_sanitizer feature, but main program does. +#endif +#else +#if HAS_ASAN != 0 +#error Module has the address_sanitizer feature, but main program doesn't. +#endif +#endif + +// expected-no-diagnostics diff --git a/test/Modules/diagnostics.modulemap b/test/Modules/diagnostics.modulemap index 3b5b6a5c0396..865892b53b28 100644 --- a/test/Modules/diagnostics.modulemap +++ b/test/Modules/diagnostics.modulemap @@ -1,4 +1,4 @@ -// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/diagnostics-aux.modulemap -fmodule-map-file=%s -fsyntax-only -x c++ /dev/null 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/diagnostics-aux.modulemap -fmodule-map-file=%s -fsyntax-only -x c++ /dev/null 2>&1 | FileCheck %s --implicit-check-not error: // CHECK: In file included from {{.*}}diagnostics-aux.modulemap:3: // CHECK: diagnostics-aux-2.modulemap:2:3: error: expected @@ -15,3 +15,15 @@ module bad_use { // CHECK: diagnostics.modulemap:[[@LINE+1]]:22: error: use declarations are only allowed in top-level modules module submodule { use foo } } + +module header_attr { + // CHECK: diagnostics.modulemap:[[@LINE+1]]:20: error: expected a header attribute name + header "foo.h" { x } + // CHECK: diagnostics.modulemap:[[@LINE+1]]:27: error: header attribute 'size' specified multiple times + header "bar.h" { size 1 size 2 } + // CHECK: diagnostics.modulemap:[[@LINE+1]]:25: error: expected integer literal as value for header attribute 'size' + header "baz.h" { size "30 kilobytes" } + + header "quux.h" { size 1 mtime 2 } + header "no_attrs.h" {} +} diff --git a/test/Modules/header-attribs.cpp b/test/Modules/header-attribs.cpp new file mode 100644 index 000000000000..292a94561e45 --- /dev/null +++ b/test/Modules/header-attribs.cpp @@ -0,0 +1,10 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -I%S/Inputs/header-attribs -fmodule-map-file=%S/Inputs/header-attribs/textual.modulemap -fmodules-cache-path=%t -verify %s -fmodule-name=A -fmodules-strict-decluse +// RUN: not %clang_cc1 -fmodules -I%S/Inputs/header-attribs -emit-module -x c++-module-map %S/Inputs/header-attribs/modular.modulemap -fmodules-cache-path=%t -fmodule-name=A 2>&1 | FileCheck %s --check-prefix BUILD-MODULAR + +#include "foo.h" // ok, stats match +#include "bar.h" // expected-error {{does not depend on a module exporting 'bar.h'}} +#include "baz.h" // expected-error {{does not depend on a module exporting 'baz.h'}} + +// FIXME: Explain why the 'bar.h' found on disk doesn't match the module map. +// BUILD-MODULAR: error: header 'bar.h' not found diff --git a/test/Modules/lookup.m b/test/Modules/lookup.m index edf70639e5cc..b22e41f84594 100644 --- a/test/Modules/lookup.m +++ b/test/Modules/lookup.m @@ -14,7 +14,7 @@ void test(id x) { // expected-note@Inputs/lookup_right.h:3{{also found}} } -// CHECK-PRINT: - (int) method; -// CHECK-PRINT: - (double) method +// CHECK-PRINT: - (int)method; +// CHECK-PRINT: - (double)method // CHECK-PRINT: void test(id x) diff --git a/test/Modules/preprocess-missing.modulemap b/test/Modules/preprocess-missing.modulemap new file mode 100644 index 000000000000..300494672f2c --- /dev/null +++ b/test/Modules/preprocess-missing.modulemap @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fmodules -fmodule-name=A -x c++-module-map %s -emit-module -o /dev/null -verify +module A { + header "does not exist" { size 12345 } // ok, do not need mtime for explicit module build + header "also does not exist" { mtime 12345 } +} +#pragma clang module contents +// expected-error@4 {{cannot emit module A: size must be explicitly specified for missing header file "also does not exist"}} diff --git a/test/Modules/preprocess-module.cpp b/test/Modules/preprocess-module.cpp index 9d1a2bb6801f..1e9458e667e1 100644 --- a/test/Modules/preprocess-module.cpp +++ b/test/Modules/preprocess-module.cpp @@ -28,12 +28,21 @@ // RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DINCLUDE -I%S/Inputs/preprocess // RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DREWRITE -DINCLUDE -I%S/Inputs/preprocess +// Now try building the module when the header files are missing. +// RUN: cp %S/Inputs/preprocess/fwd.h %S/Inputs/preprocess/file.h %S/Inputs/preprocess/file2.h %S/Inputs/preprocess/module.modulemap %t +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -I%t -x c++-module-map %t/module.modulemap -E -frewrite-includes -o %t/copy.ii +// RUN: rm %t/fwd.h %t/file.h %t/file2.h %t/module.modulemap +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/copy.ii -emit-module -o %t/copy.pcm + +// Finally, check that our module contains correct mapping information for the headers. +// RUN: cp %S/Inputs/preprocess/fwd.h %S/Inputs/preprocess/file.h %S/Inputs/preprocess/file2.h %S/Inputs/preprocess/module.modulemap %t +// RUN: %clang_cc1 -fmodules -fmodule-file=%t/copy.pcm %s -I%t -verify -fno-modules-error-recovery -DCOPY -DINCLUDE // == module map // CHECK: # 1 "{{.*}}module.modulemap" // CHECK: module file { -// CHECK: header "file.h" -// CHECK: header "file2.h" +// CHECK: header "file.h" { size +// CHECK: header "file2.h" { size // CHECK: } // == file.h @@ -98,6 +107,8 @@ __FILE *a; // expected-error {{declaration of '__FILE' must be imported}} #ifdef REWRITE // expected-note@rewrite.ii:1 {{here}} +#elif COPY +// expected-note@copy.ii:1 {{here}} #else // expected-note@no-rewrite.ii:1 {{here}} #endif diff --git a/test/Sema/warn-strict-prototypes.m b/test/Sema/warn-strict-prototypes.m index 4567dab01930..66d574f75f80 100644 --- a/test/Sema/warn-strict-prototypes.m +++ b/test/Sema/warn-strict-prototypes.m @@ -2,16 +2,16 @@ @interface Foo -@property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this function declaration is not a prototype}} +@property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this block declaration is not a prototype}} @property (nonatomic, copy) void (^block)(void); // no warning -- doStuff:(void (^)()) completionHandler; // expected-warning {{this function declaration is not a prototype}} +- doStuff:(void (^)()) completionHandler; // expected-warning {{this block declaration is not a prototype}} - doOtherStuff:(void (^)(void)) completionHandler; // no warning @end void foo() { - void (^block)() = // expected-warning {{this function declaration is not a prototype}} + void (^block)() = // expected-warning {{this block declaration is not a prototype}} ^void(int arg) { // no warning }; void (^block2)(void) = ^void() { // no warning @@ -19,3 +19,8 @@ void foo() { void (^block3)(void) = ^ { // no warning }; } + +void (*(^(*(^block4)()) // expected-warning {{this block declaration is not a prototype}} + ()) // expected-warning {{this function declaration is not a prototype}} + ()) // expected-warning {{this block declaration is not a prototype}} + (); // expected-warning {{this function declaration is not a prototype}} diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp index a867cf68a6e1..4eedc2162f07 100644 --- a/test/SemaCXX/coroutines.cpp +++ b/test/SemaCXX/coroutines.cpp @@ -892,3 +892,16 @@ void test_bad_suspend() { co_await d; // OK } } + +template +struct NoCopy { + NoCopy(NoCopy const&) = delete; // expected-note 2 {{deleted here}} +}; +template +void test_dependent_param(T t, U) { + // expected-error@-1 {{call to deleted constructor of 'NoCopy<0>'}} + // expected-error@-2 {{call to deleted constructor of 'NoCopy<1>'}} + ((void)t); + co_return 42; +} +template void test_dependent_param(NoCopy<0>, NoCopy<1>); // expected-note {{requested here}} diff --git a/test/SemaOpenCL/func.cl b/test/SemaOpenCL/func.cl index ea3bab6c514c..dc5b44057b19 100644 --- a/test/SemaOpenCL/func.cl +++ b/test/SemaOpenCL/func.cl @@ -4,8 +4,15 @@ void vararg_f(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}} void __vararg_f(int, ...); typedef void (*vararg_fptr_t)(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}} + // expected-error@-1{{pointers to functions are not allowed}} int printf(__constant const char *st, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}} +// Struct type with function pointer field +typedef struct s +{ + void (*f)(struct s *self, int *i); // expected-error{{pointers to functions are not allowed}} +} s_t; + //Function pointer void foo(void*); diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp index c94c9db94e06..74a25865aa20 100644 --- a/test/SemaTemplate/deduction-crash.cpp +++ b/test/SemaTemplate/deduction-crash.cpp @@ -1,14 +1,10 @@ -// RUN: not %clang_cc1 -fsyntax-only %s -std=c++11 2>&1| FileCheck %s - -// Note that the error count below doesn't matter. We just want to -// make sure that the parser doesn't crash. -// CHECK: 17 errors +// RUN: %clang_cc1 -fsyntax-only %s -std=c++1z -verify // PR7511 -template +template // expected-error +{{}} struct int_; -template +template // expected-error +{{}} template struct ac { @@ -17,7 +13,7 @@ struct ac templatestruct aaa { - typedef ac<1,int,int>::ae ae + typedef ac<1,int,int>::ae ae // expected-error +{{}} }; template @@ -36,19 +32,19 @@ struct state_machine struct In; template - struct In,my>; + struct In,my>; // expected-error +{{}} template int process(Event) { - In > a; + In > a; // expected-error +{{}} } - } + } // expected-error +{{}} template int ant(Event) { region_processing_helper* helper; - helper->process(0) + helper->process(0) // expected-error +{{}} } }; @@ -81,21 +77,21 @@ void endl( ) ; extern basic_ostream cout; -int operator<<( basic_ostream , pair ) ; +int operator<<( basic_ostream , pair ) ; // expected-note +{{}} void register_object_imp ( ) { -cout << endl<1>; +cout << endl<1>; // expected-error +{{}} } // PR12933 -namespacae PR12933 { - template +namespace PR12933 { + template // expected-error +{{}} template void function(S a, T b) {} int main() { - function(0, 1); + function(0, 1); // expected-error +{{}} return 0; } } @@ -142,3 +138,9 @@ namespace PR14281_part3 { template struct B {}; A, &some_decl>::type x; } + +namespace var_template_partial_spec_incomplete { + template int n; + template int n; // expected-error +{{}} expected-note {{}} + int k = n; +} diff --git a/test/lit.cfg b/test/lit.cfg index a5e8b9de994b..e72eca6bd397 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -529,3 +529,6 @@ if run_console_tests != 0: config.available_features.add('console') lit.util.usePlatformSdkOnDarwin(config, lit_config) +macOSSDKVersion = lit.util.findPlatformSdkVersionOnMacOS(config, lit_config) +if macOSSDKVersion is not None: + config.available_features.add('macos-sdk-' + macOSSDKVersion) diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp index e5a09a31f69f..ae6d0f0dd2e2 100644 --- a/unittests/AST/DeclPrinterTest.cpp +++ b/unittests/AST/DeclPrinterTest.cpp @@ -1228,7 +1228,7 @@ TEST(DeclPrinter, TestObjCMethod1) { "@end\n", namedDecl(hasName("A:inRange:"), hasDescendant(namedDecl(hasName("printThis")))).bind("id"), - "- (int) A:(id)anObject inRange:(long)range")); + "- (int)A:(id)anObject inRange:(long)range")); } TEST(DeclPrinter, TestObjCProtocol1) { From 25091d6bd042c6bf2709eaab2bd1a88f3f2d9fda Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 3 Jun 2017 15:21:00 +0000 Subject: [PATCH 10/22] Vendor import of compiler-rt trunk r304659: https://llvm.org/svn/llvm-project/compiler-rt/trunk@304659 --- include/sanitizer/coverage_interface.h | 6 - lib/asan/asan_activation.cc | 3 - lib/asan/asan_interceptors.cc | 7 +- lib/asan/asan_thread.cc | 12 +- lib/lsan/lsan_common.cc | 3 + lib/lsan/lsan_common_linux.cc | 23 +- lib/sanitizer_common/CMakeLists.txt | 2 - lib/sanitizer_common/sanitizer_common.h | 6 - .../sanitizer_coverage_interface.inc | 1 - .../sanitizer_coverage_libcdep.cc | 627 ------------------ .../sanitizer_coverage_libcdep_new.cc | 25 + .../sanitizer_coverage_mapping_libcdep.cc | 122 ---- lib/sanitizer_common/sanitizer_flags.inc | 10 - lib/sanitizer_common/sanitizer_linux.cc | 22 +- lib/sanitizer_common/sanitizer_platform.h | 9 + .../sanitizer_platform_limits_posix.h | 8 + .../sanitizer_posix_libcdep.cc | 1 - lib/sanitizer_common/sanitizer_win.cc | 3 - lib/sanitizer_common/scripts/check_lint.sh | 2 +- .../tests/sanitizer_flags_test.cc | 6 +- lib/ubsan/ubsan_checks.inc | 1 + lib/ubsan/ubsan_handlers.cc | 31 + lib/ubsan/ubsan_handlers.h | 7 + lib/ubsan/ubsan_interface.inc | 2 + .../TestCases/Android/coverage-android.cc | 147 ---- test/asan/TestCases/Linux/uar_signals.cc | 33 +- .../Posix/coverage-maybe-open-file.cc | 34 - .../sanitizer_coverage_inline8bit_counter.cc | 23 + .../TestCases/Pointer/index-overflow.cpp | 19 + 29 files changed, 186 insertions(+), 1009 deletions(-) delete mode 100644 lib/sanitizer_common/sanitizer_coverage_libcdep.cc delete mode 100644 lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc delete mode 100644 test/asan/TestCases/Android/coverage-android.cc delete mode 100644 test/asan/TestCases/Posix/coverage-maybe-open-file.cc create mode 100644 test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc create mode 100644 test/ubsan/TestCases/Pointer/index-overflow.cpp diff --git a/include/sanitizer/coverage_interface.h b/include/sanitizer/coverage_interface.h index bdb113728b95..637379d47c41 100644 --- a/include/sanitizer/coverage_interface.h +++ b/include/sanitizer/coverage_interface.h @@ -19,8 +19,6 @@ extern "C" { #endif - // Initialize coverage. - void __sanitizer_cov_init(); // Record and dump coverage info. void __sanitizer_cov_dump(); @@ -28,10 +26,6 @@ extern "C" { // .sancov files. void __sanitizer_dump_coverage(const uintptr_t *pcs, uintptr_t len); - // Open .sancov.packed in the coverage directory and return the file - // descriptor. Returns -1 on failure, or if coverage dumping is disabled. - // This is intended for use by sandboxing code. - intptr_t __sanitizer_maybe_open_cov_file(const char *name); #ifdef __cplusplus } // extern "C" #endif diff --git a/lib/asan/asan_activation.cc b/lib/asan/asan_activation.cc index 7e4e604dc218..66eba9ce2748 100644 --- a/lib/asan/asan_activation.cc +++ b/lib/asan/asan_activation.cc @@ -106,7 +106,6 @@ void AsanDeactivate() { // Deactivate the runtime. SetCanPoisonMemory(false); SetMallocContextSize(1); - ReInitializeCoverage(false, nullptr); AllocatorOptions disabled = asan_deactivated_flags.allocator_options; disabled.quarantine_size_mb = 0; @@ -130,8 +129,6 @@ void AsanActivate() { SetCanPoisonMemory(asan_deactivated_flags.poison_heap); SetMallocContextSize(asan_deactivated_flags.malloc_context_size); - ReInitializeCoverage(asan_deactivated_flags.coverage, - asan_deactivated_flags.coverage_dir); ReInitializeAllocator(asan_deactivated_flags.allocator_options); asan_is_deactivated = false; diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index e82a5a4a7e96..4682fba3392c 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -242,9 +242,8 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) CheckNoDeepBind(filename, flag); \ } while (false) #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() -#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ - CoverageUpdateMapping() -#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping() +#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) +#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ if (AsanThread *t = GetCurrentThread()) { \ @@ -723,9 +722,7 @@ static void AfterFork() { INTERCEPTOR(int, fork, void) { ENSURE_ASAN_INITED(); BeforeFork(); - if (common_flags()->coverage) CovBeforeFork(); int pid = REAL(fork)(); - if (common_flags()->coverage) CovAfterFork(pid); AfterFork(); return pid; } diff --git a/lib/asan/asan_thread.cc b/lib/asan/asan_thread.cc index f41ee2df2d96..714496d5c606 100644 --- a/lib/asan/asan_thread.cc +++ b/lib/asan/asan_thread.cc @@ -166,16 +166,19 @@ void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save, } inline AsanThread::StackBounds AsanThread::GetStackBounds() const { - if (!atomic_load(&stack_switching_, memory_order_acquire)) - return StackBounds{stack_bottom_, stack_top_}; // NOLINT + if (!atomic_load(&stack_switching_, memory_order_acquire)) { + // Make sure the stack bounds are fully initialized. + if (stack_bottom_ >= stack_top_) return {0, 0}; + return {stack_bottom_, stack_top_}; + } char local; const uptr cur_stack = (uptr)&local; // Note: need to check next stack first, because FinishSwitchFiber // may be in process of overwriting stack_top_/bottom_. But in such case // we are already on the next stack. if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_) - return StackBounds{next_stack_bottom_, next_stack_top_}; // NOLINT - return StackBounds{stack_bottom_, stack_top_}; // NOLINT + return {next_stack_bottom_, next_stack_top_}; + return {stack_bottom_, stack_top_}; } uptr AsanThread::stack_top() { @@ -197,6 +200,7 @@ FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() { uptr stack_size = this->stack_size(); if (stack_size == 0) // stack_size is not yet available, don't use FakeStack. return nullptr; + CHECK_LE(stack_size, 0x10000000); uptr old_val = 0; // fake_stack_ has 3 states: // 0 -- not initialized diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc index a5ffc6835f5f..d4f670681fa5 100644 --- a/lib/lsan/lsan_common.cc +++ b/lib/lsan/lsan_common.cc @@ -408,6 +408,9 @@ static void MarkInvalidPCCb(uptr chunk, void *arg) { // On Linux, handles dynamically allocated TLS blocks by treating all chunks // allocated from ld-linux.so as reachable. +// On Linux, treats all chunks allocated from ld-linux.so as reachable, which +// covers dynamically allocated TLS blocks, internal dynamic loader's loaded +// modules accounting etc. // Dynamic TLS blocks contain the TLS variables of dynamically loaded modules. // They are allocated with a __libc_memalign() call in allocate_and_init() // (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those diff --git a/lib/lsan/lsan_common_linux.cc b/lib/lsan/lsan_common_linux.cc index c903be42d1e7..2e4095b495fe 100644 --- a/lib/lsan/lsan_common_linux.cc +++ b/lib/lsan/lsan_common_linux.cc @@ -23,6 +23,10 @@ #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_stackdepot.h" +#if SANITIZER_USE_GETAUXVAL +#include +#endif // SANITIZER_USE_GETAUXVAL + namespace __lsan { static const char kLinkerName[] = "ld"; @@ -30,8 +34,12 @@ static const char kLinkerName[] = "ld"; static char linker_placeholder[sizeof(LoadedModule)] ALIGNED(64); static LoadedModule *linker = nullptr; -static bool IsLinker(const char* full_name) { - return LibraryNameIs(full_name, kLinkerName); +static bool IsLinker(const LoadedModule& module) { +#if SANITIZER_USE_GETAUXVAL + return module.base_address() == getauxval(AT_BASE); +#else + return LibraryNameIs(module.full_name(), kLinkerName); +#endif // SANITIZER_USE_GETAUXVAL } __attribute__((tls_model("initial-exec"))) @@ -49,22 +57,25 @@ void InitializePlatformSpecificModules() { ListOfModules modules; modules.init(); for (LoadedModule &module : modules) { - if (!IsLinker(module.full_name())) continue; + if (!IsLinker(module)) + continue; if (linker == nullptr) { linker = reinterpret_cast(linker_placeholder); *linker = module; module = LoadedModule(); } else { VReport(1, "LeakSanitizer: Multiple modules match \"%s\". " - "TLS will not be handled correctly.\n", kLinkerName); + "TLS and other allocations originating from linker might be " + "falsely reported as leaks.\n", kLinkerName); linker->clear(); linker = nullptr; return; } } if (linker == nullptr) { - VReport(1, "LeakSanitizer: Dynamic linker not found. " - "TLS will not be handled correctly.\n"); + VReport(1, "LeakSanitizer: Dynamic linker not found. TLS and other " + "allocations originating from linker might be falsely reported " + "as leaks.\n"); } } diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt index 6cdc91897cd8..bf8459ef5e91 100644 --- a/lib/sanitizer_common/CMakeLists.txt +++ b/lib/sanitizer_common/CMakeLists.txt @@ -54,9 +54,7 @@ set(SANITIZER_NOLIBC_SOURCES set(SANITIZER_LIBCDEP_SOURCES sanitizer_common_libcdep.cc sancov_flags.cc - sanitizer_coverage_libcdep.cc sanitizer_coverage_libcdep_new.cc - sanitizer_coverage_mapping_libcdep.cc sanitizer_coverage_win_sections.cc sanitizer_linux_libcdep.cc sanitizer_posix_libcdep.cc diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index a1c9c5a57a84..79ee6873bcc4 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -317,15 +317,9 @@ bool AddressSpaceIsUnlimited(); void SetAddressSpaceUnlimited(); void AdjustStackSize(void *attr); void PrepareForSandboxing(__sanitizer_sandbox_arguments *args); -void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args); void SetSandboxingCallback(void (*f)()); -void CoverageUpdateMapping(); -void CovBeforeFork(); -void CovAfterFork(int child_pid); - void InitializeCoverage(bool enabled, const char *coverage_dir); -void ReInitializeCoverage(bool enabled, const char *coverage_dir); void InitTlsSize(); uptr GetTlsSize(); diff --git a/lib/sanitizer_common/sanitizer_coverage_interface.inc b/lib/sanitizer_common/sanitizer_coverage_interface.inc index 70c10e04b653..d4749000d80a 100644 --- a/lib/sanitizer_common/sanitizer_coverage_interface.inc +++ b/lib/sanitizer_common/sanitizer_coverage_interface.inc @@ -11,7 +11,6 @@ INTERFACE_FUNCTION(__sanitizer_cov_dump) INTERFACE_FUNCTION(__sanitizer_dump_coverage) INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage) -INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file) INTERFACE_WEAK_FUNCTION(__sancov_default_options) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp) INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1) diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc deleted file mode 100644 index abfdf3d02088..000000000000 --- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ /dev/null @@ -1,627 +0,0 @@ -//===-- sanitizer_coverage.cc ---------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Sanitizer Coverage. -// This file implements run-time support for a poor man's coverage tool. -// -// Compiler instrumentation: -// For every interesting basic block the compiler injects the following code: -// if (Guard < 0) { -// __sanitizer_cov(&Guard); -// } -// At the module start up time __sanitizer_cov_module_init sets the guards -// to consecutive negative numbers (-1, -2, -3, ...). -// It's fine to call __sanitizer_cov more than once for a given block. -// -// Run-time: -// - __sanitizer_cov(): record that we've executed the PC (GET_CALLER_PC). -// and atomically set Guard to -Guard. -// - __sanitizer_cov_dump: dump the coverage data to disk. -// For every module of the current process that has coverage data -// this will create a file module_name.PID.sancov. -// -// The file format is simple: the first 8 bytes is the magic, -// one of 0xC0BFFFFFFFFFFF64 and 0xC0BFFFFFFFFFFF32. The last byte of the -// magic defines the size of the following offsets. -// The rest of the data is the offsets in the module. -// -// Eventually, this coverage implementation should be obsoleted by a more -// powerful general purpose Clang/LLVM coverage instrumentation. -// Consider this implementation as prototype. -// -// FIXME: support (or at least test with) dlclose. -//===----------------------------------------------------------------------===// - -#include "sanitizer_allocator_internal.h" -#include "sanitizer_common.h" -#include "sanitizer_libc.h" -#include "sanitizer_mutex.h" -#include "sanitizer_procmaps.h" -#include "sanitizer_stacktrace.h" -#include "sanitizer_symbolizer.h" -#include "sanitizer_flags.h" - -using namespace __sanitizer; - -static const u64 kMagic64 = 0xC0BFFFFFFFFFFF64ULL; -static const u64 kMagic32 = 0xC0BFFFFFFFFFFF32ULL; -static const uptr kNumWordsForMagic = SANITIZER_WORDSIZE == 64 ? 1 : 2; -static const u64 kMagic = SANITIZER_WORDSIZE == 64 ? kMagic64 : kMagic32; - -static atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once. - -static atomic_uintptr_t coverage_counter; - -// pc_array is the array containing the covered PCs. -// To make the pc_array thread- and async-signal-safe it has to be large enough. -// 128M counters "ought to be enough for anybody" (4M on 32-bit). - -// With coverage_direct=1 in ASAN_OPTIONS, pc_array memory is mapped to a file. -// In this mode, __sanitizer_cov_dump does nothing, and CovUpdateMapping() -// dump current memory layout to another file. - -static bool cov_sandboxed = false; -static fd_t cov_fd = kInvalidFd; -static unsigned int cov_max_block_size = 0; -static bool coverage_enabled = false; -static const char *coverage_dir; - -namespace __sanitizer { - -class CoverageData { - public: - void Init(); - void Enable(); - void Disable(); - void ReInit(); - void BeforeFork(); - void AfterFork(int child_pid); - void Extend(uptr npcs); - void Add(uptr pc, u32 *guard); - void DumpOffsets(); - void DumpAll(); - - void InitializeGuardArray(s32 *guards); - void InitializeGuards(s32 *guards, uptr n, const char *module_name, - uptr caller_pc); - void ReinitializeGuards(); - - uptr *data(); - uptr size() const; - - private: - struct NamedPcRange { - const char *copied_module_name; - uptr beg, end; // elements [beg,end) in pc_array. - }; - - void DirectOpen(); - void UpdateModuleNameVec(uptr caller_pc, uptr range_beg, uptr range_end); - void GetRangeOffsets(const NamedPcRange& r, Symbolizer* s, - InternalMmapVector* offsets) const; - - // Maximal size pc array may ever grow. - // We MmapNoReserve this space to ensure that the array is contiguous. - static const uptr kPcArrayMaxSize = - FIRST_32_SECOND_64(1 << (SANITIZER_ANDROID ? 24 : 26), 1 << 27); - // The amount file mapping for the pc array is grown by. - static const uptr kPcArrayMmapSize = 64 * 1024; - - // pc_array is allocated with MmapNoReserveOrDie and so it uses only as - // much RAM as it really needs. - uptr *pc_array; - // Index of the first available pc_array slot. - atomic_uintptr_t pc_array_index; - // Array size. - atomic_uintptr_t pc_array_size; - // Current file mapped size of the pc array. - uptr pc_array_mapped_size; - // Descriptor of the file mapped pc array. - fd_t pc_fd; - - // Vector of coverage guard arrays, protected by mu. - InternalMmapVectorNoCtor guard_array_vec; - - // Vector of module and compilation unit pc ranges. - InternalMmapVectorNoCtor comp_unit_name_vec; - InternalMmapVectorNoCtor module_name_vec; - - StaticSpinMutex mu; -}; - -static CoverageData coverage_data; - -void CovUpdateMapping(const char *path, uptr caller_pc = 0); - -void CoverageData::DirectOpen() { - InternalScopedString path(kMaxPathLength); - internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.raw", - coverage_dir, internal_getpid()); - pc_fd = OpenFile(path.data(), RdWr); - if (pc_fd == kInvalidFd) { - Report("Coverage: failed to open %s for reading/writing\n", path.data()); - Die(); - } - - pc_array_mapped_size = 0; - CovUpdateMapping(coverage_dir); -} - -void CoverageData::Init() { - pc_fd = kInvalidFd; -} - -void CoverageData::Enable() { - if (pc_array) - return; - pc_array = reinterpret_cast( - MmapNoReserveOrDie(sizeof(uptr) * kPcArrayMaxSize, "CovInit")); - atomic_store(&pc_array_index, 0, memory_order_relaxed); - if (common_flags()->coverage_direct) { - Report("coverage_direct=1 is deprecated, don't use it.\n"); - Die(); - atomic_store(&pc_array_size, 0, memory_order_relaxed); - } else { - atomic_store(&pc_array_size, kPcArrayMaxSize, memory_order_relaxed); - } -} - -void CoverageData::InitializeGuardArray(s32 *guards) { - Enable(); // Make sure coverage is enabled at this point. - s32 n = guards[0]; - for (s32 j = 1; j <= n; j++) { - uptr idx = atomic_load_relaxed(&pc_array_index); - atomic_store_relaxed(&pc_array_index, idx + 1); - guards[j] = -static_cast(idx + 1); - } -} - -void CoverageData::Disable() { - if (pc_array) { - UnmapOrDie(pc_array, sizeof(uptr) * kPcArrayMaxSize); - pc_array = nullptr; - } - if (pc_fd != kInvalidFd) { - CloseFile(pc_fd); - pc_fd = kInvalidFd; - } -} - -void CoverageData::ReinitializeGuards() { - // Assuming single thread. - atomic_store(&pc_array_index, 0, memory_order_relaxed); - for (uptr i = 0; i < guard_array_vec.size(); i++) - InitializeGuardArray(guard_array_vec[i]); -} - -void CoverageData::ReInit() { - Disable(); - if (coverage_enabled) { - if (common_flags()->coverage_direct) { - // In memory-mapped mode we must extend the new file to the known array - // size. - uptr size = atomic_load(&pc_array_size, memory_order_relaxed); - uptr npcs = size / sizeof(uptr); - Enable(); - if (size) Extend(npcs); - if (coverage_enabled) CovUpdateMapping(coverage_dir); - } else { - Enable(); - } - } - // Re-initialize the guards. - // We are single-threaded now, no need to grab any lock. - CHECK_EQ(atomic_load(&pc_array_index, memory_order_relaxed), 0); - ReinitializeGuards(); -} - -void CoverageData::BeforeFork() { - mu.Lock(); -} - -void CoverageData::AfterFork(int child_pid) { - // We are single-threaded so it's OK to release the lock early. - mu.Unlock(); - if (child_pid == 0) ReInit(); -} - -// Extend coverage PC array to fit additional npcs elements. -void CoverageData::Extend(uptr npcs) { - if (!common_flags()->coverage_direct) return; - SpinMutexLock l(&mu); - - uptr size = atomic_load(&pc_array_size, memory_order_relaxed); - size += npcs * sizeof(uptr); - - if (coverage_enabled && size > pc_array_mapped_size) { - if (pc_fd == kInvalidFd) DirectOpen(); - CHECK_NE(pc_fd, kInvalidFd); - - uptr new_mapped_size = pc_array_mapped_size; - while (size > new_mapped_size) new_mapped_size += kPcArrayMmapSize; - CHECK_LE(new_mapped_size, sizeof(uptr) * kPcArrayMaxSize); - - // Extend the file and map the new space at the end of pc_array. - uptr res = internal_ftruncate(pc_fd, new_mapped_size); - int err; - if (internal_iserror(res, &err)) { - Printf("failed to extend raw coverage file: %d\n", err); - Die(); - } - - uptr next_map_base = ((uptr)pc_array) + pc_array_mapped_size; - void *p = MapWritableFileToMemory((void *)next_map_base, - new_mapped_size - pc_array_mapped_size, - pc_fd, pc_array_mapped_size); - CHECK_EQ((uptr)p, next_map_base); - pc_array_mapped_size = new_mapped_size; - } - - atomic_store(&pc_array_size, size, memory_order_release); -} - -void CoverageData::UpdateModuleNameVec(uptr caller_pc, uptr range_beg, - uptr range_end) { - auto sym = Symbolizer::GetOrInit(); - if (!sym) - return; - const char *module_name = sym->GetModuleNameForPc(caller_pc); - if (!module_name) return; - if (module_name_vec.empty() || - module_name_vec.back().copied_module_name != module_name) - module_name_vec.push_back({module_name, range_beg, range_end}); - else - module_name_vec.back().end = range_end; -} - -void CoverageData::InitializeGuards(s32 *guards, uptr n, - const char *comp_unit_name, - uptr caller_pc) { - // The array 'guards' has n+1 elements, we use the element zero - // to store 'n'. - CHECK_LT(n, 1 << 30); - guards[0] = static_cast(n); - InitializeGuardArray(guards); - SpinMutexLock l(&mu); - uptr range_end = atomic_load(&pc_array_index, memory_order_relaxed); - uptr range_beg = range_end - n; - comp_unit_name_vec.push_back({comp_unit_name, range_beg, range_end}); - guard_array_vec.push_back(guards); - UpdateModuleNameVec(caller_pc, range_beg, range_end); -} - -static const uptr kBundleCounterBits = 16; - -// When coverage_order_pcs==true and SANITIZER_WORDSIZE==64 -// we insert the global counter into the first 16 bits of the PC. -uptr BundlePcAndCounter(uptr pc, uptr counter) { - if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs) - return pc; - static const uptr kMaxCounter = (1 << kBundleCounterBits) - 1; - if (counter > kMaxCounter) - counter = kMaxCounter; - CHECK_EQ(0, pc >> (SANITIZER_WORDSIZE - kBundleCounterBits)); - return pc | (counter << (SANITIZER_WORDSIZE - kBundleCounterBits)); -} - -uptr UnbundlePc(uptr bundle) { - if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs) - return bundle; - return (bundle << kBundleCounterBits) >> kBundleCounterBits; -} - -uptr UnbundleCounter(uptr bundle) { - if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs) - return 0; - return bundle >> (SANITIZER_WORDSIZE - kBundleCounterBits); -} - -// If guard is negative, atomically set it to -guard and store the PC in -// pc_array. -void CoverageData::Add(uptr pc, u32 *guard) { - atomic_uint32_t *atomic_guard = reinterpret_cast(guard); - s32 guard_value = atomic_load(atomic_guard, memory_order_relaxed); - if (guard_value >= 0) return; - - atomic_store(atomic_guard, -guard_value, memory_order_relaxed); - if (!pc_array) return; - - uptr idx = -guard_value - 1; - if (idx >= atomic_load(&pc_array_index, memory_order_acquire)) - return; // May happen after fork when pc_array_index becomes 0. - CHECK_LT(idx, atomic_load(&pc_array_size, memory_order_acquire)); - uptr counter = atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed); - pc_array[idx] = BundlePcAndCounter(pc, counter); -} - -uptr *CoverageData::data() { - return pc_array; -} - -uptr CoverageData::size() const { - return atomic_load(&pc_array_index, memory_order_relaxed); -} - -// Block layout for packed file format: header, followed by module name (no -// trailing zero), followed by data blob. -struct CovHeader { - int pid; - unsigned int module_name_length; - unsigned int data_length; -}; - -static void CovWritePacked(int pid, const char *module, const void *blob, - unsigned int blob_size) { - if (cov_fd == kInvalidFd) return; - unsigned module_name_length = internal_strlen(module); - CovHeader header = {pid, module_name_length, blob_size}; - - if (cov_max_block_size == 0) { - // Writing to a file. Just go ahead. - WriteToFile(cov_fd, &header, sizeof(header)); - WriteToFile(cov_fd, module, module_name_length); - WriteToFile(cov_fd, blob, blob_size); - } else { - // Writing to a socket. We want to split the data into appropriately sized - // blocks. - InternalScopedBuffer block(cov_max_block_size); - CHECK_EQ((uptr)block.data(), (uptr)(CovHeader *)block.data()); - uptr header_size_with_module = sizeof(header) + module_name_length; - CHECK_LT(header_size_with_module, cov_max_block_size); - unsigned int max_payload_size = - cov_max_block_size - header_size_with_module; - char *block_pos = block.data(); - internal_memcpy(block_pos, &header, sizeof(header)); - block_pos += sizeof(header); - internal_memcpy(block_pos, module, module_name_length); - block_pos += module_name_length; - char *block_data_begin = block_pos; - const char *blob_pos = (const char *)blob; - while (blob_size > 0) { - unsigned int payload_size = Min(blob_size, max_payload_size); - blob_size -= payload_size; - internal_memcpy(block_data_begin, blob_pos, payload_size); - blob_pos += payload_size; - ((CovHeader *)block.data())->data_length = payload_size; - WriteToFile(cov_fd, block.data(), header_size_with_module + payload_size); - } - } -} - -// If packed = false: .. (name = module name). -// If packed = true and name == 0: ... -// If packed = true and name != 0: .. (name is -// user-supplied). -static fd_t CovOpenFile(InternalScopedString *path, bool packed, - const char *name, const char *extension = "sancov") { - path->clear(); - if (!packed) { - CHECK(name); - path->append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(), - extension); - } else { - if (!name) - path->append("%s/%zd.%s.packed", coverage_dir, internal_getpid(), - extension); - else - path->append("%s/%s.%s.packed", coverage_dir, name, extension); - } - error_t err; - fd_t fd = OpenFile(path->data(), WrOnly, &err); - if (fd == kInvalidFd) - Report("SanitizerCoverage: failed to open %s for writing (reason: %d)\n", - path->data(), err); - return fd; -} - -void CoverageData::GetRangeOffsets(const NamedPcRange& r, Symbolizer* sym, - InternalMmapVector* offsets) const { - offsets->clear(); - for (uptr i = 0; i < kNumWordsForMagic; i++) - offsets->push_back(0); - CHECK(r.copied_module_name); - CHECK_LE(r.beg, r.end); - CHECK_LE(r.end, size()); - for (uptr i = r.beg; i < r.end; i++) { - uptr pc = UnbundlePc(pc_array[i]); - uptr counter = UnbundleCounter(pc_array[i]); - if (!pc) continue; // Not visited. - uptr offset = 0; - sym->GetModuleNameAndOffsetForPC(pc, nullptr, &offset); - offsets->push_back(BundlePcAndCounter(offset, counter)); - } - - CHECK_GE(offsets->size(), kNumWordsForMagic); - SortArray(offsets->data(), offsets->size()); - for (uptr i = 0; i < offsets->size(); i++) - (*offsets)[i] = UnbundlePc((*offsets)[i]); -} - -static void GenerateHtmlReport(const InternalMmapVector &cov_files) { - if (!common_flags()->html_cov_report) { - return; - } - char *sancov_path = FindPathToBinary(common_flags()->sancov_path); - if (sancov_path == nullptr) { - return; - } - - InternalMmapVector sancov_argv(cov_files.size() * 2 + 3); - sancov_argv.push_back(sancov_path); - sancov_argv.push_back(internal_strdup("-html-report")); - auto argv_deleter = at_scope_exit([&] { - for (uptr i = 0; i < sancov_argv.size(); ++i) { - InternalFree(sancov_argv[i]); - } - }); - - for (const auto &cov_file : cov_files) { - sancov_argv.push_back(internal_strdup(cov_file)); - } - - { - ListOfModules modules; - modules.init(); - for (const LoadedModule &module : modules) { - sancov_argv.push_back(internal_strdup(module.full_name())); - } - } - - InternalScopedString report_path(kMaxPathLength); - fd_t report_fd = - CovOpenFile(&report_path, false /* packed */, GetProcessName(), "html"); - int pid = StartSubprocess(sancov_argv[0], sancov_argv.data(), - kInvalidFd /* stdin */, report_fd /* std_out */); - if (pid > 0) { - int result = WaitForProcess(pid); - if (result == 0) - Printf("coverage report generated to %s\n", report_path.data()); - } -} - -void CoverageData::DumpOffsets() { - auto sym = Symbolizer::GetOrInit(); - if (!common_flags()->coverage_pcs) return; - Printf("**\n***\n***\n"); - Printf("**WARNING: this implementation of SanitizerCoverage is deprecated\n"); - Printf("**WARNING: and will be removed in future versions\n"); - Printf("**WARNING: See https://clang.llvm.org/docs/SanitizerCoverage.html\n"); - Printf("**\n***\n***\n"); - - CHECK_NE(sym, nullptr); - InternalMmapVector offsets(0); - InternalScopedString path(kMaxPathLength); - - InternalMmapVector cov_files(module_name_vec.size()); - auto cov_files_deleter = at_scope_exit([&] { - for (uptr i = 0; i < cov_files.size(); ++i) { - InternalFree(cov_files[i]); - } - }); - - for (uptr m = 0; m < module_name_vec.size(); m++) { - auto r = module_name_vec[m]; - GetRangeOffsets(r, sym, &offsets); - - uptr num_offsets = offsets.size() - kNumWordsForMagic; - u64 *magic_p = reinterpret_cast(offsets.data()); - CHECK_EQ(*magic_p, 0ULL); - // FIXME: we may want to write 32-bit offsets even in 64-mode - // if all the offsets are small enough. - *magic_p = kMagic; - - const char *module_name = StripModuleName(r.copied_module_name); - if (cov_sandboxed) { - if (cov_fd != kInvalidFd) { - CovWritePacked(internal_getpid(), module_name, offsets.data(), - offsets.size() * sizeof(offsets[0])); - VReport(1, " CovDump: %zd PCs written to packed file\n", num_offsets); - } - } else { - // One file per module per process. - fd_t fd = CovOpenFile(&path, false /* packed */, module_name); - if (fd == kInvalidFd) continue; - WriteToFile(fd, offsets.data(), offsets.size() * sizeof(offsets[0])); - CloseFile(fd); - cov_files.push_back(internal_strdup(path.data())); - VReport(1, " CovDump: %s: %zd PCs written\n", path.data(), num_offsets); - } - } - if (cov_fd != kInvalidFd) - CloseFile(cov_fd); - - GenerateHtmlReport(cov_files); -} - -void CoverageData::DumpAll() { - if (!coverage_enabled || common_flags()->coverage_direct) return; - if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed)) - return; - DumpOffsets(); -} - -void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) { - if (!args) return; - if (!coverage_enabled) return; - cov_sandboxed = args->coverage_sandboxed; - if (!cov_sandboxed) return; - cov_max_block_size = args->coverage_max_block_size; - if (args->coverage_fd >= 0) { - cov_fd = (fd_t)args->coverage_fd; - } else { - InternalScopedString path(kMaxPathLength); - // Pre-open the file now. The sandbox won't allow us to do it later. - cov_fd = CovOpenFile(&path, true /* packed */, nullptr); - } -} - -fd_t MaybeOpenCovFile(const char *name) { - CHECK(name); - if (!coverage_enabled) return kInvalidFd; - InternalScopedString path(kMaxPathLength); - return CovOpenFile(&path, true /* packed */, name); -} - -void CovBeforeFork() { - coverage_data.BeforeFork(); -} - -void CovAfterFork(int child_pid) { - coverage_data.AfterFork(child_pid); -} - -static void MaybeDumpCoverage() { - if (common_flags()->coverage) - __sanitizer_cov_dump(); -} - -void InitializeCoverage(bool enabled, const char *dir) { - if (coverage_enabled) - return; // May happen if two sanitizer enable coverage in the same process. - coverage_enabled = enabled; - coverage_dir = dir; - coverage_data.Init(); - if (enabled) coverage_data.Enable(); - if (!common_flags()->coverage_direct) Atexit(__sanitizer_cov_dump); - AddDieCallback(MaybeDumpCoverage); -} - -void ReInitializeCoverage(bool enabled, const char *dir) { - coverage_enabled = enabled; - coverage_dir = dir; - coverage_data.ReInit(); -} - -void CoverageUpdateMapping() { - if (coverage_enabled) - CovUpdateMapping(coverage_dir); -} - -} // namespace __sanitizer - -extern "C" { -SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { - __sanitizer_dump_trace_pc_guard_coverage(); -} -SANITIZER_INTERFACE_ATTRIBUTE -sptr __sanitizer_maybe_open_cov_file(const char *name) { - return (sptr)MaybeOpenCovFile(name); -} -// Default empty implementations (weak). Users should redefine them. -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp4, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp8, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_switch, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} -} // extern "C" diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc index a98dde76e22a..24433356c63d 100644 --- a/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc +++ b/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc @@ -146,6 +146,17 @@ static TracePcGuardController pc_guard_controller; } // namespace } // namespace __sancov +namespace __sanitizer { +void InitializeCoverage(bool enabled, const char *dir) { + static bool coverage_enabled = false; + if (coverage_enabled) + return; // May happen if two sanitizer enable coverage in the same process. + coverage_enabled = enabled; + Atexit(__sanitizer_cov_dump); + AddDieCallback(__sanitizer_cov_dump); +} +} // namespace __sanitizer + extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT const uptr* pcs, uptr len) { @@ -166,4 +177,18 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage() { __sancov::pc_guard_controller.Dump(); } +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { + __sanitizer_dump_trace_pc_guard_coverage(); +} +// Default empty implementations (weak). Users should redefine them. +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp4, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp8, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_switch, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} } // extern "C" diff --git a/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc deleted file mode 100644 index 3477b065b06a..000000000000 --- a/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc +++ /dev/null @@ -1,122 +0,0 @@ -//===-- sanitizer_coverage_mapping.cc -------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Mmap-based implementation of sanitizer coverage. -// -// This is part of the implementation of code coverage that does not require -// __sanitizer_cov_dump() call. Data is stored in 2 files per process. -// -// $pid.sancov.map describes process memory layout in the following text-based -// format: -// // 1 line, 32 or 64 -// // repeated -// ... -// Mapping lines are NOT sorted. This file is updated every time memory layout -// is changed (i.e. in dlopen() and dlclose() interceptors). -// -// $pid.sancov.raw is a binary dump of PC values, sizeof(uptr) each. Again, not -// sorted. This file is extended by 64Kb at a time and mapped into memory. It -// contains one or more 0 words at the end, up to the next 64Kb aligned offset. -// -// To convert these 2 files to the usual .sancov format, run sancov.py rawunpack -// $pid.sancov.raw. -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_allocator_internal.h" -#include "sanitizer_libc.h" -#include "sanitizer_procmaps.h" - -namespace __sanitizer { - -static const uptr kMaxTextSize = 64 * 1024; - -struct CachedMapping { - public: - bool NeedsUpdate(uptr pc) { - int new_pid = internal_getpid(); - if (last_pid == new_pid && pc && pc >= last_range_start && - pc < last_range_end) - return false; - last_pid = new_pid; - return true; - } - - void SetModuleRange(uptr start, uptr end) { - last_range_start = start; - last_range_end = end; - } - - private: - uptr last_range_start, last_range_end; - int last_pid; -}; - -static CachedMapping cached_mapping; -static StaticSpinMutex mapping_mu; - -void CovUpdateMapping(const char *coverage_dir, uptr caller_pc) { - if (!common_flags()->coverage_direct) return; - - SpinMutexLock l(&mapping_mu); - - if (!cached_mapping.NeedsUpdate(caller_pc)) - return; - - InternalScopedString text(kMaxTextSize); - - { - text.append("%d\n", sizeof(uptr) * 8); - ListOfModules modules; - modules.init(); - for (const LoadedModule &module : modules) { - const char *module_name = StripModuleName(module.full_name()); - uptr base = module.base_address(); - for (const auto &range : module.ranges()) { - if (range.executable) { - uptr start = range.beg; - uptr end = range.end; - text.append("%zx %zx %zx %s\n", start, end, base, module_name); - if (caller_pc && caller_pc >= start && caller_pc < end) - cached_mapping.SetModuleRange(start, end); - } - } - } - } - - error_t err; - InternalScopedString tmp_path(64 + internal_strlen(coverage_dir)); - uptr res = internal_snprintf((char *)tmp_path.data(), tmp_path.size(), - "%s/%zd.sancov.map.tmp", coverage_dir, - internal_getpid()); - CHECK_LE(res, tmp_path.size()); - fd_t map_fd = OpenFile(tmp_path.data(), WrOnly, &err); - if (map_fd == kInvalidFd) { - Report("Coverage: failed to open %s for writing: %d\n", tmp_path.data(), - err); - Die(); - } - - if (!WriteToFile(map_fd, text.data(), text.length(), nullptr, &err)) { - Printf("sancov.map write failed: %d\n", err); - Die(); - } - CloseFile(map_fd); - - InternalScopedString path(64 + internal_strlen(coverage_dir)); - res = internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.map", - coverage_dir, internal_getpid()); - CHECK_LE(res, path.size()); - if (!RenameFile(tmp_path.data(), path.data(), &err)) { - Printf("sancov.map rename failed: %d\n", err); - Die(); - } -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index f87d8b6433ac..8c486b5b1b4d 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -138,16 +138,6 @@ COMMON_FLAG( bool, coverage, false, "If set, coverage information will be dumped at program shutdown (if the " "coverage instrumentation was enabled at compile time).") -COMMON_FLAG(bool, coverage_pcs, true, - "If set (and if 'coverage' is set too), the coverage information " - "will be dumped as a set of PC offsets for every module.") -COMMON_FLAG(bool, coverage_order_pcs, false, - "If true, the PCs will be dumped in the order they've" - " appeared during the execution.") -COMMON_FLAG(bool, coverage_direct, SANITIZER_ANDROID, - "If set, coverage information will be dumped directly to a memory " - "mapped file. This way data is not lost even if the process is " - "suddenly killed.") COMMON_FLAG(const char *, coverage_dir, ".", "Target directory for coverage dumps. Defaults to the current " "directory.") diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index 3bda35655d9e..7bc7682dd962 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -62,8 +62,6 @@ #if SANITIZER_FREEBSD #include #include -#include -#include #include extern "C" { // must be included after and on @@ -77,16 +75,6 @@ extern char **environ; // provided by crt1 #include #endif -#ifndef __GLIBC_PREREQ -#define __GLIBC_PREREQ(x, y) 0 -#endif - -#if SANITIZER_LINUX && __GLIBC_PREREQ(2, 16) -# define SANITIZER_USE_GETAUXVAL 1 -#else -# define SANITIZER_USE_GETAUXVAL 0 -#endif - #if SANITIZER_USE_GETAUXVAL #include #endif @@ -237,7 +225,8 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) { uptr internal_stat(const char *path, void *buf) { #if SANITIZER_FREEBSD - return internal_syscall(SYSCALL(stat), path, buf); + return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, + (uptr)buf, 0); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); @@ -261,7 +250,8 @@ uptr internal_stat(const char *path, void *buf) { uptr internal_lstat(const char *path, void *buf) { #if SANITIZER_FREEBSD - return internal_syscall(SYSCALL(lstat), path, buf); + return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, + (uptr)buf, AT_SYMLINK_NOFOLLOW); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, AT_SYMLINK_NOFOLLOW); @@ -604,7 +594,9 @@ uptr internal_getppid() { } uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { -#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +#if SANITIZER_FREEBSD + return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL); +#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count); #else return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count); diff --git a/lib/sanitizer_common/sanitizer_platform.h b/lib/sanitizer_common/sanitizer_platform.h index 49732aa32323..8fa3f7ab66fc 100644 --- a/lib/sanitizer_common/sanitizer_platform.h +++ b/lib/sanitizer_common/sanitizer_platform.h @@ -269,5 +269,14 @@ # define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0 #endif +#ifndef __GLIBC_PREREQ +#define __GLIBC_PREREQ(x, y) 0 +#endif + +#if SANITIZER_LINUX && __GLIBC_PREREQ(2, 16) +# define SANITIZER_USE_GETAUXVAL 1 +#else +# define SANITIZER_USE_GETAUXVAL 0 +#endif #endif // SANITIZER_PLATFORM_H diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h index c6f6a211573c..24ffcd7d94f4 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -23,6 +23,9 @@ // incorporates the map structure. # define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ ((link_map*)((handle) == nullptr ? nullptr : ((char*)(handle) + 544))) +// Get sys/_types.h, because that tells us whether 64-bit inodes are +// used in struct dirent below. +#include #else # define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map*)(handle)) #endif // !SANITIZER_FREEBSD @@ -485,7 +488,12 @@ namespace __sanitizer { }; #elif SANITIZER_FREEBSD struct __sanitizer_dirent { +#if defined(__INO64) + unsigned long long d_fileno; + unsigned long long d_off; +#else unsigned int d_fileno; +#endif unsigned short d_reclen; // more fields that we don't care about }; diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index 791ff4481ca8..5b1d53698707 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -264,7 +264,6 @@ void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { // Same for /proc/self/exe in the symbolizer. #if !SANITIZER_GO Symbolizer::GetOrInit()->PrepareForSandboxing(); - CovPrepareForSandboxing(args); #endif } diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index c912e8fa2aa3..afc3bb0ac678 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -400,9 +400,6 @@ void ReExec() { } void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { -#if !SANITIZER_GO - CovPrepareForSandboxing(args); -#endif } bool StackSizeIsUnlimited() { diff --git a/lib/sanitizer_common/scripts/check_lint.sh b/lib/sanitizer_common/scripts/check_lint.sh index 9108a81e26c8..82e4bc84d594 100755 --- a/lib/sanitizer_common/scripts/check_lint.sh +++ b/lib/sanitizer_common/scripts/check_lint.sh @@ -18,7 +18,7 @@ fi # Filters # TODO: remove some of these filters COMMON_LINT_FILTER=-build/include,-build/header_guard,-legal/copyright,-whitespace/comments,-readability/casting,\ --build/namespaces +-build/namespaces,-readability/braces ASAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int ASAN_TEST_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/sizeof,-runtime/int,-runtime/printf,-runtime/threadsafe_fn ASAN_LIT_TEST_LINT_FILTER=${ASAN_TEST_LINT_FILTER},-whitespace/line_length diff --git a/lib/sanitizer_common/tests/sanitizer_flags_test.cc b/lib/sanitizer_common/tests/sanitizer_flags_test.cc index 0af84a20b7f5..f3fe139e6ee8 100644 --- a/lib/sanitizer_common/tests/sanitizer_flags_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_flags_test.cc @@ -167,13 +167,13 @@ TEST(SanitizerCommon, CommonFlags) { cf.symbolize = false; cf.coverage = true; - cf.coverage_direct = true; + cf.heap_profile = true; cf.log_path = "path/one"; - parser.ParseString("symbolize=1:coverage_direct=false log_path='path/two'"); + parser.ParseString("symbolize=1:heap_profile=false log_path='path/two'"); EXPECT_TRUE(cf.symbolize); EXPECT_TRUE(cf.coverage); - EXPECT_FALSE(cf.coverage_direct); + EXPECT_FALSE(cf.heap_profile); EXPECT_STREQ("path/two", cf.log_path); } diff --git a/lib/ubsan/ubsan_checks.inc b/lib/ubsan/ubsan_checks.inc index 6e086414051e..0a87e6e8e3a4 100644 --- a/lib/ubsan/ubsan_checks.inc +++ b/lib/ubsan/ubsan_checks.inc @@ -19,6 +19,7 @@ UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined") UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null") +UBSAN_CHECK(PointerOverflow, "pointer-overflow", "pointer-overflow") UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", "alignment") UBSAN_CHECK(InsufficientObjectSize, "insufficient-object-size", "object-size") UBSAN_CHECK(SignedIntegerOverflow, "signed-integer-overflow", diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index d6a8f52a27b4..80cc8ad25790 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -554,6 +554,37 @@ void __ubsan::__ubsan_handle_nullability_arg_abort(NonNullArgData *Data) { Die(); } +static void handlePointerOverflowImpl(PointerOverflowData *Data, + ValueHandle Base, + ValueHandle Result, + ReportOptions Opts) { + SourceLocation Loc = Data->Loc.acquire(); + ErrorType ET = ErrorType::PointerOverflow; + + if (ignoreReport(Loc, Opts, ET)) + return; + + ScopedReport R(Opts, Loc, ET); + + Diag(Loc, DL_Error, "pointer index expression with base %0 overflowed to %1") + << (void *)Base << (void*)Result; +} + +void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data, + ValueHandle Base, + ValueHandle Result) { + GET_REPORT_OPTIONS(false); + handlePointerOverflowImpl(Data, Base, Result, Opts); +} + +void __ubsan::__ubsan_handle_pointer_overflow_abort(PointerOverflowData *Data, + ValueHandle Base, + ValueHandle Result) { + GET_REPORT_OPTIONS(true); + handlePointerOverflowImpl(Data, Base, Result, Opts); + Die(); +} + static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function, ReportOptions Opts) { if (Data->CheckKind != CFITCK_ICall) diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index 5857bc2495f5..483c18ced579 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -152,6 +152,13 @@ struct NonNullArgData { RECOVERABLE(nonnull_arg, NonNullArgData *Data) RECOVERABLE(nullability_arg, NonNullArgData *Data) +struct PointerOverflowData { + SourceLocation Loc; +}; + +RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base, + ValueHandle Result) + /// \brief Known CFI check kinds. /// Keep in sync with the enum of the same name in CodeGenFunction.h enum CFITypeCheckKind : unsigned char { diff --git a/lib/ubsan/ubsan_interface.inc b/lib/ubsan/ubsan_interface.inc index 0e43ebc68299..681476b3c91d 100644 --- a/lib/ubsan/ubsan_interface.inc +++ b/lib/ubsan/ubsan_interface.inc @@ -36,6 +36,8 @@ INTERFACE_FUNCTION(__ubsan_handle_nullability_return) INTERFACE_FUNCTION(__ubsan_handle_nullability_return_abort) INTERFACE_FUNCTION(__ubsan_handle_out_of_bounds) INTERFACE_FUNCTION(__ubsan_handle_out_of_bounds_abort) +INTERFACE_FUNCTION(__ubsan_handle_pointer_overflow) +INTERFACE_FUNCTION(__ubsan_handle_pointer_overflow_abort) INTERFACE_FUNCTION(__ubsan_handle_shift_out_of_bounds) INTERFACE_FUNCTION(__ubsan_handle_shift_out_of_bounds_abort) INTERFACE_FUNCTION(__ubsan_handle_sub_overflow) diff --git a/test/asan/TestCases/Android/coverage-android.cc b/test/asan/TestCases/Android/coverage-android.cc deleted file mode 100644 index cf4f33ebdb44..000000000000 --- a/test/asan/TestCases/Android/coverage-android.cc +++ /dev/null @@ -1,147 +0,0 @@ -// Test for direct coverage writing with dlopen. - -// Test normal exit, coverage level 1. -// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %T/libcoverage_android_test_1.so -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=func -DSO_DIR=\"%device\" %s -o %t - -// RUN: adb shell rm -rf %device/coverage-android -// RUN: rm -rf %T/coverage-android - -// RUN: adb shell mkdir -p %device/coverage-android/direct -// RUN: mkdir -p %T/coverage-android/direct -// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-android/direct:verbosity=1 %run %t -// RUN: adb pull %device/coverage-android/direct %T/coverage-android/direct -// RUN: ls; pwd -// RUN: cd %T/coverage-android/direct -// RUN: %sancov rawunpack *.sancov.raw -// RUN: %sancov print *.sancov |& FileCheck --check-prefix=CHECK1 %s - - -// Test sudden death, coverage level 1. -// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED -DKILL %s -shared -o %T/libcoverage_android_test_1.so -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=func -DSO_DIR=\"%device\" %s -o %t - -// RUN: adb shell rm -rf %device/coverage-android-kill -// RUN: rm -rf %T/coverage-android-kill - -// RUN: adb shell mkdir -p %device/coverage-android-kill/direct -// RUN: mkdir -p %T/coverage-android-kill/direct -// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-android-kill/direct:verbosity=1 not %run %t -// RUN: adb pull %device/coverage-android-kill/direct %T/coverage-android-kill/direct -// RUN: ls; pwd -// RUN: cd %T/coverage-android-kill/direct -// RUN: %sancov rawunpack *.sancov.raw -// RUN: %sancov print *.sancov |& FileCheck --check-prefix=CHECK1 %s - - -// Test normal exit, coverage level 2. -// RUN: %clangxx_asan -fsanitize-coverage=bb -DSHARED %s -shared -o %T/libcoverage_android_test_1.so -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=bb -DSO_DIR=\"%device\" %s -o %t - -// RUN: adb shell rm -rf %device/coverage-android -// RUN: rm -rf %T/coverage-android - -// RUN: adb shell mkdir -p %device/coverage-android/direct -// RUN: mkdir -p %T/coverage-android/direct -// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-android/direct:verbosity=1 %run %t -// RUN: adb pull %device/coverage-android/direct %T/coverage-android/direct -// RUN: ls; pwd -// RUN: cd %T/coverage-android/direct -// RUN: %sancov rawunpack *.sancov.raw -// RUN: %sancov print *.sancov |& FileCheck --check-prefix=CHECK2 %s - - -// Test sudden death, coverage level 2. -// RUN: %clangxx_asan -fsanitize-coverage=bb -DSHARED -DKILL %s -shared -o %T/libcoverage_android_test_1.so -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=bb -DSO_DIR=\"%device\" %s -o %t - -// RUN: adb shell rm -rf %device/coverage-android-kill -// RUN: rm -rf %T/coverage-android-kill - -// RUN: adb shell mkdir -p %device/coverage-android-kill/direct -// RUN: mkdir -p %T/coverage-android-kill/direct -// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-android-kill/direct:verbosity=1 not %run %t -// RUN: adb pull %device/coverage-android-kill/direct %T/coverage-android-kill/direct -// RUN: ls; pwd -// RUN: cd %T/coverage-android-kill/direct -// RUN: %sancov rawunpack *.sancov.raw -// RUN: %sancov print *.sancov |& FileCheck --check-prefix=CHECK2 %s - - -// Test normal exit, coverage level 3. -// RUN: %clangxx_asan -fsanitize-coverage=edge -DSHARED %s -shared -o %T/libcoverage_android_test_1.so -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=edge -DSO_DIR=\"%device\" %s -o %t - -// RUN: adb shell rm -rf %device/coverage-android -// RUN: rm -rf %T/coverage-android - -// RUN: adb shell mkdir -p %device/coverage-android/direct -// RUN: mkdir -p %T/coverage-android/direct -// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-android/direct:verbosity=1 %run %t -// RUN: adb pull %device/coverage-android/direct %T/coverage-android/direct -// RUN: ls; pwd -// RUN: cd %T/coverage-android/direct -// RUN: %sancov rawunpack *.sancov.raw -// RUN: %sancov print *.sancov |& FileCheck --check-prefix=CHECK3 %s - - -// Test sudden death, coverage level 3. -// RUN: %clangxx_asan -fsanitize-coverage=edge -DSHARED -DKILL %s -shared -o %T/libcoverage_android_test_1.so -fPIC -// RUN: %clangxx_asan -fsanitize-coverage=edge -DSO_DIR=\"%device\" %s -o %t - -// RUN: adb shell rm -rf %device/coverage-android-kill -// RUN: rm -rf %T/coverage-android-kill - -// RUN: adb shell mkdir -p %device/coverage-android-kill/direct -// RUN: mkdir -p %T/coverage-android-kill/direct -// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-android-kill/direct:verbosity=1 not %run %t -// RUN: adb pull %device/coverage-android-kill/direct %T/coverage-android-kill/direct -// RUN: ls; pwd -// RUN: cd %T/coverage-android-kill/direct -// RUN: %sancov rawunpack *.sancov.raw -// RUN: %sancov print *.sancov |& FileCheck --check-prefix=CHECK3 %s - -// PC counts in CHECK lines are platform dependent and match arm32 at the moment. -// sancov tool does not support Android well enough to match function names -// REQUIRES: arm - -#include -#include -#include -#include -#include -#include - -#ifdef SHARED -extern "C" { -void bar() { - printf("bar\n"); -#ifdef KILL - kill(getpid(), SIGKILL); -#endif -} -} -#else - -volatile int sink; - -int main(int argc, char **argv) { - fprintf(stderr, "PID: %d\n", getpid()); - void *handle1 = - dlopen(SO_DIR "/libcoverage_android_test_1.so", RTLD_LAZY); - assert(handle1); - - if (argc == 0) - sink = 0; - - void (*bar1)() = (void (*)())dlsym(handle1, "bar"); - assert(bar1); - bar1(); - - return 0; -} -#endif - -// CHECK1: 2 PCs total -// CHECK2: 4 PCs total -// CHECK3: 5 PCs total diff --git a/test/asan/TestCases/Linux/uar_signals.cc b/test/asan/TestCases/Linux/uar_signals.cc index f42c3f666554..f96a2fecb367 100644 --- a/test/asan/TestCases/Linux/uar_signals.cc +++ b/test/asan/TestCases/Linux/uar_signals.cc @@ -1,12 +1,13 @@ // This test checks that the implementation of use-after-return // is async-signal-safe. -// RUN: %clangxx_asan -O1 %s -o %t -pthread && %run %t +// RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread && %run %t // REQUIRES: stable-runtime #include #include #include #include #include +#include int *g; int n_signals; @@ -17,7 +18,6 @@ void SignalHandler(int, siginfo_t*, void*) { int local; g = &local; n_signals++; - // printf("s: %p\n", &local); } static void EnableSigprof(Sigaction SignalHandler) { @@ -49,22 +49,29 @@ void RecursiveFunction(int depth) { RecursiveFunction(depth - 1); } -void *Thread(void *) { - RecursiveFunction(18); +void *FastThread(void *) { + RecursiveFunction(1); + return NULL; +} + +void *SlowThread(void *) { + RecursiveFunction(1); return NULL; } int main(int argc, char **argv) { EnableSigprof(SignalHandler); - for (int i = 0; i < 4; i++) { - fprintf(stderr, "."); - const int kNumThread = sizeof(void*) == 8 ? 16 : 8; - pthread_t t[kNumThread]; - for (int i = 0; i < kNumThread; i++) - pthread_create(&t[i], 0, Thread, 0); - for (int i = 0; i < kNumThread; i++) - pthread_join(t[i], 0); + for (auto Thread : {&FastThread, &SlowThread}) { + for (int i = 0; i < 1000; i++) { + fprintf(stderr, "."); + const int kNumThread = sizeof(void*) == 8 ? 32 : 8; + pthread_t t[kNumThread]; + for (int i = 0; i < kNumThread; i++) + pthread_create(&t[i], 0, Thread, 0); + for (int i = 0; i < kNumThread; i++) + pthread_join(t[i], 0); + } + fprintf(stderr, "\n"); } - fprintf(stderr, "\n"); } diff --git a/test/asan/TestCases/Posix/coverage-maybe-open-file.cc b/test/asan/TestCases/Posix/coverage-maybe-open-file.cc deleted file mode 100644 index ee2977af11c4..000000000000 --- a/test/asan/TestCases/Posix/coverage-maybe-open-file.cc +++ /dev/null @@ -1,34 +0,0 @@ -// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 -// XFAIL: android -// UNSUPPORTED: ios -// -// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t -// RUN: rm -rf %T/coverage-maybe-open-file -// RUN: mkdir -p %T/coverage-maybe-open-file && cd %T/coverage-maybe-open-file -// RUN: %env_asan_opts=coverage=1 %run %t | FileCheck %s --check-prefix=CHECK-success -// RUN: %env_asan_opts=coverage=0 %run %t | FileCheck %s --check-prefix=CHECK-fail -// RUN: FileCheck %s < test.sancov.packed -implicit-check-not={{.}} --check-prefix=CHECK-test -// RUN: cd .. && rm -rf %T/coverage-maybe-open-file - -#include -#include -#include - -#include - -// FIXME: the code below might not work on Windows. -int main(int argc, char **argv) { - int fd = __sanitizer_maybe_open_cov_file("test"); - if (fd > 0) { - printf("SUCCESS\n"); - const char s[] = "test\n"; - write(fd, s, strlen(s)); - close(fd); - } else { - printf("FAIL\n"); - } -} - -// CHECK-success: SUCCESS -// CHECK-fail: FAIL -// CHECK-test: {{^}}test{{$}} diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc new file mode 100644 index 000000000000..b7246ebf2751 --- /dev/null +++ b/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc @@ -0,0 +1,23 @@ +// Tests -fsanitize-coverage=inline-8bit-counters +// +// REQUIRES: has_sancovcc,stable-runtime +// UNSUPPORTED: i386-darwin +// +// RUN: %clangxx -O0 %s -fsanitize-coverage=inline-8bit-counters 2>&1 + +#include +#include + +const char *first_counter; + +extern "C" +void __sanitizer_cov_8bit_counters_init(const char *start, const char *end) { + printf("INIT: %p %p\n", start, end); + assert(end - start > 1); + first_counter = start; +} + +int main() { + assert(first_counter); + assert(*first_counter == 1); +} diff --git a/test/ubsan/TestCases/Pointer/index-overflow.cpp b/test/ubsan/TestCases/Pointer/index-overflow.cpp new file mode 100644 index 000000000000..eb7f95e85c2c --- /dev/null +++ b/test/ubsan/TestCases/Pointer/index-overflow.cpp @@ -0,0 +1,19 @@ +// RUN: %clangxx -fsanitize=pointer-overflow %s -o %t +// RUN: %t 1 2>&1 | FileCheck %s --check-prefix=ERR +// RUN: %t 0 2>&1 | FileCheck %s --check-prefix=SAFE +// RUN: %t -1 2>&1 | FileCheck %s --check-prefix=SAFE + +#include +#include +#include + +int main(int argc, char *argv[]) { + // SAFE-NOT: runtime error + // ERR: runtime error: pointer index expression with base {{.*}} overflowed to + + char *p = (char *)(UINTPTR_MAX); + + printf("%p\n", p + atoi(argv[1])); + + return 0; +} From 60bb8ce74a67345b14fd540dd739254f562c605b Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 3 Jun 2017 15:21:27 +0000 Subject: [PATCH 11/22] Vendor import of lldb trunk r304659: https://llvm.org/svn/llvm-project/lldb/trunk@304659 --- cmake/modules/LLDBConfig.cmake | 22 --- cmake/modules/LLDBGenerateConfig.cmake | 9 ++ include/lldb/Host/Config.h.cmake | 4 + include/lldb/Host/linux/Uio.h | 3 +- .../objc/objc-new-syntax/TestObjCNewSyntax.py | 131 ++++++++++++++++-- source/Host/linux/LibcGlue.cpp | 8 +- .../Platform/MacOSX/PlatformDarwin.cpp | 77 ++++++++++ .../Plugins/Platform/MacOSX/PlatformDarwin.h | 8 +- .../Platform/MacOSX/PlatformMacOSX.cpp | 4 + .../MacOSX/PlatformRemoteDarwinDevice.cpp | 68 +-------- source/Symbol/ClangASTContext.cpp | 5 + unittests/CMakeLists.txt | 2 +- 12 files changed, 239 insertions(+), 102 deletions(-) diff --git a/cmake/modules/LLDBConfig.cmake b/cmake/modules/LLDBConfig.cmake index 79512941fd8d..bbf7a0838d26 100644 --- a/cmake/modules/LLDBConfig.cmake +++ b/cmake/modules/LLDBConfig.cmake @@ -334,28 +334,6 @@ if (HAVE_LIBDL) list(APPEND system_libs ${CMAKE_DL_LIBS}) endif() -# Check for syscall used by lldb-server on linux. -# If these are not found, it will fall back to ptrace (slow) for memory reads. -check_cxx_source_compiles(" - #include - int main() { process_vm_readv(0, nullptr, 0, nullptr, 0, 0); return 0; }" - HAVE_PROCESS_VM_READV) - -if (HAVE_PROCESS_VM_READV) - add_definitions(-DHAVE_PROCESS_VM_READV) -else() - # If we don't have the syscall wrapper function, but we know the syscall number, we can - # still issue the syscall manually - check_cxx_source_compiles(" - #include - int main() { return __NR_process_vm_readv; }" - HAVE_NR_PROCESS_VM_READV) - - if (HAVE_NR_PROCESS_VM_READV) - add_definitions(-DHAVE_NR_PROCESS_VM_READV) - endif() -endif() - # Figure out if lldb could use lldb-server. If so, then we'll # ensure we build lldb-server when an lldb target is being built. if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD") diff --git a/cmake/modules/LLDBGenerateConfig.cmake b/cmake/modules/LLDBGenerateConfig.cmake index f812cf11614a..d3d0cb220b93 100644 --- a/cmake/modules/LLDBGenerateConfig.cmake +++ b/cmake/modules/LLDBGenerateConfig.cmake @@ -12,6 +12,15 @@ check_symbol_exists(sigaction signal.h HAVE_SIGACTION) check_include_file(termios.h HAVE_TERMIOS_H) check_include_files("sys/types.h;sys/event.h" HAVE_SYS_EVENT_H) +check_cxx_source_compiles(" + #include + int main() { process_vm_readv(0, nullptr, 0, nullptr, 0, 0); return 0; }" + HAVE_PROCESS_VM_READV) +check_cxx_source_compiles(" + #include + int main() { return __NR_process_vm_readv; }" + HAVE_NR_PROCESS_VM_READV) + # These checks exist in LLVM's configuration, so I want to match the LLVM names # so that the check isn't duplicated, but we translate them into the LLDB names # so that I don't have to change all the uses at the moment. diff --git a/include/lldb/Host/Config.h.cmake b/include/lldb/Host/Config.h.cmake index 5a16425fe0a9..0deedd151a5e 100644 --- a/include/lldb/Host/Config.h.cmake +++ b/include/lldb/Host/Config.h.cmake @@ -20,4 +20,8 @@ #cmakedefine01 HAVE_SIGACTION +#cmakedefine01 HAVE_PROCESS_VM_READV + +#cmakedefine01 HAVE_NR_PROCESS_VM_READV + #endif // #ifndef LLDB_HOST_CONFIG_H diff --git a/include/lldb/Host/linux/Uio.h b/include/lldb/Host/linux/Uio.h index 8b964d3f3e25..0b8b7dbf6fb9 100644 --- a/include/lldb/Host/linux/Uio.h +++ b/include/lldb/Host/linux/Uio.h @@ -10,11 +10,12 @@ #ifndef liblldb_Host_linux_Uio_h_ #define liblldb_Host_linux_Uio_h_ +#include "lldb/Host/Config.h" #include // We shall provide our own implementation of process_vm_readv if it is not // present -#ifndef HAVE_PROCESS_VM_READV +#if !HAVE_PROCESS_VM_READV ssize_t process_vm_readv(::pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags); diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py index add3f7a01ad6..96c5a33f14b0 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py @@ -26,16 +26,7 @@ def setUp(self): # Find the line number to break inside main(). self.line = line_number('main.m', '// Set breakpoint 0 here.') - @skipUnlessDarwin - @expectedFailureAll( - oslist=['macosx'], - compiler='clang', - compiler_version=[ - '<', - '7.0.0']) - @skipIf(macos_version=["<", "10.12"]) - @expectedFailureAll(archs=["i[3-6]86"]) - def test_expr(self): + def runToBreakpoint(self): self.build() exe = os.path.join(os.getcwd(), "a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) @@ -55,6 +46,18 @@ def test_expr(self): self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, substrs=[' resolved, hit count = 1']) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_read_array(self): + self.runToBreakpoint() + self.expect( "expr --object-description -- immutable_array[0]", VARIABLES_DISPLAYED_CORRECTLY, @@ -65,6 +68,18 @@ def test_expr(self): VARIABLES_DISPLAYED_CORRECTLY, substrs=["foo"]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_update_array(self): + self.runToBreakpoint() + self.expect( "expr --object-description -- mutable_array[0] = @\"bar\"", VARIABLES_DISPLAYED_CORRECTLY, @@ -75,6 +90,18 @@ def test_expr(self): VARIABLES_DISPLAYED_CORRECTLY, substrs=["bar"]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_read_dictionary(self): + self.runToBreakpoint() + self.expect( "expr --object-description -- immutable_dictionary[@\"key\"]", VARIABLES_DISPLAYED_CORRECTLY, @@ -85,6 +112,18 @@ def test_expr(self): VARIABLES_DISPLAYED_CORRECTLY, substrs=["value"]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_update_dictionary(self): + self.runToBreakpoint() + self.expect( "expr --object-description -- mutable_dictionary[@\"key\"] = @\"object\"", VARIABLES_DISPLAYED_CORRECTLY, @@ -95,6 +134,18 @@ def test_expr(self): VARIABLES_DISPLAYED_CORRECTLY, substrs=["object"]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_array_literal(self): + self.runToBreakpoint() + self.expect( "expr --object-description -- @[ @\"foo\", @\"bar\" ]", VARIABLES_DISPLAYED_CORRECTLY, @@ -103,6 +154,18 @@ def test_expr(self): "foo", "bar"]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_dictionary_literal(self): + self.runToBreakpoint() + self.expect( "expr --object-description -- @{ @\"key\" : @\"object\" }", VARIABLES_DISPLAYED_CORRECTLY, @@ -110,9 +173,33 @@ def test_expr(self): "key", "object"]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_char_literal(self): + self.runToBreakpoint() + self.expect("expr --object-description -- @'a'", VARIABLES_DISPLAYED_CORRECTLY, substrs=[str(ord('a'))]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_integer_literals(self): + self.runToBreakpoint() + self.expect( "expr --object-description -- @1", VARIABLES_DISPLAYED_CORRECTLY, @@ -138,9 +225,33 @@ def test_expr(self): VARIABLES_DISPLAYED_CORRECTLY, substrs=["1"]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_float_literal(self): + self.runToBreakpoint() + self.expect("expr -- @123.45", VARIABLES_DISPLAYED_CORRECTLY, substrs=["NSNumber", "123.45"]) + @skipUnlessDarwin + @expectedFailureAll( + oslist=['macosx'], + compiler='clang', + compiler_version=[ + '<', + '7.0.0']) + @skipIf(macos_version=["<", "10.12"]) + @expectedFailureAll(archs=["i[3-6]86"]) + def test_expressions_in_literals(self): + self.runToBreakpoint() + self.expect( "expr --object-description -- @( 1 + 3 )", VARIABLES_DISPLAYED_CORRECTLY, diff --git a/source/Host/linux/LibcGlue.cpp b/source/Host/linux/LibcGlue.cpp index c036bb28a9bc..93d2a41d2eb1 100644 --- a/source/Host/linux/LibcGlue.cpp +++ b/source/Host/linux/LibcGlue.cpp @@ -14,13 +14,13 @@ #include #include -#ifndef HAVE_PROCESS_VM_READV // If the syscall wrapper is not available, - // provide one. +#if !HAVE_PROCESS_VM_READV +// If the syscall wrapper is not available, provide one. ssize_t process_vm_readv(::pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags) { -#ifdef HAVE_NR_PROCESS_VM_READV // If we have the syscall number, we can issue - // the syscall ourselves. +#if HAVE_NR_PROCESS_VM_READV + // If we have the syscall number, we can issue the syscall ourselves. return syscall(__NR_process_vm_readv, pid, local_iov, liovcnt, remote_iov, riovcnt, flags); #else // If not, let's pretend the syscall is not present. diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index d69a02e41d51..a29cc9e1ed86 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -33,6 +33,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Utility/DataBufferLLVM.h" @@ -1763,3 +1764,79 @@ PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) { // Let our parent class do the real launching. return PlatformPOSIX::LaunchProcess(launch_info); } + +lldb_private::Status +PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec, Process *process, + ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, + ModuleSP *old_module_sp_ptr, bool *did_create_ptr) +{ + const FileSpec &platform_file = module_spec.GetFileSpec(); + // See if the file is present in any of the module_search_paths_ptr directories. + if (!module_sp && module_search_paths_ptr && platform_file) { + // create a vector of all the file / directory names in platform_file + // e.g. this might be + // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation + // + // We'll need to look in the module_search_paths_ptr directories for + // both "UIFoundation" and "UIFoundation.framework" -- most likely the + // latter will be the one we find there. + + FileSpec platform_pull_apart(platform_file); + std::vector path_parts; + ConstString unix_root_dir("/"); + while (true) { + ConstString part = platform_pull_apart.GetLastPathComponent(); + platform_pull_apart.RemoveLastPathComponent(); + if (part.IsEmpty() || part == unix_root_dir) + break; + path_parts.push_back(part.AsCString()); + } + const size_t path_parts_size = path_parts.size(); + + size_t num_module_search_paths = module_search_paths_ptr->GetSize(); + for (size_t i = 0; i < num_module_search_paths; ++i) { + Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log_verbose) + log_verbose->Printf ("PlatformRemoteDarwinDevice::GetSharedModule searching for binary in search-path %s", module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str()); + // Create a new FileSpec with this module_search_paths_ptr + // plus just the filename ("UIFoundation"), then the parent + // dir plus filename ("UIFoundation.framework/UIFoundation") + // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") + + for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { + FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); + + // Add the components backwards. For + // .../PrivateFrameworks/UIFoundation.framework/UIFoundation + // path_parts is + // [0] UIFoundation + // [1] UIFoundation.framework + // [2] PrivateFrameworks + // + // and if 'j' is 2, we want to append path_parts[1] and then + // path_parts[0], aka + // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr + // path. + + for (int k = j; k >= 0; --k) { + path_to_try.AppendPathComponent(path_parts[k]); + } + + if (path_to_try.Exists()) { + ModuleSpec new_module_spec(module_spec); + new_module_spec.GetFileSpec() = path_to_try; + Status new_error(Platform::GetSharedModule( + new_module_spec, process, module_sp, NULL, old_module_sp_ptr, + did_create_ptr)); + + if (module_sp) { + module_sp->SetPlatformFileSpec(path_to_try); + return new_error; + } + } + } + } + } + return Status(); +} diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h index 6495609ac495..c04318e98cae 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -128,9 +128,15 @@ class PlatformDarwin : public PlatformPOSIX { std::vector &options, SDKType sdk_type); + const char *GetDeveloperDirectory(); + + lldb_private::Status + FindBundleBinaryInExecSearchPaths (const lldb_private::ModuleSpec &module_spec, lldb_private::Process *process, + lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr, + lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); + std::string m_developer_directory; - const char *GetDeveloperDirectory(); private: DISALLOW_COPY_AND_ASSIGN(PlatformDarwin); diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp index c08417a80ae4..43f4d8bbf023 100644 --- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -339,5 +339,9 @@ lldb_private::Status PlatformMacOSX::GetSharedModule( } } } + + if (!module_sp) { + error = FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); + } return error; } diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp index f7395fb8cf3d..ea44714a916e 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp @@ -605,70 +605,12 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( // See if the file is present in any of the module_search_paths_ptr // directories. - if (!module_sp && module_search_paths_ptr && platform_file) { - // create a vector of all the file / directory names in platform_file - // e.g. this might be - // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation - // - // We'll need to look in the module_search_paths_ptr directories for - // both "UIFoundation" and "UIFoundation.framework" -- most likely the - // latter will be the one we find there. + if (!module_sp) + error = PlatformDarwin::FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp, + module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); - FileSpec platform_pull_apart(platform_file); - std::vector path_parts; - ConstString unix_root_dir("/"); - while (true) { - ConstString part = platform_pull_apart.GetLastPathComponent(); - platform_pull_apart.RemoveLastPathComponent(); - if (part.IsEmpty() || part == unix_root_dir) - break; - path_parts.push_back(part.AsCString()); - } - const size_t path_parts_size = path_parts.size(); - - size_t num_module_search_paths = module_search_paths_ptr->GetSize(); - for (size_t i = 0; i < num_module_search_paths; ++i) { - LLDB_LOGV(log, "searching for binary in search-path {0}", - module_search_paths_ptr->GetFileSpecAtIndex(i)); - // Create a new FileSpec with this module_search_paths_ptr - // plus just the filename ("UIFoundation"), then the parent - // dir plus filename ("UIFoundation.framework/UIFoundation") - // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") - - for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { - FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); - - // Add the components backwards. For - // .../PrivateFrameworks/UIFoundation.framework/UIFoundation - // path_parts is - // [0] UIFoundation - // [1] UIFoundation.framework - // [2] PrivateFrameworks - // - // and if 'j' is 2, we want to append path_parts[1] and then - // path_parts[0], aka - // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr - // path. - - for (int k = j; k >= 0; --k) { - path_to_try.AppendPathComponent(path_parts[k]); - } - - if (path_to_try.Exists()) { - ModuleSpec new_module_spec(module_spec); - new_module_spec.GetFileSpec() = path_to_try; - Status new_error(Platform::GetSharedModule( - new_module_spec, process, module_sp, NULL, old_module_sp_ptr, - did_create_ptr)); - - if (module_sp) { - module_sp->SetPlatformFileSpec(path_to_try); - return new_error; - } - } - } - } - } + if (error.Success()) + return error; const bool always_create = false; error = ModuleList::GetSharedModule( diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp index 94c91fe335a7..c8738e6e5502 100644 --- a/source/Symbol/ClangASTContext.cpp +++ b/source/Symbol/ClangASTContext.cpp @@ -3938,6 +3938,11 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, const clang::Type::TypeClass type_class = qual_type->getTypeClass(); switch (type_class) { + case clang::Type::Attributed: + return GetTypeInfo( + qual_type->getAs() + ->getModifiedType().getAsOpaquePtr(), + pointee_or_element_clang_type); case clang::Type::Builtin: { const clang::BuiltinType *builtin_type = llvm::dyn_cast( qual_type->getCanonicalTypeInternal()); diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index f4c735e78e34..f78879db09b4 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -40,7 +40,7 @@ function(add_lldb_unittest test_name) POST_BUILD COMMAND "${CMAKE_COMMAND}" -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/Inputs) - target_link_libraries(${test_name} ${ARG_LINK_LIBS} ${CLANG_USED_LIBS} ${LLDB_SYSTEM_LIBS}) + target_link_libraries(${test_name} ${ARG_LINK_LIBS} ${LLDB_SYSTEM_LIBS}) endfunction() function(add_unittest_inputs test_name inputs) From 1b08b196ac845675036ac78f3ac927d0a37f707c Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 10 Jun 2017 13:44:22 +0000 Subject: [PATCH 12/22] Vendor import of clang trunk r305145: https://llvm.org/svn/llvm-project/cfe/trunk@305145 --- bindings/python/clang/cindex.py | 11 + bindings/python/tests/cindex/test_type.py | 17 ++ docs/ClangFormatStyleOptions.rst | 2 +- docs/LanguageExtensions.rst | 42 +++ docs/LibASTMatchersReference.html | 102 +++++-- include/clang-c/Index.h | 19 +- include/clang/AST/Decl.h | 58 +++- include/clang/AST/ExternalASTMerger.h | 2 + include/clang/AST/RecursiveASTVisitor.h | 16 +- include/clang/ASTMatchers/ASTMatchers.h | 44 ++- .../clang/ASTMatchers/Dynamic/Diagnostics.h | 2 +- include/clang/ASTMatchers/Dynamic/Parser.h | 4 +- .../clang/ASTMatchers/Dynamic/VariantValue.h | 23 ++ include/clang/Basic/Attr.td | 36 +++ .../clang/Basic/DiagnosticFrontendKinds.td | 1 + include/clang/Basic/DiagnosticLexKinds.td | 4 + include/clang/Basic/DiagnosticParseKinds.td | 9 + include/clang/Basic/DiagnosticSemaKinds.td | 5 + .../Basic/DiagnosticSerializationKinds.td | 9 + include/clang/Basic/LangOptions.h | 1 + include/clang/Basic/SourceManager.h | 4 + include/clang/Driver/Options.td | 8 + include/clang/Edit/EditedSource.h | 8 +- include/clang/Frontend/ASTUnit.h | 54 ++-- include/clang/Frontend/CodeGenOptions.def | 3 +- include/clang/Frontend/CompilerInstance.h | 10 + include/clang/Frontend/FrontendAction.h | 9 +- include/clang/Frontend/FrontendActions.h | 9 +- .../Frontend/PreprocessorOutputOptions.h | 2 + include/clang/Lex/ModuleLoader.h | 34 +++ include/clang/Lex/Preprocessor.h | 8 + include/clang/Lex/PreprocessorOptions.h | 4 + include/clang/Parse/Parser.h | 4 +- .../clang/Rewrite/Frontend/FrontendActions.h | 7 +- include/clang/Sema/Overload.h | 9 +- include/clang/Sema/Sema.h | 47 +++- .../Core/BugReporter/PathDiagnostic.h | 16 +- include/clang/Tooling/Tooling.h | 9 +- lib/AST/ASTContext.cpp | 5 +- lib/AST/ASTImporter.cpp | 7 +- lib/AST/CMakeLists.txt | 5 +- lib/AST/Decl.cpp | 19 +- lib/AST/DeclObjC.cpp | 18 +- lib/AST/ODRHash.cpp | 27 +- lib/AST/StmtProfile.cpp | 5 +- lib/AST/Type.cpp | 2 +- lib/ASTMatchers/Dynamic/Diagnostics.cpp | 4 +- lib/ASTMatchers/Dynamic/Marshallers.h | 20 ++ lib/ASTMatchers/Dynamic/Parser.cpp | 63 +++-- lib/ASTMatchers/Dynamic/Registry.cpp | 28 +- lib/ASTMatchers/Dynamic/VariantValue.cpp | 64 +++++ lib/Basic/SourceManager.cpp | 41 ++- lib/Basic/Targets.cpp | 33 ++- lib/CodeGen/BackendUtil.cpp | 2 +- lib/CodeGen/CGBlocks.cpp | 62 ++--- lib/CodeGen/CGCXXABI.cpp | 8 +- lib/CodeGen/CGDebugInfo.cpp | 19 +- lib/CodeGen/CGDecl.cpp | 7 + lib/CodeGen/CGDeclCXX.cpp | 6 +- lib/CodeGen/CGException.cpp | 13 +- lib/CodeGen/CGExpr.cpp | 8 +- lib/CodeGen/CGObjC.cpp | 28 +- lib/CodeGen/CGObjCMac.cpp | 65 +++-- lib/CodeGen/CGOpenMPRuntime.cpp | 91 ++++--- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 49 ++-- lib/CodeGen/CGStmtOpenMP.cpp | 5 +- lib/CodeGen/CodeGenFunction.cpp | 5 +- lib/CodeGen/CodeGenModule.cpp | 30 ++- lib/CodeGen/ItaniumCXXABI.cpp | 6 +- lib/CodeGen/MicrosoftCXXABI.cpp | 29 +- lib/Driver/CMakeLists.txt | 1 + lib/Driver/Driver.cpp | 7 + lib/Driver/SanitizerArgs.cpp | 4 +- lib/Driver/ToolChains/Arch/Mips.cpp | 7 + lib/Driver/ToolChains/Clang.cpp | 7 +- lib/Driver/ToolChains/Linux.cpp | 5 +- lib/Driver/ToolChains/MSVC.cpp | 4 +- lib/Edit/EditedSource.cpp | 37 +-- lib/Format/ContinuationIndenter.cpp | 4 +- lib/Format/TokenAnnotator.cpp | 12 +- lib/Format/WhitespaceManager.cpp | 60 ++++- lib/Frontend/ASTMerge.cpp | 5 +- lib/Frontend/ASTUnit.cpp | 92 +++++-- lib/Frontend/CompilerInstance.cpp | 254 ++++++++++++------ lib/Frontend/CompilerInvocation.cpp | 5 +- lib/Frontend/FrontendAction.cpp | 108 +++++--- lib/Frontend/FrontendActions.cpp | 14 +- lib/Frontend/Rewrite/CMakeLists.txt | 1 + lib/Frontend/Rewrite/FrontendActions.cpp | 121 +++++++-- .../ExecuteCompilerInvocation.cpp | 3 +- lib/Headers/avxintrin.h | 2 +- lib/Headers/bmiintrin.h | 8 +- lib/Headers/emmintrin.h | 32 ++- lib/Headers/xmmintrin.h | 2 +- lib/Lex/PPDirectives.cpp | 44 +-- lib/Lex/Pragma.cpp | 131 ++++++++- lib/Lex/Preprocessor.cpp | 10 +- lib/Parse/ParseDeclCXX.cpp | 4 +- lib/Parse/ParsePragma.cpp | 60 +++++ lib/Sema/SemaAttr.cpp | 30 +++ lib/Sema/SemaCodeComplete.cpp | 1 + lib/Sema/SemaDecl.cpp | 25 ++ lib/Sema/SemaDeclCXX.cpp | 43 ++- lib/Sema/SemaExpr.cpp | 39 ++- lib/Sema/SemaExprCXX.cpp | 18 +- lib/Sema/SemaLookup.cpp | 13 +- lib/Sema/SemaOverload.cpp | 224 +++++---------- lib/Sema/SemaStmt.cpp | 20 +- lib/Sema/SemaTemplate.cpp | 46 ++-- lib/Sema/SemaTemplateDeduction.cpp | 116 +++++--- lib/Sema/SemaTemplateInstantiate.cpp | 41 ++- lib/Sema/SemaTemplateInstantiateDecl.cpp | 22 +- lib/Sema/SemaType.cpp | 2 +- lib/Serialization/ASTReader.cpp | 17 +- lib/Serialization/ASTReaderDecl.cpp | 86 +++--- lib/Serialization/ASTWriter.cpp | 2 + lib/Serialization/ASTWriterDecl.cpp | 5 + .../Checkers/NullabilityChecker.cpp | 2 +- lib/StaticAnalyzer/Core/BugReporter.cpp | 12 +- lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 46 +++- test/Analysis/nullability-notes.m | 204 ++++++++++++++ test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp | 28 ++ .../dcl.meaning/dcl.fct.default/p4.cpp | 33 +++ test/CXX/drs/dr13xx.cpp | 13 +- test/CXX/temp/temp.decls/temp.mem/p5.cpp | 13 + .../temp.deduct/temp.deduct.call/p4.cpp | 9 +- test/CodeGen/arm-long-calls.c | 4 +- test/CodeGen/arm-no-movt.c | 4 +- test/CodeGen/arm-target-attr.c | 19 ++ test/CodeGen/arm-target-features.c | 34 ++- test/CodeGen/arm-thumb-mode-target-feature.c | 33 +++ test/CodeGen/captured-statements.c | 7 +- test/CodeGen/mips-madd4.c | 87 ++++++ test/CodeGen/neon-aapcs-align.c | 17 ++ test/CodeGenCXX/captured-statements.cpp | 17 +- test/CodeGenCXX/clang-sections-tentative.c | 41 +++ test/CodeGenCXX/clang-sections.cpp | 78 ++++++ test/CodeGenObjC/exceptions-asm-attribute.m | 10 +- test/CodeGenObjC/image-info.m | 4 +- test/CodeGenObjC/metadata-symbols-64.m | 16 +- test/CodeGenObjC/metadata_symbols.m | 10 +- test/CodeGenObjC/non-lazy-classes.m | 6 +- test/CodeGenObjC/sections.m | 72 +++++ test/Driver/baremetal.cpp | 4 +- test/Driver/cl-link.c | 2 +- test/Driver/fsanitize-coverage.c | 1 + test/Driver/fsanitize.c | 6 + test/FixIt/fixit-format-darwin.m | 59 ++++ test/FixIt/fixit.c | 3 +- test/Headers/ms-cppoperkey.cpp | 16 ++ test/Headers/ms-cppoperkey1.cpp | 27 ++ test/Headers/ms-cppoperkey2.cpp | 11 + test/Index/pipe-size.cl | 16 ++ test/Index/singe-file-parse.m | 11 + .../crash-typo-correction-visibility/module.h | 1 + .../module.modulemap | 3 + .../crash-typo-correction-visibility.cpp | 10 + test/Modules/preprocess-build-diamond.m | 26 ++ test/Modules/preprocess-build.cpp | 35 +++ test/Modules/preprocess-module.cpp | 26 +- test/Modules/requires-coroutines.mm | 11 +- test/Modules/requires-gnuinlineasm.m | 4 +- test/Modules/requires.m | 17 +- test/Modules/requires.mm | 8 +- test/Preprocessor/init.c | 14 +- test/Sema/2010-05-31-palignr.c | 8 +- test/Sema/ext_vector_ops.c | 27 ++ test/Sema/pragma-clang-section.c | 17 ++ test/SemaCXX/PR27037.cpp | 13 + test/SemaCXX/cxx0x-cursory-default-delete.cpp | 6 +- .../cxx1y-generic-lambdas-capturing.cpp | 4 + ...xx1z-class-template-argument-deduction.cpp | 32 +++ test/SemaCXX/cxx1z-noexcept-function-type.cpp | 2 +- test/SemaTemplate/deduction.cpp | 6 +- .../dependent-template-recover.cpp | 22 ++ test/SemaTemplate/temp_arg_type.cpp | 54 ++++ tools/c-index-test/c-index-test.c | 30 +++ tools/clang-check/ClangCheck.cpp | 3 +- tools/clang-format/ClangFormat.cpp | 3 +- .../ClangOffloadBundler.cpp | 3 +- tools/driver/cc1as_main.cpp | 10 +- tools/libclang/CIndex.cpp | 6 +- tools/libclang/CXType.cpp | 22 ++ tools/libclang/libclang.exports | 2 + unittests/ASTMatchers/Dynamic/ParserTest.cpp | 28 +- .../ASTMatchers/Dynamic/RegistryTest.cpp | 43 +++ .../ASTMatchers/Dynamic/VariantValueTest.cpp | 25 ++ unittests/Basic/SourceManagerTest.cpp | 24 +- unittests/Format/FormatTestComments.cpp | 33 +++ unittests/Format/FormatTestJS.cpp | 45 ++++ unittests/Frontend/FrontendActionTest.cpp | 5 +- unittests/Lex/LexerTest.cpp | 20 +- unittests/Lex/PPCallbacksTest.cpp | 23 +- .../Lex/PPConditionalDirectiveRecordTest.cpp | 20 +- unittests/Tooling/CommentHandlerTest.cpp | 3 +- unittests/Tooling/ToolingTest.cpp | 2 +- 196 files changed, 3782 insertions(+), 1109 deletions(-) create mode 100644 test/Analysis/nullability-notes.m create mode 100644 test/CodeGen/arm-target-attr.c create mode 100644 test/CodeGen/arm-thumb-mode-target-feature.c create mode 100644 test/CodeGen/mips-madd4.c create mode 100644 test/CodeGen/neon-aapcs-align.c create mode 100644 test/CodeGenCXX/clang-sections-tentative.c create mode 100644 test/CodeGenCXX/clang-sections.cpp create mode 100644 test/CodeGenObjC/sections.m create mode 100644 test/FixIt/fixit-format-darwin.m create mode 100644 test/Headers/ms-cppoperkey.cpp create mode 100644 test/Headers/ms-cppoperkey1.cpp create mode 100644 test/Headers/ms-cppoperkey2.cpp create mode 100644 test/Index/pipe-size.cl create mode 100644 test/Index/singe-file-parse.m create mode 100644 test/Modules/Inputs/crash-typo-correction-visibility/module.h create mode 100644 test/Modules/Inputs/crash-typo-correction-visibility/module.modulemap create mode 100644 test/Modules/crash-typo-correction-visibility.cpp create mode 100644 test/Modules/preprocess-build-diamond.m create mode 100644 test/Modules/preprocess-build.cpp create mode 100644 test/Sema/ext_vector_ops.c create mode 100644 test/Sema/pragma-clang-section.c create mode 100644 test/SemaCXX/PR27037.cpp diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index 2c50d2722dec..8440b0aabe08 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -2162,6 +2162,12 @@ def is_function_variadic(self): return conf.lib.clang_isFunctionTypeVariadic(self) + def get_address_space(self): + return conf.lib.clang_getAddressSpace(self) + + def get_typedef_name(self): + return conf.lib.clang_getTypedefName(self) + def is_pod(self): """Determine whether this Type represents plain old data (POD).""" return conf.lib.clang_isPODType(self) @@ -3665,6 +3671,11 @@ def cursor(self): Type, Type.from_result), + ("clang_getTypedefName", + [Type], + _CXString, + _CXString.from_result), + ("clang_getTypeKindSpelling", [c_uint], _CXString, diff --git a/bindings/python/tests/cindex/test_type.py b/bindings/python/tests/cindex/test_type.py index f2184338be4b..6ee0773828ec 100644 --- a/bindings/python/tests/cindex/test_type.py +++ b/bindings/python/tests/cindex/test_type.py @@ -37,37 +37,44 @@ def test_a_struct(): assert not fields[0].type.is_const_qualified() assert fields[0].type.kind == TypeKind.INT assert fields[0].type.get_canonical().kind == TypeKind.INT + assert fields[0].type.get_typedef_name() == '' assert fields[1].spelling == 'b' assert not fields[1].type.is_const_qualified() assert fields[1].type.kind == TypeKind.TYPEDEF assert fields[1].type.get_canonical().kind == TypeKind.INT assert fields[1].type.get_declaration().spelling == 'I' + assert fields[1].type.get_typedef_name() == 'I' assert fields[2].spelling == 'c' assert not fields[2].type.is_const_qualified() assert fields[2].type.kind == TypeKind.LONG assert fields[2].type.get_canonical().kind == TypeKind.LONG + assert fields[2].type.get_typedef_name() == '' assert fields[3].spelling == 'd' assert not fields[3].type.is_const_qualified() assert fields[3].type.kind == TypeKind.ULONG assert fields[3].type.get_canonical().kind == TypeKind.ULONG + assert fields[3].type.get_typedef_name() == '' assert fields[4].spelling == 'e' assert not fields[4].type.is_const_qualified() assert fields[4].type.kind == TypeKind.LONG assert fields[4].type.get_canonical().kind == TypeKind.LONG + assert fields[4].type.get_typedef_name() == '' assert fields[5].spelling == 'f' assert fields[5].type.is_const_qualified() assert fields[5].type.kind == TypeKind.INT assert fields[5].type.get_canonical().kind == TypeKind.INT + assert fields[5].type.get_typedef_name() == '' assert fields[6].spelling == 'g' assert not fields[6].type.is_const_qualified() assert fields[6].type.kind == TypeKind.POINTER assert fields[6].type.get_pointee().kind == TypeKind.INT + assert fields[6].type.get_typedef_name() == '' assert fields[7].spelling == 'h' assert not fields[7].type.is_const_qualified() @@ -75,6 +82,7 @@ def test_a_struct(): assert fields[7].type.get_pointee().kind == TypeKind.POINTER assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT + assert fields[7].type.get_typedef_name() == '' def test_references(): """Ensure that a Type maintains a reference to a TranslationUnit.""" @@ -404,3 +412,12 @@ def test_decay(): assert a.kind == TypeKind.INCOMPLETEARRAY assert a.element_type.kind == TypeKind.INT assert a.get_canonical().kind == TypeKind.INCOMPLETEARRAY + +def test_addrspace(): + """Ensure the address space can be queried""" + tu = get_tu('__attribute__((address_space(2))) int testInteger = 3;', 'c') + + testInteger = get_cursor(tu, 'testInteger') + + assert testInteger is not None, "Could not find testInteger." + assert testInteger.type.get_address_space() == 2 diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index f54acd9b81dd..9e0bacaf7c14 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -894,7 +894,7 @@ the configuration (without a prefix: ``Auto``). ? firstValue : SecondValueVeryVeryVeryVeryLong; - true: + false: veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription ? firstValue : SecondValueVeryVeryVeryVeryLong; diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index f8dd1a39c676..dab538f3a983 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -2521,3 +2521,45 @@ whether or not an attribute is supported by the pragma by referring to the The attributes are applied to all matching declarations individually, even when the attribute is semantically incorrect. The attributes that aren't applied to any declaration are not verified semantically. + +Specifying section names for global objects (#pragma clang section) +=================================================================== + +The ``#pragma clang section`` directive provides a means to assign section-names +to global variables, functions and static variables. + +The section names can be specified as: + +.. code-block:: c++ + + #pragma clang section bss="myBSS" data="myData" rodata="myRodata" text="myText" + +The section names can be reverted back to default name by supplying an empty +string to the section kind, for example: + +.. code-block:: c++ + + #pragma clang section bss="" data="" text="" rodata="" + +The ``#pragma clang section`` directive obeys the following rules: + +* The pragma applies to all global variable, statics and function declarations + from the pragma to the end of the translation unit. + +* The pragma clang section is enabled automatically, without need of any flags. + +* This feature is only defined to work sensibly for ELF targets. + +* If section name is specified through _attribute_((section("myname"))), then + the attribute name gains precedence. + +* Global variables that are initialized to zero will be placed in the named + bss section, if one is present. + +* The ``#pragma clang section`` directive does not does try to infer section-kind + from the name. For example, naming a section "``.bss.mySec``" does NOT mean + it will be a bss section name. + +* The decision about which section-kind applies to each global is taken in the back-end. + Once the section-kind is known, appropriate section name, as specified by the user using + ``#pragma clang section`` directive, is applied to that global. diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index c91b2a249029..a0403a5edf65 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1859,17 +1859,36 @@ Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) -Matcher<CXXBoolLiteral>equalsValueT Value -

    Matches literals that are equal to the given value.
    +Matcher<CXXBoolLiteralExpr>equalsValueT  Value
    +
    Matches literals that are equal to the given value of type ValueT.
     
    -Example matches true (matcher = cxxBoolLiteral(equals(true)))
    -  true
    +Given
    +  f('false, 3.14, 42);
    +characterLiteral(equals(0))
    +  matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
    +  match false
    +floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
    +  match 3.14
    +integerLiteral(equals(42))
    +  matches 42
     
    -Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>,
    +Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteralExpr>,
                Matcher<FloatingLiteral>, Matcher<IntegerLiteral>
     
    +Matcher<CXXBoolLiteralExpr>equalsbool Value +
    
    +
    +
    +Matcher<CXXBoolLiteralExpr>equalsdouble Value
    +
    
    +
    +
    +Matcher<CXXBoolLiteralExpr>equalsunsigned Value
    +
    
    +
    +
     Matcher<CXXCatchStmt>isCatchAll
     
    Matches a C++ catch statement that has a catch-all handler.
     
    @@ -2296,16 +2315,35 @@ Example: matches the implicit cast around 0
     
     
     Matcher<CharacterLiteral>equalsValueT  Value
    -
    Matches literals that are equal to the given value.
    +
    Matches literals that are equal to the given value of type ValueT.
     
    -Example matches true (matcher = cxxBoolLiteral(equals(true)))
    -  true
    +Given
    +  f('false, 3.14, 42);
    +characterLiteral(equals(0))
    +  matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
    +  match false
    +floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
    +  match 3.14
    +integerLiteral(equals(42))
    +  matches 42
     
    -Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>,
    +Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteralExpr>,
                Matcher<FloatingLiteral>, Matcher<IntegerLiteral>
     
    +Matcher<CharacterLiteral>equalsbool Value +
    
    +
    +
    +Matcher<CharacterLiteral>equalsdouble Value
    +
    
    +
    +
    +Matcher<CharacterLiteral>equalsunsigned Value
    +
    
    +
    +
     Matcher<ClassTemplateSpecializationDecl>templateArgumentCountIsunsigned N
     
    Matches if the number of template arguments equals N.
     
    @@ -2533,16 +2571,27 @@ fieldDecl(isBitField())
     
     
     Matcher<FloatingLiteral>equalsValueT  Value
    -
    Matches literals that are equal to the given value.
    +
    Matches literals that are equal to the given value of type ValueT.
     
    -Example matches true (matcher = cxxBoolLiteral(equals(true)))
    -  true
    +Given
    +  f('false, 3.14, 42);
    +characterLiteral(equals(0))
    +  matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
    +  match false
    +floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
    +  match 3.14
    +integerLiteral(equals(42))
    +  matches 42
     
    -Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>,
    +Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteralExpr>,
                Matcher<FloatingLiteral>, Matcher<IntegerLiteral>
     
    +Matcher<FloatingLiteral>equalsdouble Value +
    
    +
    +
     Matcher<FunctionDecl>hasDynamicExceptionSpec
     
    Matches functions that have a dynamic exception specification.
     
    @@ -2805,16 +2854,35 @@ functionProtoType(parameterCountIs(3))
     
     
     Matcher<IntegerLiteral>equalsValueT  Value
    -
    Matches literals that are equal to the given value.
    +
    Matches literals that are equal to the given value of type ValueT.
     
    -Example matches true (matcher = cxxBoolLiteral(equals(true)))
    -  true
    +Given
    +  f('false, 3.14, 42);
    +characterLiteral(equals(0))
    +  matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
    +  match false
    +floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
    +  match 3.14
    +integerLiteral(equals(42))
    +  matches 42
     
    -Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>,
    +Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteralExpr>,
                Matcher<FloatingLiteral>, Matcher<IntegerLiteral>
     
    +Matcher<IntegerLiteral>equalsbool Value +
    
    +
    +
    +Matcher<IntegerLiteral>equalsdouble Value
    +
    
    +
    +
    +Matcher<IntegerLiteral>equalsunsigned Value
    +
    
    +
    +
     Matcher<MemberExpr>isArrow
     
    Matches member expressions that are called with '->' as opposed
     to '.'.
    diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
    index 91b3d11a549a..417ac9fd369a 100644
    --- a/include/clang-c/Index.h
    +++ b/include/clang-c/Index.h
    @@ -32,7 +32,7 @@
      * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
      */
     #define CINDEX_VERSION_MAJOR 0
    -#define CINDEX_VERSION_MINOR 41
    +#define CINDEX_VERSION_MINOR 43
     
     #define CINDEX_VERSION_ENCODE(major, minor) ( \
           ((major) * 10000)                       \
    @@ -1234,7 +1234,12 @@ enum CXTranslationUnit_Flags {
        * purposes of an IDE, this is undesirable behavior and as much information
        * as possible should be reported. Use this flag to enable this behavior.
        */
    -  CXTranslationUnit_KeepGoing = 0x200
    +  CXTranslationUnit_KeepGoing = 0x200,
    +
    +  /**
    +   * \brief Sets the preprocessor in a mode for parsing a single file only.
    +   */
    +  CXTranslationUnit_SingleFileParse = 0x400
     };
     
     /**
    @@ -3416,6 +3421,16 @@ CINDEX_LINKAGE unsigned clang_isVolatileQualifiedType(CXType T);
      */
     CINDEX_LINKAGE unsigned clang_isRestrictQualifiedType(CXType T);
     
    +/**
    + * \brief Returns the address space of the given type.
    + */
    +CINDEX_LINKAGE unsigned clang_getAddressSpace(CXType T);
    +
    +/**
    + * \brief Returns the typedef name of the given type.
    + */
    +CINDEX_LINKAGE CXString clang_getTypedefName(CXType CT);
    +
     /**
      * \brief For pointer types, returns the type of the pointee.
      */
    diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
    index 4f8042ac9291..9d49bac26a86 100644
    --- a/include/clang/AST/Decl.h
    +++ b/include/clang/AST/Decl.h
    @@ -851,6 +851,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable {
     
       class NonParmVarDeclBitfields {
         friend class VarDecl;
    +    friend class ImplicitParamDecl;
         friend class ASTDeclReader;
     
         unsigned : NumVarDeclBits;
    @@ -894,6 +895,10 @@ class VarDecl : public DeclaratorDecl, public Redeclarable {
         /// declared in the same block scope. This controls whether we should merge
         /// the type of this declaration with its previous declaration.
         unsigned PreviousDeclInSameBlockScope : 1;
    +
    +    /// Defines kind of the ImplicitParamDecl: 'this', 'self', 'vtt', '_cmd' or
    +    /// something else.
    +    unsigned ImplicitParamKind : 3;
       };
     
       union {
    @@ -1376,20 +1381,50 @@ class VarDecl : public DeclaratorDecl, public Redeclarable {
     
     class ImplicitParamDecl : public VarDecl {
       void anchor() override;
    +
     public:
    +  /// Defines the kind of the implicit parameter: is this an implicit parameter
    +  /// with pointer to 'this', 'self', '_cmd', virtual table pointers, captured
    +  /// context or something else.
    +  enum ImplicitParamKind : unsigned {
    +    ObjCSelf,        /// Parameter for Objective-C 'self' argument
    +    ObjCCmd,         /// Parameter for Objective-C '_cmd' argument
    +    CXXThis,         /// Parameter for C++ 'this' argument
    +    CXXVTT,          /// Parameter for C++ virtual table pointers
    +    CapturedContext, /// Parameter for captured context
    +    Other,           /// Other implicit parameter
    +  };
    +
    +  /// Create implicit parameter.
       static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
                                        SourceLocation IdLoc, IdentifierInfo *Id,
    -                                   QualType T);
    +                                   QualType T, ImplicitParamKind ParamKind);
    +  static ImplicitParamDecl *Create(ASTContext &C, QualType T,
    +                                   ImplicitParamKind ParamKind);
     
       static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID);
     
       ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
    -                    IdentifierInfo *Id, QualType Type)
    -    : VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
    -              /*tinfo*/ nullptr, SC_None) {
    +                    IdentifierInfo *Id, QualType Type,
    +                    ImplicitParamKind ParamKind)
    +      : VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
    +                /*TInfo=*/nullptr, SC_None) {
    +    NonParmVarDeclBits.ImplicitParamKind = ParamKind;
         setImplicit();
       }
     
    +  ImplicitParamDecl(ASTContext &C, QualType Type, ImplicitParamKind ParamKind)
    +      : VarDecl(ImplicitParam, C, /*DC=*/nullptr, SourceLocation(),
    +                SourceLocation(), /*Id=*/nullptr, Type,
    +                /*TInfo=*/nullptr, SC_None) {
    +    NonParmVarDeclBits.ImplicitParamKind = ParamKind;
    +    setImplicit();
    +  }
    +
    +  /// Returns the implicit parameter kind.
    +  ImplicitParamKind getParameterKind() const {
    +    return static_cast(NonParmVarDeclBits.ImplicitParamKind);
    +  }
       // Implement isa/cast/dyncast/etc.
       static bool classof(const Decl *D) { return classofKind(D->getKind()); }
       static bool classofKind(Kind K) { return K == ImplicitParam; }
    @@ -1829,14 +1864,15 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
         return getBody(Definition);
       }
     
    -  /// isThisDeclarationADefinition - Returns whether this specific
    -  /// declaration of the function is also a definition. This does not
    -  /// determine whether the function has been defined (e.g., in a
    -  /// previous definition); for that information, use isDefined. Note
    -  /// that this returns false for a defaulted function unless that function
    -  /// has been implicitly defined (possibly as deleted).
    +  /// Returns whether this specific declaration of the function is also a
    +  /// definition that does not contain uninstantiated body.
    +  ///
    +  /// This does not determine whether the function has been defined (e.g., in a
    +  /// previous definition); for that information, use isDefined.
    +  ///
       bool isThisDeclarationADefinition() const {
    -    return IsDeleted || Body || IsLateTemplateParsed;
    +    return IsDeleted || IsDefaulted || Body || IsLateTemplateParsed ||
    +      hasDefiningAttr();
       }
     
       /// doesThisDeclarationHaveABody - Returns whether this specific
    diff --git a/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h
    index 55459df1fe6b..92d7b39c48d2 100644
    --- a/include/clang/AST/ExternalASTMerger.h
    +++ b/include/clang/AST/ExternalASTMerger.h
    @@ -45,6 +45,8 @@ class ExternalASTMerger : public ExternalASTSource {
                                llvm::function_ref IsKindWeWant,
                                SmallVectorImpl &Result) override;
     
    +   using ExternalASTSource::CompleteType;
    +
        void CompleteType(TagDecl *Tag) override;
     };
     
    diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
    index cd2a39449825..ad3f40d0d3f6 100644
    --- a/include/clang/AST/RecursiveASTVisitor.h
    +++ b/include/clang/AST/RecursiveASTVisitor.h
    @@ -1021,8 +1021,12 @@ DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, {
     DEF_TRAVERSE_TYPE(RecordType, {})
     DEF_TRAVERSE_TYPE(EnumType, {})
     DEF_TRAVERSE_TYPE(TemplateTypeParmType, {})
    -DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {})
    -DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {})
    +DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {
    +  TRY_TO(TraverseType(T->getReplacementType()));
    +})
    +DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {
    +  TRY_TO(TraverseTemplateArgument(T->getArgumentPack()));
    +})
     
     DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
       TRY_TO(TraverseTemplateName(T->getTemplateName()));
    @@ -1249,8 +1253,12 @@ DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, {
     DEF_TRAVERSE_TYPELOC(RecordType, {})
     DEF_TRAVERSE_TYPELOC(EnumType, {})
     DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
    -DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {})
    -DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {})
    +DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {
    +  TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType()));
    +})
    +DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {
    +  TRY_TO(TraverseTemplateArgument(TL.getTypePtr()->getArgumentPack()));
    +})
     
     // FIXME: use the loc for the template name?
     DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
    diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
    index 0ab8d5fe4fc1..cba4c99be959 100644
    --- a/include/clang/ASTMatchers/ASTMatchers.h
    +++ b/include/clang/ASTMatchers/ASTMatchers.h
    @@ -3806,14 +3806,22 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
       return Node.size() == N;
     }
     
    -/// \brief Matches literals that are equal to the given value.
    +/// \brief Matches literals that are equal to the given value of type ValueT.
     ///
    -/// Example matches true (matcher = cxxBoolLiteral(equals(true)))
    +/// Given
     /// \code
    -///   true
    +///   f('\0', false, 3.14, 42);
     /// \endcode
    +/// characterLiteral(equals(0))
    +///   matches '\0'
    +/// cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
    +///   match false
    +/// floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
    +///   match 3.14
    +/// integerLiteral(equals(42))
    +///   matches 42
     ///
    -/// Usable as: Matcher, Matcher,
    +/// Usable as: Matcher, Matcher,
     ///            Matcher, Matcher
     template 
     internal::PolymorphicMatcherWithParam1
    @@ -3823,6 +3831,34 @@ equals(const ValueT &Value) {
         ValueT>(Value);
     }
     
    +AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
    +                          AST_POLYMORPHIC_SUPPORTED_TYPES(CharacterLiteral,
    +                                                          CXXBoolLiteralExpr,
    +                                                          IntegerLiteral),
    +                          bool, Value, 0) {
    +  return internal::ValueEqualsMatcher(Value)
    +    .matchesNode(Node);
    +}
    +
    +AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
    +                          AST_POLYMORPHIC_SUPPORTED_TYPES(CharacterLiteral,
    +                                                          CXXBoolLiteralExpr,
    +                                                          IntegerLiteral),
    +                          unsigned, Value, 1) {
    +  return internal::ValueEqualsMatcher(Value)
    +    .matchesNode(Node);
    +}
    +
    +AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
    +                          AST_POLYMORPHIC_SUPPORTED_TYPES(CharacterLiteral,
    +                                                          CXXBoolLiteralExpr,
    +                                                          FloatingLiteral,
    +                                                          IntegerLiteral),
    +                          double, Value, 2) {
    +  return internal::ValueEqualsMatcher(Value)
    +    .matchesNode(Node);
    +}
    +
     /// \brief Matches the operator Name of operator expressions (binary or
     /// unary).
     ///
    diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
    index 2c76ddaa07d9..908fa0db622d 100644
    --- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h
    +++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
    @@ -76,7 +76,7 @@ class Diagnostics {
         ET_ParserInvalidToken = 106,
         ET_ParserMalformedBindExpr = 107,
         ET_ParserTrailingCode = 108,
    -    ET_ParserUnsignedError = 109,
    +    ET_ParserNumberError = 109,
         ET_ParserOverloadedType = 110
       };
     
    diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
    index 76926f09dbcb..5ec4a9abf4bf 100644
    --- a/include/clang/ASTMatchers/Dynamic/Parser.h
    +++ b/include/clang/ASTMatchers/Dynamic/Parser.h
    @@ -19,8 +19,10 @@
     /// \code
     /// Grammar for the expressions supported:
     ///         :=  |  | 
    -///            :=  | 
    +///            :=  |  |  | 
     ///      := "quoted string"
    +///            := true | false
    +///             := [0-9]+.[0-9]* | [0-9]+.[0-9]*[eE][-+]?[0-9]+
     ///           := [0-9]+
     ///         := 
     ///  := () |
    diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
    index c5426dd75ef5..f9efe0f16f43 100644
    --- a/include/clang/ASTMatchers/Dynamic/VariantValue.h
    +++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
    @@ -35,6 +35,8 @@ class ArgKind {
      public:
       enum Kind {
         AK_Matcher,
    +    AK_Boolean,
    +    AK_Double,
         AK_Unsigned,
         AK_String
       };
    @@ -241,6 +243,8 @@ struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
     /// copy/assignment.
     ///
     /// Supported types:
    +///  - \c bool
    +//   - \c double
     ///  - \c unsigned
     ///  - \c llvm::StringRef
     ///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher)
    @@ -253,14 +257,29 @@ class VariantValue {
       VariantValue &operator=(const VariantValue &Other);
     
       /// \brief Specific constructors for each supported type.
    +  VariantValue(bool Boolean);
    +  VariantValue(double Double);
       VariantValue(unsigned Unsigned);
       VariantValue(StringRef String);
       VariantValue(const VariantMatcher &Matchers);
     
    +  /// \brief Constructs an \c unsigned value (disambiguation from bool).
    +  VariantValue(int Signed) : VariantValue(static_cast(Signed)) {}
    +
       /// \brief Returns true iff this is not an empty value.
       explicit operator bool() const { return hasValue(); }
       bool hasValue() const { return Type != VT_Nothing; }
     
    +  /// \brief Boolean value functions.
    +  bool isBoolean() const;
    +  bool getBoolean() const;
    +  void setBoolean(bool Boolean);
    +
    +  /// \brief Double value functions.
    +  bool isDouble() const;
    +  double getDouble() const;
    +  void setDouble(double Double);
    +
       /// \brief Unsigned value functions.
       bool isUnsigned() const;
       unsigned getUnsigned() const;
    @@ -303,6 +322,8 @@ class VariantValue {
       /// \brief All supported value types.
       enum ValueType {
         VT_Nothing,
    +    VT_Boolean,
    +    VT_Double,
         VT_Unsigned,
         VT_String,
         VT_Matcher
    @@ -311,6 +332,8 @@ class VariantValue {
       /// \brief All supported value types.
       union AllValues {
         unsigned Unsigned;
    +    double Double;
    +    bool Boolean;
         std::string *String;
         VariantMatcher *Matcher;
       };
    diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
    index 9da2cc376d54..bc36fd8c8297 100644
    --- a/include/clang/Basic/Attr.td
    +++ b/include/clang/Basic/Attr.td
    @@ -1683,6 +1683,42 @@ def Section : InheritableAttr {
       let Documentation = [SectionDocs];
     }
     
    +def PragmaClangBSSSection : InheritableAttr {
    +  // This attribute has no spellings as it is only ever created implicitly.
    +  let Spellings = [];
    +  let Args = [StringArgument<"Name">];
    +  let Subjects = SubjectList<[GlobalVar], ErrorDiag,
    +                             "ExpectedFunctionMethodOrGlobalVar">;
    +  let Documentation = [Undocumented];
    +}
    +
    +def PragmaClangDataSection : InheritableAttr {
    +  // This attribute has no spellings as it is only ever created implicitly.
    +  let Spellings = [];
    +  let Args = [StringArgument<"Name">];
    +  let Subjects = SubjectList<[GlobalVar], ErrorDiag,
    +                             "ExpectedFunctionMethodOrGlobalVar">;
    +  let Documentation = [Undocumented];
    +}
    +
    +def PragmaClangRodataSection : InheritableAttr {
    +  // This attribute has no spellings as it is only ever created implicitly.
    +  let Spellings = [];
    +  let Args = [StringArgument<"Name">];
    +  let Subjects = SubjectList<[GlobalVar], ErrorDiag,
    +                             "ExpectedFunctionMethodOrGlobalVar">;
    +  let Documentation = [Undocumented];
    +}
    +
    +def PragmaClangTextSection : InheritableAttr {
    +  // This attribute has no spellings as it is only ever created implicitly.
    +  let Spellings = [];
    +  let Args = [StringArgument<"Name">];
    +  let Subjects = SubjectList<[Function], ErrorDiag,
    +                             "ExpectedFunctionMethodOrGlobalVar">;
    +  let Documentation = [Undocumented];
    +}
    +
     def Sentinel : InheritableAttr {
       let Spellings = [GCC<"sentinel">];
       let Args = [DefaultIntArgument<"Sentinel", 0>,
    diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
    index 1267f8d09f58..8b4cb47e545d 100644
    --- a/include/clang/Basic/DiagnosticFrontendKinds.td
    +++ b/include/clang/Basic/DiagnosticFrontendKinds.td
    @@ -196,6 +196,7 @@ def err_no_submodule_suggest : Error<
       "no submodule named %0 in module '%1'; did you mean '%2'?">;
     def warn_missing_submodule : Warning<"missing submodule '%0'">,
       InGroup;
    +def note_module_import_here : Note<"module imported here">;
     def err_module_cannot_create_includes : Error<
       "cannot create includes file for module %0: %1">;
     def warn_module_config_macro_undef : Warning<
    diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
    index 447f06945660..d6de5c04a74d 100644
    --- a/include/clang/Basic/DiagnosticLexKinds.td
    +++ b/include/clang/Basic/DiagnosticLexKinds.td
    @@ -527,6 +527,10 @@ def err_pp_module_end_without_module_begin : Error<
       "'#pragma clang module end'">;
     def note_pp_module_begin_here : Note<
       "entering module '%0' due to this pragma">;
    +def err_pp_module_build_pth : Error<
    +  "'#pragma clang module build' not supported in pretokenized header">;
    +def err_pp_module_build_missing_end : Error<
    +  "no matching '#pragma clang module endbuild' for this '#pragma clang module build'">;
     
     def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
     def err_paste_at_start : Error<
    diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
    index f04ed8ed4ce6..f39ffeae61f4 100644
    --- a/include/clang/Basic/DiagnosticParseKinds.td
    +++ b/include/clang/Basic/DiagnosticParseKinds.td
    @@ -887,9 +887,18 @@ def warn_pragma_expected_rparen : Warning<
       "missing ')' after '#pragma %0' - ignoring">, InGroup;
     def warn_pragma_expected_identifier : Warning<
       "expected identifier in '#pragma %0' - ignored">, InGroup;
    +
    +// '#pragma clang section' related errors
    +def err_pragma_expected_clang_section_name : Error<
    +  "expected one of [bss|data|rodata|text] section kind in '#pragma %0'">;
    +def err_pragma_clang_section_expected_equal : Error<
    +  "expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
    +def err_pragma_clang_section_expected_name_or_clear : Error<
    +  "expected section name or '\"\"' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
     def warn_pragma_expected_section_name : Warning<
       "expected a string literal for the section name in '#pragma %0' - ignored">,
       InGroup;
    +
     def warn_pragma_expected_section_push_pop_or_name : Warning<
       "expected push, pop or a string literal for the section name in '#pragma %0' - ignored">,
       InGroup;
    diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
    index a5a5c74afe69..aa73a6934518 100644
    --- a/include/clang/Basic/DiagnosticSemaKinds.td
    +++ b/include/clang/Basic/DiagnosticSemaKinds.td
    @@ -5613,6 +5613,11 @@ def err_enumerator_does_not_exist : Error<
     def note_enum_specialized_here : Note<
       "enum %0 was explicitly specialized here">;
     
    +def err_specialization_not_primary_template : Error<
    +  "cannot reference member of primary template because deduced class "
    +  "template specialization %0 is %select{instantiated from a partial|"
    +  "an explicit}1 specialization">;
    +
     def err_member_redeclared : Error<"class member cannot be redeclared">;
     def ext_member_redeclared : ExtWarn<"class member cannot be redeclared">,
       InGroup;
    diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
    index f9e7b8fa9b56..7c9e8c8980aa 100644
    --- a/include/clang/Basic/DiagnosticSerializationKinds.td
    +++ b/include/clang/Basic/DiagnosticSerializationKinds.td
    @@ -174,6 +174,15 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
       "method %2 with %ordinal3 parameter of type %4%select{| decayed from %6}5|"
       "method %2 with %ordinal3 parameter named %4}1">;
     
    +def err_module_odr_violation_mismatch_decl_unknown : Error<
    +  "%q0 %select{with definition in module '%2'|defined here}1 has different "
    +  "definitions in different modules; first difference is this "
    +  "%select{||||static assert|field|method|unexpected decl}3">;
    +def note_module_odr_violation_mismatch_decl_unknown : Note<
    +  "but in '%0' found "
    +  "%select{||||different static assert|different field|different method|"
    +  "another unexpected decl}1">;
    +
     def warn_duplicate_module_file_extension : Warning<
       "duplicate module file extension block name '%0'">,
       InGroup;
    diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
    index 2513de70e721..8488515d2b67 100644
    --- a/include/clang/Basic/LangOptions.h
    +++ b/include/clang/Basic/LangOptions.h
    @@ -58,6 +58,7 @@ class LangOptions : public LangOptionsBase {
         SOB_Trapping    // -ftrapv
       };
     
    +  // FIXME: Unify with TUKind.
       enum CompilingModuleKind {
         CMK_None,           ///< Not compiling a module interface at all.
         CMK_ModuleMap,      ///< Compiling a module from a module map.
    diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
    index eda802934006..5e01f6416748 100644
    --- a/include/clang/Basic/SourceManager.h
    +++ b/include/clang/Basic/SourceManager.h
    @@ -722,6 +722,10 @@ class SourceManager : public RefCountedBase {
     
       void clearIDTables();
     
    +  /// Initialize this source manager suitably to replay the compilation
    +  /// described by \p Old. Requires that \p Old outlive \p *this.
    +  void initializeForReplay(const SourceManager &Old);
    +
       DiagnosticsEngine &getDiagnostics() const { return Diag; }
     
       FileManager &getFileManager() const { return FileMgr; }
    diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
    index 12e36cc52b0b..6c51976e98fe 100644
    --- a/include/clang/Driver/Options.td
    +++ b/include/clang/Driver/Options.td
    @@ -932,6 +932,10 @@ def frewrite_includes : Flag<["-"], "frewrite-includes">, Group,
       Flags<[CC1Option]>;
     def fno_rewrite_includes : Flag<["-"], "fno-rewrite-includes">, Group;
     
    +def frewrite_imports : Flag<["-"], "frewrite-imports">, Group,
    +  Flags<[CC1Option]>;
    +def fno_rewrite_imports : Flag<["-"], "fno-rewrite-imports">, Group;
    +
     def frewrite_map_file : Separate<["-"], "frewrite-map-file">,
                             Group,
                             Flags<[ DriverOption, CC1Option ]>;
    @@ -2001,6 +2005,10 @@ def mdspr2 : Flag<["-"], "mdspr2">, Group;
     def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group;
     def msingle_float : Flag<["-"], "msingle-float">, Group;
     def mdouble_float : Flag<["-"], "mdouble-float">, Group;
    +def mmadd4 : Flag<["-"], "mmadd4">, Group,
    +  HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">;
    +def mno_madd4 : Flag<["-"], "mno-madd4">, Group,
    +  HelpText<"Disable the generation of 4-operand madd.s, madd.d and related instructions.">;
     def mmsa : Flag<["-"], "mmsa">, Group,
       HelpText<"Enable MSA ASE (MIPS only)">;
     def mno_msa : Flag<["-"], "mno-msa">, Group,
    diff --git a/include/clang/Edit/EditedSource.h b/include/clang/Edit/EditedSource.h
    index b082e4e0a3df..970791420734 100644
    --- a/include/clang/Edit/EditedSource.h
    +++ b/include/clang/Edit/EditedSource.h
    @@ -41,9 +41,11 @@ class EditedSource {
       typedef std::map FileEditsTy;
       FileEditsTy FileEdits;
     
    -  llvm::DenseMap>
    +  // Location of argument use inside the macro body 
    +  typedef std::pair MacroArgUse;
    +  llvm::DenseMap>
         ExpansionToArgMap;
    -  SmallVector, 2>
    +  SmallVector, 2>
         CurrCommitMacroArgExps;
     
       IdentifierTable IdentTable;
    @@ -84,7 +86,7 @@ class EditedSource {
       FileEditsTy::iterator getActionForOffset(FileOffset Offs);
       void deconstructMacroArgLoc(SourceLocation Loc,
                                   SourceLocation &ExpansionLoc,
    -                              IdentifierInfo *&II);
    +                              MacroArgUse &ArgUse);
     
       void startingCommit();
       void finishedCommit();
    diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
    index fb0a5e8acd4a..ae54d4151415 100644
    --- a/include/clang/Frontend/ASTUnit.h
    +++ b/include/clang/Frontend/ASTUnit.h
    @@ -51,8 +51,10 @@ class DiagnosticsEngine;
     class FileEntry;
     class FileManager;
     class HeaderSearch;
    +class InputKind;
     class MemoryBufferCache;
     class Preprocessor;
    +class PreprocessorOptions;
     class PCHContainerOperations;
     class PCHContainerReader;
     class TargetInfo;
    @@ -65,7 +67,7 @@ class FileSystem;
     
     /// \brief Utility class for loading a ASTContext from an AST file.
     ///
    -class ASTUnit : public ModuleLoader {
    +class ASTUnit {
     public:
       struct StandaloneFixIt {
         std::pair RemoveRange;
    @@ -96,6 +98,7 @@ class ASTUnit : public ModuleLoader {
       IntrusiveRefCntPtr          Ctx;
       std::shared_ptr          TargetOpts;
       std::shared_ptr    HSOpts;
    +  std::shared_ptr    PPOpts;
       IntrusiveRefCntPtr Reader;
       bool HadModuleLoaderFatalFailure;
     
    @@ -116,10 +119,13 @@ class ASTUnit : public ModuleLoader {
       /// LoadFromCommandLine available.
       std::shared_ptr Invocation;
     
    +  /// Fake module loader: the AST unit doesn't need to load any modules.
    +  TrivialModuleLoader ModuleLoader;
    +
       // OnlyLocalDecls - when true, walking this AST should only visit declarations
       // that come from the AST itself, not from included precompiled headers.
       // FIXME: This is temporary; eventually, CIndex will always do this.
    -  bool                              OnlyLocalDecls;
    +  bool OnlyLocalDecls;
     
       /// \brief Whether to capture any diagnostics produced.
       bool CaptureDiagnostics;
    @@ -185,6 +191,14 @@ class ASTUnit : public ModuleLoader {
       /// some number of calls.
       unsigned PreambleRebuildCounter;
     
    +  /// \brief Cache pairs "filename - source location"
    +  ///
    +  /// Cache contains only source locations from preamble so it is
    +  /// guaranteed that they stay valid when the SourceManager is recreated.
    +  /// This cache is used when loading preambule to increase performance
    +  /// of that loading. It must be cleared when preamble is recreated.
    +  llvm::StringMap PreambleSrcLocCache;
    +
     public:
       class PreambleData {
         const FileEntry *File;
    @@ -305,9 +319,6 @@ class ASTUnit : public ModuleLoader {
       /// (likely to change while trying to use them).
       bool UserFilesAreVolatile : 1;
      
    -  /// \brief The language options used when we load an AST file.
    -  LangOptions ASTFileLangOpts;
    -
       static void ConfigureDiags(IntrusiveRefCntPtr Diags,
                                  ASTUnit &AST, bool CaptureDiagnostics);
     
    @@ -488,7 +499,7 @@ class ASTUnit : public ModuleLoader {
       };
       friend class ConcurrencyCheck;
     
    -  ~ASTUnit() override;
    +  ~ASTUnit();
     
       bool isMainFileAST() const { return MainFileIsAST; }
     
    @@ -518,9 +529,19 @@ class ASTUnit : public ModuleLoader {
       }
     
       const LangOptions &getLangOpts() const {
    -    assert(LangOpts && " ASTUnit does not have language options");
    +    assert(LangOpts && "ASTUnit does not have language options");
         return *LangOpts;
       }
    +
    +  const HeaderSearchOptions &getHeaderSearchOpts() const {
    +    assert(HSOpts && "ASTUnit does not have header search options");
    +    return *HSOpts;
    +  }
    +  
    +  const PreprocessorOptions &getPreprocessorOpts() const {
    +    assert(PPOpts && "ASTUnit does not have preprocessor options");
    +    return *PPOpts;
    +  }
       
       const FileManager &getFileManager() const { return *FileMgr; }
             FileManager &getFileManager()       { return *FileMgr; }
    @@ -702,6 +723,9 @@ class ASTUnit : public ModuleLoader {
       /// \brief Determine what kind of translation unit this AST represents.
       TranslationUnitKind getTranslationUnitKind() const { return TUKind; }
     
    +  /// \brief Determine the input kind this AST unit represents.
    +  InputKind getInputKind() const;
    +
       /// \brief A mapping from a file name to the memory buffer that stores the
       /// remapped contents of that file.
       typedef std::pair RemappedFile;
    @@ -858,6 +882,7 @@ class ASTUnit : public ModuleLoader {
           bool CacheCodeCompletionResults = false,
           bool IncludeBriefCommentsInCodeCompletion = false,
           bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
    +      bool SingleFileParse = false,
           bool UserFilesAreVolatile = false, bool ForSerialization = false,
           llvm::Optional ModuleFormat = llvm::None,
           std::unique_ptr *ErrAST = nullptr,
    @@ -923,21 +948,6 @@ class ASTUnit : public ModuleLoader {
       ///
       /// \returns True if an error occurred, false otherwise.
       bool serialize(raw_ostream &OS);
    -
    -  ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
    -                              Module::NameVisibilityKind Visibility,
    -                              bool IsInclusionDirective) override {
    -    // ASTUnit doesn't know how to load modules (not that this matters).
    -    return ModuleLoadResult();
    -  }
    -
    -  void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
    -                         SourceLocation ImportLoc) override {}
    -
    -  GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
    -    { return nullptr; }
    -  bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
    -    { return 0; }
     };
     
     } // namespace clang
    diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
    index d7cd805fa10a..f3deb05ec6df 100644
    --- a/include/clang/Frontend/CodeGenOptions.def
    +++ b/include/clang/Frontend/CodeGenOptions.def
    @@ -29,7 +29,8 @@ CODEGENOPT(Name, Bits, Default)
     #endif
     
     CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as
    -CODEGENOPT(CompressDebugSections, 1, 0) ///< -Wa,-compress-debug-sections
    +ENUM_CODEGENOPT(CompressDebugSections, llvm::DebugCompressionType, 2,
    +                llvm::DebugCompressionType::None)
     CODEGENOPT(RelaxELFRelocations, 1, 0) ///< -Wa,--mrelax-relocations
     CODEGENOPT(AsmVerbose        , 1, 0) ///< -dA, -fverbose-asm.
     CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments.
    diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
    index 4f7149fcb8b3..5b5c75298a31 100644
    --- a/include/clang/Frontend/CompilerInstance.h
    +++ b/include/clang/Frontend/CompilerInstance.h
    @@ -136,6 +136,13 @@ class CompilerInstance : public ModuleLoader {
       /// along with the module map
       llvm::DenseMap KnownModules;
     
    +  /// \brief The set of top-level modules that has already been built on the
    +  /// fly as part of this overall compilation action.
    +  std::map BuiltModules;
    +
    +  /// Should we delete the BuiltModules when we're done?
    +  bool DeleteBuiltModules = true;
    +
       /// \brief The location of the module-import keyword for the last module
       /// import. 
       SourceLocation LastModuleImportLoc;
    @@ -773,6 +780,9 @@ class CompilerInstance : public ModuleLoader {
                                   Module::NameVisibilityKind Visibility,
                                   bool IsInclusionDirective) override;
     
    +  void loadModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName,
    +                            StringRef Source) override;
    +
       void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
                              SourceLocation ImportLoc) override;
     
    diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
    index 8d690a448f85..7ae6173512a6 100644
    --- a/include/clang/Frontend/FrontendAction.h
    +++ b/include/clang/Frontend/FrontendAction.h
    @@ -76,8 +76,7 @@ class FrontendAction {
       ///
       /// \return True on success; on failure ExecutionAction() and
       /// EndSourceFileAction() will not be called.
    -  virtual bool BeginSourceFileAction(CompilerInstance &CI,
    -                                     StringRef Filename) {
    +  virtual bool BeginSourceFileAction(CompilerInstance &CI) {
         return true;
       }
     
    @@ -176,10 +175,10 @@ class FrontendAction {
       virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
     
       /// \brief Does this action support use with PCH?
    -  virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); }
    +  virtual bool hasPCHSupport() const { return true; }
     
       /// \brief Does this action support use with AST files?
    -  virtual bool hasASTFileSupport() const { return !usesPreprocessorOnly(); }
    +  virtual bool hasASTFileSupport() const { return true; }
     
       /// \brief Does this action support use with IR files?
       virtual bool hasIRSupport() const { return false; }
    @@ -291,7 +290,7 @@ class WrapperFrontendAction : public FrontendAction {
       std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
                                                      StringRef InFile) override;
       bool BeginInvocation(CompilerInstance &CI) override;
    -  bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
    +  bool BeginSourceFileAction(CompilerInstance &CI) override;
       void ExecuteAction() override;
       void EndSourceFileAction() override;
     
    diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
    index cb4498514955..84db293c46f3 100644
    --- a/include/clang/Frontend/FrontendActions.h
    +++ b/include/clang/Frontend/FrontendActions.h
    @@ -91,7 +91,7 @@ class GeneratePCHAction : public ASTFrontendAction {
       ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile,
                                   std::string &Sysroot, std::string &OutputFile);
     
    -  bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
    +  bool BeginSourceFileAction(CompilerInstance &CI) override;
     };
     
     class GenerateModuleAction : public ASTFrontendAction {
    @@ -111,15 +111,13 @@ class GenerateModuleAction : public ASTFrontendAction {
     
     class GenerateModuleFromModuleMapAction : public GenerateModuleAction {
     private:
    -  bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
    -
       std::unique_ptr
       CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
     };
     
     class GenerateModuleInterfaceAction : public GenerateModuleAction {
     private:
    -  bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
    +  bool BeginSourceFileAction(CompilerInstance &CI) override;
     
       std::unique_ptr
       CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
    @@ -181,8 +179,7 @@ class ASTMergeAction : public FrontendAction {
       std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
                                                      StringRef InFile) override;
     
    -  bool BeginSourceFileAction(CompilerInstance &CI,
    -                             StringRef Filename) override;
    +  bool BeginSourceFileAction(CompilerInstance &CI) override;
     
       void ExecuteAction() override;
       void EndSourceFileAction() override;
    diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h
    index 3261b6653809..94afcd06a398 100644
    --- a/include/clang/Frontend/PreprocessorOutputOptions.h
    +++ b/include/clang/Frontend/PreprocessorOutputOptions.h
    @@ -24,6 +24,7 @@ class PreprocessorOutputOptions {
       unsigned ShowMacros : 1;         ///< Print macro definitions.
       unsigned ShowIncludeDirectives : 1;  ///< Print includes, imports etc. within preprocessed output.
       unsigned RewriteIncludes : 1;    ///< Preprocess include directives only.
    +  unsigned RewriteImports  : 1;    ///< Include contents of transitively-imported modules.
     
     public:
       PreprocessorOutputOptions() {
    @@ -35,6 +36,7 @@ class PreprocessorOutputOptions {
         ShowMacros = 0;
         ShowIncludeDirectives = 0;
         RewriteIncludes = 0;
    +    RewriteImports = 0;
       }
     };
     
    diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h
    index 70770d17e9ff..ee0638b57f87 100644
    --- a/include/clang/Lex/ModuleLoader.h
    +++ b/include/clang/Lex/ModuleLoader.h
    @@ -109,6 +109,16 @@ class ModuleLoader {
                                           Module::NameVisibilityKind Visibility,
                                           bool IsInclusionDirective) = 0;
     
    +  /// Attempt to load the given module from the specified source buffer. Does
    +  /// not make any submodule visible; for that, use loadModule or
    +  /// makeModuleVisible.
    +  ///
    +  /// \param Loc The location at which the module was loaded.
    +  /// \param ModuleName The name of the module to build.
    +  /// \param Source The source of the module: a (preprocessed) module map.
    +  virtual void loadModuleFromSource(SourceLocation Loc, StringRef ModuleName,
    +                                    StringRef Source) = 0;
    +
       /// \brief Make the given module visible.
       virtual void makeModuleVisible(Module *Mod,
                                      Module::NameVisibilityKind Visibility,
    @@ -136,6 +146,30 @@ class ModuleLoader {
     
       bool HadFatalFailure;
     };
    +
    +/// A module loader that doesn't know how to load modules.
    +class TrivialModuleLoader : public ModuleLoader {
    +public:
    +  ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
    +                              Module::NameVisibilityKind Visibility,
    +                              bool IsInclusionDirective) override {
    +    return ModuleLoadResult();
    +  }
    +
    +  void loadModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName,
    +                            StringRef Source) override {}
    +
    +  void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
    +                         SourceLocation ImportLoc) override {}
    +
    +  GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override {
    +    return nullptr;
    +  }
    +  bool lookupMissingImports(StringRef Name,
    +                            SourceLocation TriggerLoc) override {
    +    return 0;
    +  }
    +};
       
     }
     
    diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
    index aeca83a90716..302d006ea16c 100644
    --- a/include/clang/Lex/Preprocessor.h
    +++ b/include/clang/Lex/Preprocessor.h
    @@ -1954,6 +1954,13 @@ class Preprocessor {
       void HandleMicrosoftImportDirective(Token &Tok);
     
     public:
    +  /// Check that the given module is available, producing a diagnostic if not.
    +  /// \return \c true if the check failed (because the module is not available).
    +  ///         \c false if the module appears to be usable.
    +  static bool checkModuleIsAvailable(const LangOptions &LangOpts,
    +                                     const TargetInfo &TargetInfo,
    +                                     DiagnosticsEngine &Diags, Module *M);
    +
       // Module inclusion testing.
       /// \brief Find the module that owns the source or header file that
       /// \p Loc points to. If the location is in a file that was included
    @@ -2021,6 +2028,7 @@ class Preprocessor {
       void HandlePragmaPushMacro(Token &Tok);
       void HandlePragmaPopMacro(Token &Tok);
       void HandlePragmaIncludeAlias(Token &Tok);
    +  void HandlePragmaModuleBuild(Token &Tok);
       IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok);
     
       // Return true and store the first token only if any CommentHandler
    diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h
    index c85d2384fa47..f536be8d8e69 100644
    --- a/include/clang/Lex/PreprocessorOptions.h
    +++ b/include/clang/Lex/PreprocessorOptions.h
    @@ -95,6 +95,9 @@ class PreprocessorOptions {
       /// If given, a PTH cache file to use for speeding up header parsing.
       std::string TokenCache;
     
    +  /// When enabled, preprocessor is in a mode for parsing a single file only.
    +  bool SingleFileParseMode = false;
    +
       /// \brief True if the SourceManager should report the original file name for
       /// contents of files that were remapped to other files. Defaults to true.
       bool RemappedFilesKeepOriginalName;
    @@ -181,6 +184,7 @@ class PreprocessorOptions {
         ImplicitPCHInclude.clear();
         ImplicitPTHInclude.clear();
         TokenCache.clear();
    +    SingleFileParseMode = false;
         RetainRemappedFileBuffers = true;
         PrecompiledPreambleBytes.first = 0;
         PrecompiledPreambleBytes.second = 0;
    diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
    index 537796fa6465..a51d3a51d435 100644
    --- a/include/clang/Parse/Parser.h
    +++ b/include/clang/Parse/Parser.h
    @@ -166,6 +166,7 @@ class Parser : public CodeCompletionHandler {
       std::unique_ptr FPContractHandler;
       std::unique_ptr OpenCLExtensionHandler;
       std::unique_ptr OpenMPHandler;
    +  std::unique_ptr PCSectionHandler;
       std::unique_ptr MSCommentHandler;
       std::unique_ptr MSDetectMismatchHandler;
       std::unique_ptr MSPointersToMembers;
    @@ -1460,7 +1461,8 @@ class Parser : public CodeCompletionHandler {
       };
     
       ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast);
    -  ExprResult ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast);
    +  ExprResult ParseConstantExpressionInExprEvalContext(
    +      TypeCastState isTypeCast = NotTypeCast);
       ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast);
       ExprResult ParseConstraintExpression();
       // Expr that doesn't include commas.
    diff --git a/include/clang/Rewrite/Frontend/FrontendActions.h b/include/clang/Rewrite/Frontend/FrontendActions.h
    index 27976eac4ed2..5f83ac16fedf 100644
    --- a/include/clang/Rewrite/Frontend/FrontendActions.h
    +++ b/include/clang/Rewrite/Frontend/FrontendActions.h
    @@ -11,6 +11,7 @@
     #define LLVM_CLANG_REWRITE_FRONTEND_FRONTENDACTIONS_H
     
     #include "clang/Frontend/FrontendAction.h"
    +#include "llvm/Support/raw_ostream.h"
     
     namespace clang {
     class FixItRewriter;
    @@ -34,8 +35,7 @@ class FixItAction : public ASTFrontendAction {
       std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
                                                      StringRef InFile) override;
     
    -  bool BeginSourceFileAction(CompilerInstance &CI,
    -                             StringRef Filename) override;
    +  bool BeginSourceFileAction(CompilerInstance &CI) override;
     
       void EndSourceFileAction() override;
     
    @@ -74,7 +74,10 @@ class RewriteTestAction : public PreprocessorFrontendAction {
     };
     
     class RewriteIncludesAction : public PreprocessorFrontendAction {
    +  std::shared_ptr OutputStream;
    +  class RewriteImportsListener;
     protected:
    +  bool BeginSourceFileAction(CompilerInstance &CI) override;
       void ExecuteAction() override;
     };
     
    diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
    index 941b772b7880..ffdf011d1dcb 100644
    --- a/include/clang/Sema/Overload.h
    +++ b/include/clang/Sema/Overload.h
    @@ -633,12 +633,9 @@ namespace clang {
         /// Might be a UsingShadowDecl or a FunctionTemplateDecl.
         DeclAccessPair FoundDecl;
     
    -    // BuiltinTypes - Provides the return and parameter types of a
    -    // built-in overload candidate. Only valid when Function is NULL.
    -    struct {
    -      QualType ResultTy;
    -      QualType ParamTypes[3];
    -    } BuiltinTypes;
    +    /// BuiltinParamTypes - Provides the parameter types of a built-in overload
    +    /// candidate. Only valid when Function is NULL.
    +    QualType BuiltinParamTypes[3];
     
         /// Surrogate - The conversion function for which this candidate
         /// is a surrogate, but only if IsSurrogate is true.
    diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
    index 4c9f18a0724c..8025668e664e 100644
    --- a/include/clang/Sema/Sema.h
    +++ b/include/clang/Sema/Sema.h
    @@ -336,6 +336,35 @@ class Sema {
       /// \brief Source location for newly created implicit MSInheritanceAttrs
       SourceLocation ImplicitMSInheritanceAttrLoc;
     
    +  /// \brief pragma clang section kind
    +  enum PragmaClangSectionKind {
    +    PCSK_Invalid      = 0,
    +    PCSK_BSS          = 1,
    +    PCSK_Data         = 2,
    +    PCSK_Rodata       = 3,
    +    PCSK_Text         = 4
    +   };
    +
    +  enum PragmaClangSectionAction {
    +    PCSA_Set     = 0,
    +    PCSA_Clear   = 1
    +  };
    +
    +  struct PragmaClangSection {
    +    std::string SectionName;
    +    bool Valid = false;
    +    SourceLocation PragmaLocation;
    +
    +    void Act(SourceLocation PragmaLocation,
    +             PragmaClangSectionAction Action,
    +             StringLiteral* Name);
    +   };
    +
    +   PragmaClangSection PragmaClangBSSSection;
    +   PragmaClangSection PragmaClangDataSection;
    +   PragmaClangSection PragmaClangRodataSection;
    +   PragmaClangSection PragmaClangTextSection;
    +
       enum PragmaMsStackAction {
         PSK_Reset     = 0x0,                // #pragma ()
         PSK_Set       = 0x1,                // #pragma (value)
    @@ -2698,8 +2727,7 @@ class Sema {
                                        SourceLocation OpLoc, ArrayRef Args,
                                        OverloadCandidateSet& CandidateSet,
                                        SourceRange OpRange = SourceRange());
    -  void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
    -                           ArrayRef Args,
    +  void AddBuiltinCandidate(QualType *ParamTys, ArrayRef Args,
                                OverloadCandidateSet& CandidateSet,
                                bool IsAssignmentOperator = false,
                                unsigned NumContextualBoolArguments = 0);
    @@ -7526,6 +7554,10 @@ class Sema {
                                             unsigned ThisTypeQuals);
       void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
                               const MultiLevelTemplateArgumentList &Args);
    +  bool SubstExceptionSpec(SourceLocation Loc,
    +                          FunctionProtoType::ExceptionSpecInfo &ESI,
    +                          SmallVectorImpl &ExceptionStorage,
    +                          const MultiLevelTemplateArgumentList &Args);
       ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
                                 const MultiLevelTemplateArgumentList &TemplateArgs,
                                     int indexAdjustment,
    @@ -7611,6 +7643,9 @@ class Sema {
                               LateInstantiatedAttrVec *LateAttrs = nullptr,
                               LocalInstantiationScope *OuterMostScope = nullptr);
     
    +  bool usesPartialOrExplicitSpecialization(
    +      SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec);
    +
       bool
       InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
                                ClassTemplateSpecializationDecl *ClassTemplateSpec,
    @@ -7685,7 +7720,8 @@ class Sema {
                                 const MultiLevelTemplateArgumentList &TemplateArgs);
     
       NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
    -                          const MultiLevelTemplateArgumentList &TemplateArgs);
    +                          const MultiLevelTemplateArgumentList &TemplateArgs,
    +                          bool FindingInstantiatedContext = false);
       DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
                               const MultiLevelTemplateArgumentList &TemplateArgs);
     
    @@ -8117,6 +8153,11 @@ class Sema {
         POAK_Reset    // #pragma options align=reset
       };
     
    +  /// ActOnPragmaClangSection - Called on well formed \#pragma clang section
    +  void ActOnPragmaClangSection(SourceLocation PragmaLoc,
    +                               PragmaClangSectionAction Action,
    +                               PragmaClangSectionKind SecKind, StringRef SecName);
    +
       /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
       void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
                                    SourceLocation PragmaLoc);
    diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
    index dc6e54a33206..a07cd88950d8 100644
    --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
    +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
    @@ -550,13 +550,15 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
     class PathDiagnosticCallPiece : public PathDiagnosticPiece {
       PathDiagnosticCallPiece(const Decl *callerD,
                               const PathDiagnosticLocation &callReturnPos)
    -    : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
    -      NoExit(false), callReturn(callReturnPos) {}
    +      : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
    +        NoExit(false), IsCalleeAnAutosynthesizedPropertyAccessor(false),
    +        callReturn(callReturnPos) {}
     
       PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
    -    : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
    -      NoExit(true), path(oldPath) {}
    -  
    +      : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
    +        NoExit(true), IsCalleeAnAutosynthesizedPropertyAccessor(false),
    +        path(oldPath) {}
    +
       const Decl *Caller;
       const Decl *Callee;
     
    @@ -564,6 +566,10 @@ class PathDiagnosticCallPiece : public PathDiagnosticPiece {
       // call exit.
       bool NoExit;
     
    +  // Flag signifying that the callee function is an Objective-C autosynthesized
    +  // property getter or setter.
    +  bool IsCalleeAnAutosynthesizedPropertyAccessor;
    +
       // The custom string, which should appear after the call Return Diagnostic.
       // TODO: Should we allow multiple diagnostics?
       std::string CallStackMessage;
    diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
    index 10e26ac25d17..1c974f998852 100644
    --- a/include/clang/Tooling/Tooling.h
    +++ b/include/clang/Tooling/Tooling.h
    @@ -116,7 +116,7 @@ class SourceFileCallbacks {
     
       /// \brief Called before a source file is processed by a FrontEndAction.
       /// \see clang::FrontendAction::BeginSourceFileAction
    -  virtual bool handleBeginSource(CompilerInstance &CI, StringRef Filename) {
    +  virtual bool handleBeginSource(CompilerInstance &CI) {
         return true;
       }
     
    @@ -388,12 +388,11 @@ inline std::unique_ptr newFrontendActionFactory(
           }
     
         protected:
    -      bool BeginSourceFileAction(CompilerInstance &CI,
    -                                 StringRef Filename) override {
    -        if (!clang::ASTFrontendAction::BeginSourceFileAction(CI, Filename))
    +      bool BeginSourceFileAction(CompilerInstance &CI) override {
    +        if (!clang::ASTFrontendAction::BeginSourceFileAction(CI))
               return false;
             if (Callbacks)
    -          return Callbacks->handleBeginSource(CI, Filename);
    +          return Callbacks->handleBeginSource(CI);
             return true;
           }
           void EndSourceFileAction() override {
    diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
    index 34c4d2617ec9..62b19685c677 100644
    --- a/lib/AST/ASTContext.cpp
    +++ b/lib/AST/ASTContext.cpp
    @@ -1939,9 +1939,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
       break;
     
       case Type::Pipe: {
    -    TypeInfo Info = getTypeInfo(cast(T)->getElementType());
    -    Width = Info.Width;
    -    Align = Info.Align;
    +    Width = Target->getPointerWidth(getTargetAddressSpace(LangAS::opencl_global));
    +    Align = Target->getPointerAlign(getTargetAddressSpace(LangAS::opencl_global));
       }
     
       }
    diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
    index 847638b7bbeb..493cb6df8b83 100644
    --- a/lib/AST/ASTImporter.cpp
    +++ b/lib/AST/ASTImporter.cpp
    @@ -2462,10 +2462,9 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
         return nullptr;
     
       // Create the imported parameter.
    -  ImplicitParamDecl *ToParm
    -    = ImplicitParamDecl::Create(Importer.getToContext(), DC,
    -                                Loc, Name.getAsIdentifierInfo(),
    -                                T);
    +  auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc,
    +                                           Name.getAsIdentifierInfo(), T,
    +                                           D->getParameterKind());
       return Importer.Imported(D, ToParm);
     }
     
    diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
    index bbebf758212e..ab9b59184294 100644
    --- a/lib/AST/CMakeLists.txt
    +++ b/lib/AST/CMakeLists.txt
    @@ -1,4 +1,7 @@
    -set(LLVM_LINK_COMPONENTS support)
    +set(LLVM_LINK_COMPONENTS
    +  BinaryFormat
    +  Support
    +  )
     
     add_clang_library(clangAST
       APValue.cpp
    diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
    index a1342f477b68..9862f4f26473 100644
    --- a/lib/AST/Decl.cpp
    +++ b/lib/AST/Decl.cpp
    @@ -2534,9 +2534,8 @@ bool FunctionDecl::hasTrivialBody() const
     
     bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const {
       for (auto I : redecls()) {
    -    if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed ||
    -        I->hasDefiningAttr()) {
    -      Definition = I->IsDeleted ? I->getCanonicalDecl() : I;
    +    if (I->isThisDeclarationADefinition()) {
    +      Definition = I;
           return true;
         }
       }
    @@ -4107,15 +4106,19 @@ void ImplicitParamDecl::anchor() { }
     
     ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
                                                  SourceLocation IdLoc,
    -                                             IdentifierInfo *Id,
    -                                             QualType Type) {
    -  return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type);
    +                                             IdentifierInfo *Id, QualType Type,
    +                                             ImplicitParamKind ParamKind) {
    +  return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type, ParamKind);
    +}
    +
    +ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type,
    +                                             ImplicitParamKind ParamKind) {
    +  return new (C, nullptr) ImplicitParamDecl(C, Type, ParamKind);
     }
     
     ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C,
                                                              unsigned ID) {
    -  return new (C, ID) ImplicitParamDecl(C, nullptr, SourceLocation(), nullptr,
    -                                       QualType());
    +  return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other);
     }
     
     FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
    diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
    index a12a38033c4a..a0ec0c2b251e 100644
    --- a/lib/AST/DeclObjC.cpp
    +++ b/lib/AST/DeclObjC.cpp
    @@ -1070,20 +1070,20 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
       bool selfIsPseudoStrong, selfIsConsumed;
       QualType selfTy =
         getSelfType(Context, OID, selfIsPseudoStrong, selfIsConsumed);
    -  ImplicitParamDecl *self
    -    = ImplicitParamDecl::Create(Context, this, SourceLocation(),
    -                                &Context.Idents.get("self"), selfTy);
    -  setSelfDecl(self);
    +  auto *Self = ImplicitParamDecl::Create(Context, this, SourceLocation(),
    +                                         &Context.Idents.get("self"), selfTy,
    +                                         ImplicitParamDecl::ObjCSelf);
    +  setSelfDecl(Self);
     
       if (selfIsConsumed)
    -    self->addAttr(NSConsumedAttr::CreateImplicit(Context));
    +    Self->addAttr(NSConsumedAttr::CreateImplicit(Context));
     
       if (selfIsPseudoStrong)
    -    self->setARCPseudoStrong(true);
    +    Self->setARCPseudoStrong(true);
     
    -  setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
    -                                       &Context.Idents.get("_cmd"),
    -                                       Context.getObjCSelType()));
    +  setCmdDecl(ImplicitParamDecl::Create(
    +      Context, this, SourceLocation(), &Context.Idents.get("_cmd"),
    +      Context.getObjCSelType(), ImplicitParamDecl::ObjCCmd));
     }
     
     ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
    diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp
    index 0e822ce35b8c..08593da89bbd 100644
    --- a/lib/AST/ODRHash.cpp
    +++ b/lib/AST/ODRHash.cpp
    @@ -82,13 +82,25 @@ void ODRHash::AddDeclarationName(DeclarationName Name) {
     }
     
     void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
    -  assert(NNS && "Expecting non-null pointer.");
    -  const auto *Prefix = NNS->getPrefix();
    -  AddBoolean(Prefix);
    -  if (Prefix) {
    -    AddNestedNameSpecifier(Prefix);
    +  // Unlike the other pointer handling functions, allow null pointers here.
    +  if (!NNS) {
    +    AddBoolean(false);
    +    return;
       }
    +
    +  // Skip inlined namespaces.
       auto Kind = NNS->getKind();
    +  if (Kind == NestedNameSpecifier::Namespace) {
    +    if (NNS->getAsNamespace()->isInline()) {
    +      return AddNestedNameSpecifier(NNS->getPrefix());
    +    }
    +  }
    +
    +  AddBoolean(true);
    +
    +  // Process prefix
    +  AddNestedNameSpecifier(NNS->getPrefix());
    +
       ID.AddInteger(Kind);
       switch (Kind) {
       case NestedNameSpecifier::Identifier:
    @@ -381,10 +393,7 @@ class ODRTypeVisitor : public TypeVisitor {
       }
     
       void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
    -    Hash.AddBoolean(NNS);
    -    if (NNS) {
    -      Hash.AddNestedNameSpecifier(NNS);
    -    }
    +    Hash.AddNestedNameSpecifier(NNS);
       }
     
       void AddIdentifierInfo(const IdentifierInfo *II) {
    diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
    index f1fbe2806b5d..99a25f342526 100644
    --- a/lib/AST/StmtProfile.cpp
    +++ b/lib/AST/StmtProfile.cpp
    @@ -186,10 +186,7 @@ namespace {
           Hash.AddTemplateName(Name);
         }
         void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override {
    -      ID.AddBoolean(NNS);
    -      if (NNS) {
    -        Hash.AddNestedNameSpecifier(NNS);
    -      }
    +      Hash.AddNestedNameSpecifier(NNS);
         }
       };
     }
    diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
    index 1e10094aeeea..a62ca5f9b4d7 100644
    --- a/lib/AST/Type.cpp
    +++ b/lib/AST/Type.cpp
    @@ -1344,7 +1344,7 @@ Optional> Type::getObjCSubstitutions(
       } else if (getAs()) {
         ASTContext &ctx = dc->getParentASTContext();
         objectType = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, { })
    -                   ->castAs();;
    +                   ->castAs();
       } else {
         objectType = getAs();
       }
    diff --git a/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/lib/ASTMatchers/Dynamic/Diagnostics.cpp
    index 787b780c4243..9cddcf93caef 100644
    --- a/lib/ASTMatchers/Dynamic/Diagnostics.cpp
    +++ b/lib/ASTMatchers/Dynamic/Diagnostics.cpp
    @@ -118,8 +118,8 @@ static StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
         return "Malformed bind() expression.";
       case Diagnostics::ET_ParserTrailingCode:
         return "Expected end of code.";
    -  case Diagnostics::ET_ParserUnsignedError:
    -    return "Error parsing unsigned token: <$0>";
    +  case Diagnostics::ET_ParserNumberError:
    +    return "Error parsing numeric literal: <$0>";
       case Diagnostics::ET_ParserOverloadedType:
         return "Input value has unresolved overloaded type: $0";
     
    diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
    index fb6b349a811c..c557ff162691 100644
    --- a/lib/ASTMatchers/Dynamic/Marshallers.h
    +++ b/lib/ASTMatchers/Dynamic/Marshallers.h
    @@ -65,6 +65,26 @@ template  struct ArgTypeTraits > {
       }
     };
     
    +template <> struct ArgTypeTraits {
    +  static bool is(const VariantValue &Value) { return Value.isBoolean(); }
    +  static bool get(const VariantValue &Value) {
    +    return Value.getBoolean();
    +  }
    +  static ArgKind getKind() {
    +    return ArgKind(ArgKind::AK_Boolean);
    +  }
    +};
    +
    +template <> struct ArgTypeTraits {
    +  static bool is(const VariantValue &Value) { return Value.isDouble(); }
    +  static double get(const VariantValue &Value) {
    +    return Value.getDouble();
    +  }
    +  static ArgKind getKind() {
    +    return ArgKind(ArgKind::AK_Double);
    +  }
    +};
    +
     template <> struct ArgTypeTraits {
       static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
       static unsigned get(const VariantValue &Value) {
    diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
    index ce8d0a9a0206..f5bd29668995 100644
    --- a/lib/ASTMatchers/Dynamic/Parser.cpp
    +++ b/lib/ASTMatchers/Dynamic/Parser.cpp
    @@ -130,8 +130,8 @@ class Parser::CodeTokenizer {
     
         case '0': case '1': case '2': case '3': case '4':
         case '5': case '6': case '7': case '8': case '9':
    -      // Parse an unsigned literal.
    -      consumeUnsignedLiteral(&Result);
    +      // Parse an unsigned and float literal.
    +      consumeNumberLiteral(&Result);
           break;
     
         default:
    @@ -153,8 +153,16 @@ class Parser::CodeTokenizer {
                 break;
               ++TokenLength;
             }
    -        Result.Kind = TokenInfo::TK_Ident;
    -        Result.Text = Code.substr(0, TokenLength);
    +        if (TokenLength == 4 && Code.startswith("true")) {
    +          Result.Kind = TokenInfo::TK_Literal;
    +          Result.Value = true;
    +        } else if (TokenLength == 5 && Code.startswith("false")) {
    +          Result.Kind = TokenInfo::TK_Literal;
    +          Result.Value = false;
    +        } else {
    +          Result.Kind = TokenInfo::TK_Ident;
    +          Result.Text = Code.substr(0, TokenLength);
    +        }
             Code = Code.drop_front(TokenLength);
           } else {
             Result.Kind = TokenInfo::TK_InvalidChar;
    @@ -168,8 +176,9 @@ class Parser::CodeTokenizer {
         return Result;
       }
     
    -  /// \brief Consume an unsigned literal.
    -  void consumeUnsignedLiteral(TokenInfo *Result) {
    +  /// \brief Consume an unsigned and float literal.
    +  void consumeNumberLiteral(TokenInfo *Result) {
    +    bool isFloatingLiteral = false;
         unsigned Length = 1;
         if (Code.size() > 1) {
           // Consume the 'x' or 'b' radix modifier, if present.
    @@ -180,20 +189,44 @@ class Parser::CodeTokenizer {
         while (Length < Code.size() && isHexDigit(Code[Length]))
           ++Length;
     
    +    // Try to recognize a floating point literal.
    +    while (Length < Code.size()) {
    +      char c = Code[Length];
    +      if (c == '-' || c == '+' || c == '.' || isHexDigit(c)) {
    +        isFloatingLiteral = true;
    +        Length++;
    +      } else {
    +        break;
    +      }
    +    }
    +
         Result->Text = Code.substr(0, Length);
         Code = Code.drop_front(Length);
     
    -    unsigned Value;
    -    if (!Result->Text.getAsInteger(0, Value)) {
    -      Result->Kind = TokenInfo::TK_Literal;
    -      Result->Value = Value;
    +    if (isFloatingLiteral) {
    +      char *end;
    +      errno = 0;
    +      std::string Text = Result->Text.str();
    +      double doubleValue = strtod(Text.c_str(), &end);
    +      if (*end == 0 && errno == 0) {
    +        Result->Kind = TokenInfo::TK_Literal;
    +        Result->Value = doubleValue;
    +        return;
    +      }
         } else {
    -      SourceRange Range;
    -      Range.Start = Result->Range.Start;
    -      Range.End = currentLocation();
    -      Error->addError(Range, Error->ET_ParserUnsignedError) << Result->Text;
    -      Result->Kind = TokenInfo::TK_Error;
    +      unsigned Value;
    +      if (!Result->Text.getAsInteger(0, Value)) {
    +        Result->Kind = TokenInfo::TK_Literal;
    +        Result->Value = Value;
    +        return;
    +      }
         }
    +
    +    SourceRange Range;
    +    Range.Start = Result->Range.Start;
    +    Range.End = currentLocation();
    +    Error->addError(Range, Error->ET_ParserNumberError) << Result->Text;
    +    Result->Kind = TokenInfo::TK_Error;
       }
     
       /// \brief Consume a string literal.
    diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
    index 26743d86f5e7..031ceb320306 100644
    --- a/lib/ASTMatchers/Dynamic/Registry.cpp
    +++ b/lib/ASTMatchers/Dynamic/Registry.cpp
    @@ -56,20 +56,24 @@ void RegistryMaps::registerMatcher(
       registerMatcher(#name, internal::makeMatcherAutoMarshall(                    \
                                  ::clang::ast_matchers::name, #name));
     
    +#define REGISTER_MATCHER_OVERLOAD(name)                                        \
    +  registerMatcher(#name,                                                       \
    +      llvm::make_unique(name##Callbacks))
    +
     #define SPECIFIC_MATCHER_OVERLOAD(name, Id)                                    \
       static_cast<::clang::ast_matchers::name##_Type##Id>(                         \
           ::clang::ast_matchers::name)
     
    +#define MATCHER_OVERLOAD_ENTRY(name, Id)                                       \
    +        internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, Id), \
    +                                          #name)
    +
     #define REGISTER_OVERLOADED_2(name)                                            \
       do {                                                                         \
    -    std::unique_ptr Callbacks[] = {                         \
    -        internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0),  \
    -                                          #name),                              \
    -        internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1),  \
    -                                          #name)};                             \
    -    registerMatcher(                                                           \
    -        #name,                                                                 \
    -        llvm::make_unique(Callbacks));  \
    +    std::unique_ptr name##Callbacks[] = {                   \
    +        MATCHER_OVERLOAD_ENTRY(name, 0),                                       \
    +        MATCHER_OVERLOAD_ENTRY(name, 1)};                                      \
    +    REGISTER_MATCHER_OVERLOAD(name);                                           \
       } while (0)
     
     /// \brief Generate a registry map with all the known matchers.
    @@ -83,7 +87,6 @@ RegistryMaps::RegistryMaps() {
       // findAll
       //
       // Other:
    -  // equals
       // equalsNode
     
       REGISTER_OVERLOADED_2(callee);
    @@ -96,6 +99,13 @@ RegistryMaps::RegistryMaps() {
       REGISTER_OVERLOADED_2(references);
       REGISTER_OVERLOADED_2(thisPointerType);
     
    +  std::unique_ptr equalsCallbacks[] = {
    +      MATCHER_OVERLOAD_ENTRY(equals, 0),
    +      MATCHER_OVERLOAD_ENTRY(equals, 1),
    +      MATCHER_OVERLOAD_ENTRY(equals, 2),
    +  };
    +  REGISTER_MATCHER_OVERLOAD(equals);
    +
       REGISTER_MATCHER(accessSpecDecl);
       REGISTER_MATCHER(addrLabelExpr);
       REGISTER_MATCHER(alignOfExpr);
    diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp
    index f0339ed479cd..57858d00acb4 100644
    --- a/lib/ASTMatchers/Dynamic/VariantValue.cpp
    +++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp
    @@ -24,6 +24,10 @@ std::string ArgKind::asString() const {
       switch (getArgKind()) {
       case AK_Matcher:
         return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
    +  case AK_Boolean:
    +    return "boolean";
    +  case AK_Double:
    +    return "double";
       case AK_Unsigned:
         return "unsigned";
       case AK_String:
    @@ -247,6 +251,14 @@ VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
       *this = Other;
     }
     
    +VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
    +  setBoolean(Boolean);
    +}
    +
    +VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
    +  setDouble(Double);
    +}
    +
     VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
       setUnsigned(Unsigned);
     }
    @@ -265,6 +277,12 @@ VariantValue &VariantValue::operator=(const VariantValue &Other) {
       if (this == &Other) return *this;
       reset();
       switch (Other.Type) {
    +  case VT_Boolean:
    +    setBoolean(Other.getBoolean());
    +    break;
    +  case VT_Double:
    +    setDouble(Other.getDouble());
    +    break;
       case VT_Unsigned:
         setUnsigned(Other.getUnsigned());
         break;
    @@ -290,6 +308,8 @@ void VariantValue::reset() {
         delete Value.Matcher;
         break;
       // Cases that do nothing.
    +  case VT_Boolean:
    +  case VT_Double:
       case VT_Unsigned:
       case VT_Nothing:
         break;
    @@ -297,6 +317,36 @@ void VariantValue::reset() {
       Type = VT_Nothing;
     }
     
    +bool VariantValue::isBoolean() const {
    +  return Type == VT_Boolean;
    +}
    +
    +bool VariantValue::getBoolean() const {
    +  assert(isBoolean());
    +  return Value.Boolean;
    +}
    +
    +void VariantValue::setBoolean(bool NewValue) {
    +  reset();
    +  Type = VT_Boolean;
    +  Value.Boolean = NewValue;
    +}
    +
    +bool VariantValue::isDouble() const {
    +  return Type == VT_Double;
    +}
    +
    +double VariantValue::getDouble() const {
    +  assert(isDouble());
    +  return Value.Double;
    +}
    +
    +void VariantValue::setDouble(double NewValue) {
    +  reset();
    +  Type = VT_Double;
    +  Value.Double = NewValue;
    +}
    +
     bool VariantValue::isUnsigned() const {
       return Type == VT_Unsigned;
     }
    @@ -344,6 +394,18 @@ void VariantValue::setMatcher(const VariantMatcher &NewValue) {
     
     bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
       switch (Kind.getArgKind()) {
    +  case ArgKind::AK_Boolean:
    +    if (!isBoolean())
    +      return false;
    +    *Specificity = 1;
    +    return true;
    +
    +  case ArgKind::AK_Double:
    +    if (!isDouble())
    +      return false;
    +    *Specificity = 1;
    +    return true;
    +
       case ArgKind::AK_Unsigned:
         if (!isUnsigned())
           return false;
    @@ -383,6 +445,8 @@ std::string VariantValue::getTypeAsString() const {
       switch (Type) {
       case VT_String: return "String";
       case VT_Matcher: return getMatcher().getTypeAsString();
    +  case VT_Boolean: return "Boolean";
    +  case VT_Double: return "Double";
       case VT_Unsigned: return "Unsigned";
       case VT_Nothing: return "Nothing";
       }
    diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
    index c5cff74ac97d..fc4c6d303801 100644
    --- a/lib/Basic/SourceManager.cpp
    +++ b/lib/Basic/SourceManager.cpp
    @@ -73,11 +73,11 @@ void ContentCache::replaceBuffer(llvm::MemoryBuffer *B, bool DoNotFree) {
         Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
         return;
       }
    -  
    +
       if (shouldFreeBuffer())
         delete Buffer.getPointer();
       Buffer.setPointer(B);
    -  Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
    +  Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0);
     }
     
     llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
    @@ -345,6 +345,43 @@ void SourceManager::clearIDTables() {
       createExpansionLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1);
     }
     
    +void SourceManager::initializeForReplay(const SourceManager &Old) {
    +  assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");
    +
    +  auto CloneContentCache = [&](const ContentCache *Cache) -> ContentCache * {
    +    auto *Clone = new (ContentCacheAlloc.Allocate()) ContentCache;
    +    Clone->OrigEntry = Cache->OrigEntry;
    +    Clone->ContentsEntry = Cache->ContentsEntry;
    +    Clone->BufferOverridden = Cache->BufferOverridden;
    +    Clone->IsSystemFile = Cache->IsSystemFile;
    +    Clone->IsTransient = Cache->IsTransient;
    +    Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true);
    +    return Clone;
    +  };
    +
    +  // Set up our main file ID as a copy of the old source manager's main file.
    +  const SLocEntry &OldMainFile = Old.getSLocEntry(Old.getMainFileID());
    +  assert(OldMainFile.isFile() && "main file is macro expansion?");
    +  auto *MainCC = CloneContentCache(OldMainFile.getFile().getContentCache());
    +  MemBufferInfos.push_back(MainCC);
    +  setMainFileID(createFileID(MainCC, SourceLocation(),
    +                             OldMainFile.getFile().getFileCharacteristic(),
    +                             0, 0));
    +
    +  // Ensure all SLocEntries are loaded from the external source.
    +  for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
    +    if (!Old.SLocEntryLoaded[I])
    +      Old.loadSLocEntry(I, nullptr);
    +
    +  // Inherit any content cache data from the old source manager.
    +  for (auto &FileInfo : Old.FileInfos) {
    +    SrcMgr::ContentCache *&Slot = FileInfos[FileInfo.first];
    +    if (Slot)
    +      continue;
    +    Slot = CloneContentCache(FileInfo.second);
    +  }
    +}
    +
     /// getOrCreateContentCache - Create or return a cached ContentCache for the
     /// specified file.
     const ContentCache *
    diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
    index 605f73802afb..a3b8330707b9 100644
    --- a/lib/Basic/Targets.cpp
    +++ b/lib/Basic/Targets.cpp
    @@ -5385,6 +5385,10 @@ class ARMTargetInfo : public TargetInfo {
         // ARM has atomics up to 8 bytes
         setAtomic();
     
    +    // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
    +    if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
    +       MaxVectorAlign = 64;
    +
         // Do force alignment of members that follow zero length bitfields.  If
         // the alignment of the zero-length bitfield is greater than the member
         // that follows it, `bar', `bar' will be aligned as the  type of the
    @@ -5438,7 +5442,24 @@ class ARMTargetInfo : public TargetInfo {
           if (Feature[0] == '+')
             Features[Feature.drop_front(1)] = true;
     
    -    return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
    +    // Enable or disable thumb-mode explicitly per function to enable mixed
    +    // ARM and Thumb code generation.
    +    if (isThumb())
    +      Features["thumb-mode"] = true;
    +    else
    +      Features["thumb-mode"] = false;
    +
    +    // Convert user-provided arm and thumb GNU target attributes to
    +    // [-|+]thumb-mode target features respectively.
    +    std::vector UpdatedFeaturesVec(FeaturesVec);
    +    for (auto &Feature : UpdatedFeaturesVec) {
    +      if (Feature.compare("+arm") == 0)
    +        Feature = "-thumb-mode";
    +      else if (Feature.compare("+thumb") == 0)
    +        Feature = "+thumb-mode";
    +    }
    +
    +    return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
       }
     
       bool handleTargetFeatures(std::vector &Features,
    @@ -7716,6 +7737,7 @@ class MipsTargetInfo : public TargetInfo {
         NoDSP, DSP1, DSP2
       } DspRev;
       bool HasMSA;
    +  bool DisableMadd4;
     
     protected:
       bool HasFP64;
    @@ -7726,7 +7748,7 @@ class MipsTargetInfo : public TargetInfo {
           : TargetInfo(Triple), IsMips16(false), IsMicromips(false),
             IsNan2008(false), IsSingleFloat(false), IsNoABICalls(false),
             CanUseBSDABICalls(false), FloatABI(HardFloat), DspRev(NoDSP),
    -        HasMSA(false), HasFP64(false) {
    +        HasMSA(false), DisableMadd4(false), HasFP64(false) {
         TheCXXABI.set(TargetCXXABI::GenericMIPS);
     
         setABI((getTriple().getArch() == llvm::Triple::mips ||
    @@ -7972,6 +7994,9 @@ class MipsTargetInfo : public TargetInfo {
         if (HasMSA)
           Builder.defineMacro("__mips_msa", Twine(1));
     
    +    if (DisableMadd4)
    +      Builder.defineMacro("__mips_no_madd4", Twine(1));
    +
         Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0)));
         Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));
         Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));
    @@ -8134,6 +8159,8 @@ class MipsTargetInfo : public TargetInfo {
             DspRev = std::max(DspRev, DSP2);
           else if (Feature == "+msa")
             HasMSA = true;
    +      else if (Feature == "+nomadd4")
    +        DisableMadd4 = true;
           else if (Feature == "+fp64")
             HasFP64 = true;
           else if (Feature == "-fp64")
    @@ -8466,7 +8493,7 @@ class WebAssembly32TargetInfo : public WebAssemblyTargetInfo {
       explicit WebAssembly32TargetInfo(const llvm::Triple &T,
                                        const TargetOptions &Opts)
           : WebAssemblyTargetInfo(T, Opts) {
    -    MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
    +    MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
         resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128");
       }
     
    diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
    index fd193bcf1a69..9c4316fb1cd5 100644
    --- a/lib/CodeGen/BackendUtil.cpp
    +++ b/lib/CodeGen/BackendUtil.cpp
    @@ -410,7 +410,7 @@ static void initTargetOptions(llvm::TargetOptions &Options,
     
       Options.UseInitArray = CodeGenOpts.UseInitArray;
       Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS;
    -  Options.CompressDebugSections = CodeGenOpts.CompressDebugSections;
    +  Options.CompressDebugSections = CodeGenOpts.getCompressDebugSections();
       Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations;
     
       // Set EABI version.
    diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
    index 2e423b25f0fb..528a2b33acf8 100644
    --- a/lib/CodeGen/CGBlocks.cpp
    +++ b/lib/CodeGen/CGBlocks.cpp
    @@ -903,9 +903,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
         } else {
           // Fake up a new variable so that EmitScalarInit doesn't think
           // we're referring to the variable in its own initializer.
    -      ImplicitParamDecl blockFieldPseudoVar(getContext(), /*DC*/ nullptr,
    -                                            SourceLocation(), /*name*/ nullptr,
    -                                            type);
    +      ImplicitParamDecl BlockFieldPseudoVar(getContext(), type,
    +                                            ImplicitParamDecl::Other);
     
           // We use one of these or the other depending on whether the
           // reference is nested.
    @@ -919,7 +918,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
           // attributed to a reasonable location - otherwise it may be attributed to
           // locations of subexpressions in the initialization.
           LValueBaseInfo BaseInfo(AlignmentSource::Decl, false);
    -      EmitExprAsInit(&l2r, &blockFieldPseudoVar,
    +      EmitExprAsInit(&l2r, &BlockFieldPseudoVar,
                          MakeAddrLValue(blockField, type, BaseInfo),
                          /*captured by init*/ false);
         }
    @@ -1264,9 +1263,10 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
     
       IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
     
    -  ImplicitParamDecl selfDecl(getContext(), const_cast(blockDecl),
    -                             SourceLocation(), II, selfTy);
    -  args.push_back(&selfDecl);
    +  ImplicitParamDecl SelfDecl(getContext(), const_cast(blockDecl),
    +                             SourceLocation(), II, selfTy,
    +                             ImplicitParamDecl::ObjCSelf);
    +  args.push_back(&SelfDecl);
     
       // Now add the rest of the parameters.
       args.append(blockDecl->param_begin(), blockDecl->param_end());
    @@ -1499,12 +1499,12 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
       ASTContext &C = getContext();
     
       FunctionArgList args;
    -  ImplicitParamDecl dstDecl(getContext(), nullptr, SourceLocation(), nullptr,
    -                            C.VoidPtrTy);
    -  args.push_back(&dstDecl);
    -  ImplicitParamDecl srcDecl(getContext(), nullptr, SourceLocation(), nullptr,
    -                            C.VoidPtrTy);
    -  args.push_back(&srcDecl);
    +  ImplicitParamDecl DstDecl(getContext(), C.VoidPtrTy,
    +                            ImplicitParamDecl::Other);
    +  args.push_back(&DstDecl);
    +  ImplicitParamDecl SrcDecl(getContext(), C.VoidPtrTy,
    +                            ImplicitParamDecl::Other);
    +  args.push_back(&SrcDecl);
     
       const CGFunctionInfo &FI =
         CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
    @@ -1536,11 +1536,11 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
       auto AL = ApplyDebugLocation::CreateArtificial(*this);
       llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
     
    -  Address src = GetAddrOfLocalVar(&srcDecl);
    +  Address src = GetAddrOfLocalVar(&SrcDecl);
       src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign);
       src = Builder.CreateBitCast(src, structPtrTy, "block.source");
     
    -  Address dst = GetAddrOfLocalVar(&dstDecl);
    +  Address dst = GetAddrOfLocalVar(&DstDecl);
       dst = Address(Builder.CreateLoad(dst), blockInfo.BlockAlign);
       dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest");
     
    @@ -1676,9 +1676,9 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
       ASTContext &C = getContext();
     
       FunctionArgList args;
    -  ImplicitParamDecl srcDecl(getContext(), nullptr, SourceLocation(), nullptr,
    -                            C.VoidPtrTy);
    -  args.push_back(&srcDecl);
    +  ImplicitParamDecl SrcDecl(getContext(), C.VoidPtrTy,
    +                            ImplicitParamDecl::Other);
    +  args.push_back(&SrcDecl);
     
       const CGFunctionInfo &FI =
         CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
    @@ -1709,7 +1709,7 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
     
       llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
     
    -  Address src = GetAddrOfLocalVar(&srcDecl);
    +  Address src = GetAddrOfLocalVar(&SrcDecl);
       src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign);
       src = Builder.CreateBitCast(src, structPtrTy, "block");
     
    @@ -1918,13 +1918,13 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
       QualType R = Context.VoidTy;
     
       FunctionArgList args;
    -  ImplicitParamDecl dst(CGF.getContext(), nullptr, SourceLocation(), nullptr,
    -                        Context.VoidPtrTy);
    -  args.push_back(&dst);
    +  ImplicitParamDecl Dst(CGF.getContext(), Context.VoidPtrTy,
    +                        ImplicitParamDecl::Other);
    +  args.push_back(&Dst);
     
    -  ImplicitParamDecl src(CGF.getContext(), nullptr, SourceLocation(), nullptr,
    -                        Context.VoidPtrTy);
    -  args.push_back(&src);
    +  ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy,
    +                        ImplicitParamDecl::Other);
    +  args.push_back(&Src);
     
       const CGFunctionInfo &FI =
         CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args);
    @@ -1955,7 +1955,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
         llvm::Type *byrefPtrType = byrefInfo.Type->getPointerTo(0);
     
         // dst->x
    -    Address destField = CGF.GetAddrOfLocalVar(&dst);
    +    Address destField = CGF.GetAddrOfLocalVar(&Dst);
         destField = Address(CGF.Builder.CreateLoad(destField),
                             byrefInfo.ByrefAlignment);
         destField = CGF.Builder.CreateBitCast(destField, byrefPtrType);
    @@ -1963,7 +1963,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
                                               "dest-object");
     
         // src->x
    -    Address srcField = CGF.GetAddrOfLocalVar(&src);
    +    Address srcField = CGF.GetAddrOfLocalVar(&Src);
         srcField = Address(CGF.Builder.CreateLoad(srcField),
                            byrefInfo.ByrefAlignment);
         srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType);
    @@ -1995,9 +1995,9 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
       QualType R = Context.VoidTy;
     
       FunctionArgList args;
    -  ImplicitParamDecl src(CGF.getContext(), nullptr, SourceLocation(), nullptr,
    -                        Context.VoidPtrTy);
    -  args.push_back(&src);
    +  ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy,
    +                        ImplicitParamDecl::Other);
    +  args.push_back(&Src);
     
       const CGFunctionInfo &FI =
         CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args);
    @@ -2026,7 +2026,7 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
       CGF.StartFunction(FD, R, Fn, FI, args);
     
       if (generator.needsDispose()) {
    -    Address addr = CGF.GetAddrOfLocalVar(&src);
    +    Address addr = CGF.GetAddrOfLocalVar(&Src);
         addr = Address(CGF.Builder.CreateLoad(addr), byrefInfo.ByrefAlignment);
         auto byrefPtrType = byrefInfo.Type->getPointerTo(0);
         addr = CGF.Builder.CreateBitCast(addr, byrefPtrType);
    diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
    index df75a7d7ffde..e29e525edd24 100644
    --- a/lib/CodeGen/CGCXXABI.cpp
    +++ b/lib/CodeGen/CGCXXABI.cpp
    @@ -159,10 +159,10 @@ void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) {
     
       // FIXME: I'm not entirely sure I like using a fake decl just for code
       // generation. Maybe we can come up with a better way?
    -  ImplicitParamDecl *ThisDecl
    -    = ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(),
    -                                &CGM.getContext().Idents.get("this"),
    -                                MD->getThisType(CGM.getContext()));
    +  auto *ThisDecl = ImplicitParamDecl::Create(
    +      CGM.getContext(), nullptr, MD->getLocation(),
    +      &CGM.getContext().Idents.get("this"), MD->getThisType(CGM.getContext()),
    +      ImplicitParamDecl::CXXThis);
       params.push_back(ThisDecl);
       CGF.CXXABIThisDecl = ThisDecl;
     
    diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
    index 02db79159b58..ebb264eb61c9 100644
    --- a/lib/CodeGen/CGDebugInfo.cpp
    +++ b/lib/CodeGen/CGDebugInfo.cpp
    @@ -3466,13 +3466,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
       unsigned AddressSpace = CGM.getContext().getTargetAddressSpace(VD->getType());
       AppendAddressSpaceXDeref(AddressSpace, Expr);
     
    -  // If this is the first argument and it is implicit then
    -  // give it an object pointer flag.
    -  // FIXME: There has to be a better way to do this, but for static
    -  // functions there won't be an implicit param at arg1 and
    -  // otherwise it is 'self' or 'this'.
    -  if (isa(VD) && ArgNo && *ArgNo == 1)
    -  Flags |= llvm::DINode::FlagObjectPointer;
    +  // If this is implicit parameter of CXXThis or ObjCSelf kind, then give it an
    +  // object pointer flag.
    +  if (const auto *IPD = dyn_cast(VD)) {
    +    if (IPD->getParameterKind() == ImplicitParamDecl::CXXThis ||
    +        IPD->getParameterKind() == ImplicitParamDecl::ObjCSelf)
    +      Flags |= llvm::DINode::FlagObjectPointer;
    +  }
     
       // Note: Older versions of clang used to emit byval references with an extra
       // DW_OP_deref, because they referenced the IR arg directly instead of
    @@ -3583,8 +3583,9 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
     
       // Self is passed along as an implicit non-arg variable in a
       // block. Mark it as the object pointer.
    -  if (isa(VD) && VD->getName() == "self")
    -    Ty = CreateSelfType(VD->getType(), Ty);
    +  if (const auto *IPD = dyn_cast(VD))
    +    if (IPD->getParameterKind() == ImplicitParamDecl::ObjCSelf)
    +      Ty = CreateSelfType(VD->getType(), Ty);
     
       // Get location information.
       unsigned Line = getLineNumber(VD->getLocation());
    diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
    index d6abfa15e541..87bfa507a8c0 100644
    --- a/lib/CodeGen/CGDecl.cpp
    +++ b/lib/CodeGen/CGDecl.cpp
    @@ -406,6 +406,13 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
       if (D.hasAttr())
         CGM.AddGlobalAnnotations(&D, var);
     
    +  if (auto *SA = D.getAttr())
    +    var->addAttribute("bss-section", SA->getName());
    +  if (auto *SA = D.getAttr())
    +    var->addAttribute("data-section", SA->getName());
    +  if (auto *SA = D.getAttr())
    +    var->addAttribute("rodata-section", SA->getName());
    +
       if (const SectionAttr *SA = D.getAttr())
         var->setSection(SA->getName());
     
    diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
    index ff766e6b3b9c..d8768bee2cdf 100644
    --- a/lib/CodeGen/CGDeclCXX.cpp
    +++ b/lib/CodeGen/CGDeclCXX.cpp
    @@ -603,9 +603,9 @@ llvm::Function *CodeGenFunction::generateDestroyHelper(
         Address addr, QualType type, Destroyer *destroyer,
         bool useEHCleanupForArray, const VarDecl *VD) {
       FunctionArgList args;
    -  ImplicitParamDecl dst(getContext(), nullptr, SourceLocation(), nullptr,
    -                        getContext().VoidPtrTy);
    -  args.push_back(&dst);
    +  ImplicitParamDecl Dst(getContext(), getContext().VoidPtrTy,
    +                        ImplicitParamDecl::Other);
    +  args.push_back(&Dst);
     
       const CGFunctionInfo &FI =
         CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, args);
    diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
    index e65fa863fe31..40ae0921098c 100644
    --- a/lib/CodeGen/CGException.cpp
    +++ b/lib/CodeGen/CGException.cpp
    @@ -1649,18 +1649,19 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
         // parameters. Win32 filters take no parameters.
         if (IsFilter) {
           Args.push_back(ImplicitParamDecl::Create(
    -          getContext(), nullptr, StartLoc,
    +          getContext(), /*DC=*/nullptr, StartLoc,
               &getContext().Idents.get("exception_pointers"),
    -          getContext().VoidPtrTy));
    +          getContext().VoidPtrTy, ImplicitParamDecl::Other));
         } else {
           Args.push_back(ImplicitParamDecl::Create(
    -          getContext(), nullptr, StartLoc,
    +          getContext(), /*DC=*/nullptr, StartLoc,
               &getContext().Idents.get("abnormal_termination"),
    -          getContext().UnsignedCharTy));
    +          getContext().UnsignedCharTy, ImplicitParamDecl::Other));
         }
         Args.push_back(ImplicitParamDecl::Create(
    -        getContext(), nullptr, StartLoc,
    -        &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
    +        getContext(), /*DC=*/nullptr, StartLoc,
    +        &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy,
    +        ImplicitParamDecl::Other));
       }
     
       QualType RetTy = IsFilter ? getContext().LongTy : getContext().VoidTy;
    diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
    index 2aa045879213..9f800a75b5bc 100644
    --- a/lib/CodeGen/CGExpr.cpp
    +++ b/lib/CodeGen/CGExpr.cpp
    @@ -2847,10 +2847,10 @@ void CodeGenFunction::EmitCfiCheckStub() {
     void CodeGenFunction::EmitCfiCheckFail() {
       SanitizerScope SanScope(this);
       FunctionArgList Args;
    -  ImplicitParamDecl ArgData(getContext(), nullptr, SourceLocation(), nullptr,
    -                            getContext().VoidPtrTy);
    -  ImplicitParamDecl ArgAddr(getContext(), nullptr, SourceLocation(), nullptr,
    -                            getContext().VoidPtrTy);
    +  ImplicitParamDecl ArgData(getContext(), getContext().VoidPtrTy,
    +                            ImplicitParamDecl::Other);
    +  ImplicitParamDecl ArgAddr(getContext(), getContext().VoidPtrTy,
    +                            ImplicitParamDecl::Other);
       Args.push_back(&ArgData);
       Args.push_back(&ArgAddr);
     
    diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
    index 820520121763..90fcad261415 100644
    --- a/lib/CodeGen/CGObjC.cpp
    +++ b/lib/CodeGen/CGObjC.cpp
    @@ -3246,10 +3246,12 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
       SrcTy = C.getPointerType(SrcTy);
       
       FunctionArgList args;
    -  ImplicitParamDecl dstDecl(getContext(), FD, SourceLocation(), nullptr,DestTy);
    -  args.push_back(&dstDecl);
    -  ImplicitParamDecl srcDecl(getContext(), FD, SourceLocation(), nullptr, SrcTy);
    -  args.push_back(&srcDecl);
    +  ImplicitParamDecl DstDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
    +                            DestTy, ImplicitParamDecl::Other);
    +  args.push_back(&DstDecl);
    +  ImplicitParamDecl SrcDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
    +                            SrcTy, ImplicitParamDecl::Other);
    +  args.push_back(&SrcDecl);
     
       const CGFunctionInfo &FI =
         CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
    @@ -3265,12 +3267,12 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
     
       StartFunction(FD, C.VoidTy, Fn, FI, args);
       
    -  DeclRefExpr DstExpr(&dstDecl, false, DestTy,
    +  DeclRefExpr DstExpr(&DstDecl, false, DestTy,
                           VK_RValue, SourceLocation());
       UnaryOperator DST(&DstExpr, UO_Deref, DestTy->getPointeeType(),
                         VK_LValue, OK_Ordinary, SourceLocation());
       
    -  DeclRefExpr SrcExpr(&srcDecl, false, SrcTy,
    +  DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy,
                           VK_RValue, SourceLocation());
       UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
                         VK_LValue, OK_Ordinary, SourceLocation());
    @@ -3327,10 +3329,12 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
       SrcTy = C.getPointerType(SrcTy);
       
       FunctionArgList args;
    -  ImplicitParamDecl dstDecl(getContext(), FD, SourceLocation(), nullptr,DestTy);
    -  args.push_back(&dstDecl);
    -  ImplicitParamDecl srcDecl(getContext(), FD, SourceLocation(), nullptr, SrcTy);
    -  args.push_back(&srcDecl);
    +  ImplicitParamDecl DstDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
    +                            DestTy, ImplicitParamDecl::Other);
    +  args.push_back(&DstDecl);
    +  ImplicitParamDecl SrcDecl(getContext(), FD, SourceLocation(), /*Id=*/nullptr,
    +                            SrcTy, ImplicitParamDecl::Other);
    +  args.push_back(&SrcDecl);
     
       const CGFunctionInfo &FI =
         CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, args);
    @@ -3345,7 +3349,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
     
       StartFunction(FD, C.VoidTy, Fn, FI, args);
       
    -  DeclRefExpr SrcExpr(&srcDecl, false, SrcTy,
    +  DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy,
                           VK_RValue, SourceLocation());
       
       UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
    @@ -3371,7 +3375,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
                                  CXXConstExpr->getConstructionKind(),
                                  SourceRange());
       
    -  DeclRefExpr DstExpr(&dstDecl, false, DestTy,
    +  DeclRefExpr DstExpr(&DstDecl, false, DestTy,
                           VK_RValue, SourceLocation());
       
       RValue DV = EmitAnyExpr(&DstExpr);
    diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
    index 9c048423285b..c78d3febd4cd 100644
    --- a/lib/CodeGen/CGObjCMac.cpp
    +++ b/lib/CodeGen/CGObjCMac.cpp
    @@ -1004,6 +1004,8 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
                                           const ObjCInterfaceDecl *ID,
                                           ObjCCommonTypesHelper &ObjCTypes);
     
    +  std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
    +
     public:
       /// CreateMetadataVar - Create a global variable with internal
       /// linkage for use by the Objective-C runtime.
    @@ -4786,6 +4788,27 @@ llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
     
     /* *** Private Interface *** */
     
    +std::string CGObjCCommonMac::GetSectionName(StringRef Section,
    +                                            StringRef MachOAttributes) {
    +  switch (CGM.getTriple().getObjectFormat()) {
    +  default:
    +    llvm_unreachable("unexpected object file format");
    +  case llvm::Triple::MachO: {
    +    if (MachOAttributes.empty())
    +      return ("__DATA," + Section).str();
    +    return ("__DATA," + Section + "," + MachOAttributes).str();
    +  }
    +  case llvm::Triple::ELF:
    +    assert(Section.substr(0, 2) == "__" &&
    +           "expected the name to begin with __");
    +    return Section.substr(2).str();
    +  case llvm::Triple::COFF:
    +    assert(Section.substr(0, 2) == "__" &&
    +           "expected the name to begin with __");
    +    return ("." + Section.substr(2) + "$B").str();
    +  }
    +}
    +
     /// EmitImageInfo - Emit the image info marker used to encode some module
     /// level information.
     ///
    @@ -4809,9 +4832,10 @@ enum ImageInfoFlags {
     
     void CGObjCCommonMac::EmitImageInfo() {
       unsigned version = 0; // Version is unused?
    -  const char *Section = (ObjCABI == 1) ?
    -    "__OBJC, __image_info,regular" :
    -    "__DATA, __objc_imageinfo, regular, no_dead_strip";
    +  std::string Section =
    +      (ObjCABI == 1)
    +          ? "__OBJC,__image_info,regular"
    +          : GetSectionName("__objc_imageinfo", "regular,no_dead_strip");
     
       // Generate module-level named metadata to convey this information to the
       // linker and code-gen.
    @@ -4822,7 +4846,7 @@ void CGObjCCommonMac::EmitImageInfo() {
       Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
                         version);
       Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
    -                    llvm::MDString::get(VMContext,Section));
    +                    llvm::MDString::get(VMContext, Section));
     
       if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
         // Non-GC overrides those files which specify GC.
    @@ -5930,17 +5954,21 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
       }
     
       AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
    -                     "__DATA, __objc_classlist, regular, no_dead_strip");
    +                     GetSectionName("__objc_classlist",
    +                                    "regular,no_dead_strip"));
     
       AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
    -                     "__DATA, __objc_nlclslist, regular, no_dead_strip");
    +                     GetSectionName("__objc_nlclslist",
    +                                    "regular,no_dead_strip"));
     
       // Build list of all implemented category addresses in array
       // L_OBJC_LABEL_CATEGORY_$.
       AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
    -                     "__DATA, __objc_catlist, regular, no_dead_strip");
    +                     GetSectionName("__objc_catlist",
    +                                    "regular,no_dead_strip"));
       AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
    -                     "__DATA, __objc_nlcatlist, regular, no_dead_strip");
    +                     GetSectionName("__objc_nlcatlist",
    +                                    "regular,no_dead_strip"));
     
       EmitImageInfo();
     }
    @@ -6359,7 +6387,8 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
         llvm::GlobalValue::WeakAnyLinkage,
         Init,
         ProtocolName);
    -  PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
    +  PTGV->setSection(GetSectionName("__objc_protorefs",
    +                                  "coalesced,no_dead_strip"));
       PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
       PTGV->setAlignment(Align.getQuantity());
       CGM.addCompilerUsedGlobal(PTGV);
    @@ -6818,8 +6847,8 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
         PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
       PTGV->setAlignment(
         CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
    -  if (CGM.getTriple().isOSBinFormatMachO())
    -    PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
    +  PTGV->setSection(GetSectionName("__objc_protolist",
    +                                  "coalesced,no_dead_strip"));
       PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
       CGM.addCompilerUsedGlobal(PTGV);
       return Entry;
    @@ -7015,7 +7044,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
                                                   /*constant*/ false,
                                             llvm::GlobalValue::WeakAnyLinkage);
         messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
    -    messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
    +    messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced"));
       }
       
       bool requiresnullCheck = false;
    @@ -7126,7 +7155,8 @@ CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
                                          false, llvm::GlobalValue::PrivateLinkage,
                                          ClassGV, "OBJC_CLASSLIST_REFERENCES_$_");
         Entry->setAlignment(Align.getQuantity());
    -    Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
    +    Entry->setSection(GetSectionName("__objc_classrefs",
    +                                     "regular,no_dead_strip"));
         CGM.addCompilerUsedGlobal(Entry);
       }
       return CGF.Builder.CreateAlignedLoad(Entry, Align);
    @@ -7160,7 +7190,8 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
                                          false, llvm::GlobalValue::PrivateLinkage,
                                          ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
         Entry->setAlignment(Align.getQuantity());
    -    Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
    +    Entry->setSection(GetSectionName("__objc_superrefs",
    +                                     "regular,no_dead_strip"));
         CGM.addCompilerUsedGlobal(Entry);
       }
       return CGF.Builder.CreateAlignedLoad(Entry, Align);
    @@ -7182,7 +7213,8 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
                                          MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
         Entry->setAlignment(Align.getQuantity());
     
    -    Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
    +    Entry->setSection(GetSectionName("__objc_superrefs",
    +                                     "regular,no_dead_strip"));
         CGM.addCompilerUsedGlobal(Entry);
       }
     
    @@ -7278,7 +7310,8 @@ Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF,
                                          false, llvm::GlobalValue::PrivateLinkage,
                                          Casted, "OBJC_SELECTOR_REFERENCES_");
         Entry->setExternallyInitialized(true);
    -    Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
    +    Entry->setSection(GetSectionName("__objc_selrefs",
    +                                     "literal_pointers,no_dead_strip"));
         Entry->setAlignment(Align.getQuantity());
         CGM.addCompilerUsedGlobal(Entry);
       }
    diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
    index 63300e25d37e..468838e56e38 100644
    --- a/lib/CodeGen/CGOpenMPRuntime.cpp
    +++ b/lib/CodeGen/CGOpenMPRuntime.cpp
    @@ -747,9 +747,9 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
       QualType PtrTy = C.getPointerType(Ty).withRestrict();
       FunctionArgList Args;
       ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
    -                               /*Id=*/nullptr, PtrTy);
    +                               /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
       ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
    -                              /*Id=*/nullptr, PtrTy);
    +                              /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
       Args.push_back(&OmpOutParm);
       Args.push_back(&OmpInParm);
       auto &FnInfo =
    @@ -1808,8 +1808,8 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
           // threadprivate copy of the variable VD
           CodeGenFunction CtorCGF(CGM);
           FunctionArgList Args;
    -      ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
    -                            /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
    +      ImplicitParamDecl Dst(CGM.getContext(), CGM.getContext().VoidPtrTy,
    +                            ImplicitParamDecl::Other);
           Args.push_back(&Dst);
     
           auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
    @@ -1839,8 +1839,8 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
           // of the variable VD
           CodeGenFunction DtorCGF(CGM);
           FunctionArgList Args;
    -      ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
    -                            /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
    +      ImplicitParamDecl Dst(CGM.getContext(), CGM.getContext().VoidPtrTy,
    +                            ImplicitParamDecl::Other);
           Args.push_back(&Dst);
     
           auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
    @@ -2191,10 +2191,8 @@ static llvm::Value *emitCopyprivateCopyFunction(
       auto &C = CGM.getContext();
       // void copy_func(void *LHSArg, void *RHSArg);
       FunctionArgList Args;
    -  ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
    -                           C.VoidPtrTy);
    -  ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
    -                           C.VoidPtrTy);
    +  ImplicitParamDecl LHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
    +  ImplicitParamDecl RHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       Args.push_back(&LHSArg);
       Args.push_back(&RHSArg);
       auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
    @@ -2785,8 +2783,7 @@ createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
                                              const RegionCodeGenTy &Codegen) {
       auto &C = CGM.getContext();
       FunctionArgList Args;
    -  ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
    -                             /*Id=*/nullptr, C.VoidPtrTy);
    +  ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       Args.push_back(&DummyPtr);
     
       CodeGenFunction CGF(CGM);
    @@ -2889,7 +2886,7 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
       // descriptor, so we can reuse the logic that emits Ctors and Dtors.
       auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
       ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
    -                                IdentInfo, C.CharTy);
    +                                IdentInfo, C.CharTy, ImplicitParamDecl::Other);
     
       auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
           CGM, ".omp_offloading.descriptor_unreg",
    @@ -3319,10 +3316,11 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
                           llvm::Value *TaskPrivatesMap) {
       auto &C = CGM.getContext();
       FunctionArgList Args;
    -  ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
    -  ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
    -                                /*Id=*/nullptr,
    -                                KmpTaskTWithPrivatesPtrQTy.withRestrict());
    +  ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
    +                            ImplicitParamDecl::Other);
    +  ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
    +                                KmpTaskTWithPrivatesPtrQTy.withRestrict(),
    +                                ImplicitParamDecl::Other);
       Args.push_back(&GtidArg);
       Args.push_back(&TaskTypeArg);
       auto &TaskEntryFnInfo =
    @@ -3413,10 +3411,11 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
                                                 QualType KmpTaskTWithPrivatesQTy) {
       auto &C = CGM.getContext();
       FunctionArgList Args;
    -  ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
    -  ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
    -                                /*Id=*/nullptr,
    -                                KmpTaskTWithPrivatesPtrQTy.withRestrict());
    +  ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
    +                            ImplicitParamDecl::Other);
    +  ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
    +                                KmpTaskTWithPrivatesPtrQTy.withRestrict(),
    +                                ImplicitParamDecl::Other);
       Args.push_back(&GtidArg);
       Args.push_back(&TaskTypeArg);
       FunctionType::ExtInfo Info;
    @@ -3472,36 +3471,40 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
       FunctionArgList Args;
       ImplicitParamDecl TaskPrivatesArg(
           C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
    -      C.getPointerType(PrivatesQTy).withConst().withRestrict());
    +      C.getPointerType(PrivatesQTy).withConst().withRestrict(),
    +      ImplicitParamDecl::Other);
       Args.push_back(&TaskPrivatesArg);
       llvm::DenseMap PrivateVarsPos;
       unsigned Counter = 1;
       for (auto *E: PrivateVars) {
         Args.push_back(ImplicitParamDecl::Create(
    -        C, /*DC=*/nullptr, Loc,
    -        /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
    -                            .withConst()
    -                            .withRestrict()));
    +        C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
    +        C.getPointerType(C.getPointerType(E->getType()))
    +            .withConst()
    +            .withRestrict(),
    +        ImplicitParamDecl::Other));
         auto *VD = cast(cast(E)->getDecl());
         PrivateVarsPos[VD] = Counter;
         ++Counter;
       }
       for (auto *E : FirstprivateVars) {
         Args.push_back(ImplicitParamDecl::Create(
    -        C, /*DC=*/nullptr, Loc,
    -        /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
    -                            .withConst()
    -                            .withRestrict()));
    +        C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
    +        C.getPointerType(C.getPointerType(E->getType()))
    +            .withConst()
    +            .withRestrict(),
    +        ImplicitParamDecl::Other));
         auto *VD = cast(cast(E)->getDecl());
         PrivateVarsPos[VD] = Counter;
         ++Counter;
       }
       for (auto *E: LastprivateVars) {
         Args.push_back(ImplicitParamDecl::Create(
    -        C, /*DC=*/nullptr, Loc,
    -        /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
    -                            .withConst()
    -                            .withRestrict()));
    +        C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
    +        C.getPointerType(C.getPointerType(E->getType()))
    +            .withConst()
    +            .withRestrict(),
    +        ImplicitParamDecl::Other));
         auto *VD = cast(cast(E)->getDecl());
         PrivateVarsPos[VD] = Counter;
         ++Counter;
    @@ -3661,12 +3664,14 @@ emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
                         ArrayRef Privates, bool WithLastIter) {
       auto &C = CGM.getContext();
       FunctionArgList Args;
    -  ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc,
    -                           /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
    -  ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc,
    -                           /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
    -  ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc,
    -                                /*Id=*/nullptr, C.IntTy);
    +  ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
    +                           KmpTaskTWithPrivatesPtrQTy,
    +                           ImplicitParamDecl::Other);
    +  ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
    +                           KmpTaskTWithPrivatesPtrQTy,
    +                           ImplicitParamDecl::Other);
    +  ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
    +                                ImplicitParamDecl::Other);
       Args.push_back(&DstArg);
       Args.push_back(&SrcArg);
       Args.push_back(&LastprivArg);
    @@ -4278,10 +4283,8 @@ llvm::Value *CGOpenMPRuntime::emitReductionFunction(
     
       // void reduction_func(void *LHSArg, void *RHSArg);
       FunctionArgList Args;
    -  ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
    -                           C.VoidPtrTy);
    -  ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
    -                           C.VoidPtrTy);
    +  ImplicitParamDecl LHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
    +  ImplicitParamDecl RHSArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       Args.push_back(&LHSArg);
       Args.push_back(&RHSArg);
       auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
    diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
    index bbedac962d55..3ced05d08a47 100644
    --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
    +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
    @@ -1252,24 +1252,19 @@ emitReduceScratchpadFunction(CodeGenModule &CGM,
       auto Int32Ty = C.getIntTypeForBitwidth(32, /* Signed */ true);
     
       // Destination of the copy.
    -  ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                  /*Id=*/nullptr, C.VoidPtrTy);
    +  ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       // Base address of the scratchpad array, with each element storing a
       // Reduce list per team.
    -  ImplicitParamDecl ScratchPadArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                  /*Id=*/nullptr, C.VoidPtrTy);
    +  ImplicitParamDecl ScratchPadArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       // A source index into the scratchpad array.
    -  ImplicitParamDecl IndexArg(C, /*DC=*/nullptr, SourceLocation(),
    -                             /*Id=*/nullptr, Int32Ty);
    +  ImplicitParamDecl IndexArg(C, Int32Ty, ImplicitParamDecl::Other);
       // Row width of an element in the scratchpad array, typically
       // the number of teams.
    -  ImplicitParamDecl WidthArg(C, /*DC=*/nullptr, SourceLocation(),
    -                             /*Id=*/nullptr, Int32Ty);
    +  ImplicitParamDecl WidthArg(C, Int32Ty, ImplicitParamDecl::Other);
       // If should_reduce == 1, then it's load AND reduce,
       // If should_reduce == 0 (or otherwise), then it only loads (+ copy).
       // The latter case is used for initialization.
    -  ImplicitParamDecl ShouldReduceArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                    /*Id=*/nullptr, Int32Ty);
    +  ImplicitParamDecl ShouldReduceArg(C, Int32Ty, ImplicitParamDecl::Other);
     
       FunctionArgList Args;
       Args.push_back(&ReduceListArg);
    @@ -1381,20 +1376,16 @@ static llvm::Value *emitCopyToScratchpad(CodeGenModule &CGM,
       auto Int32Ty = C.getIntTypeForBitwidth(32, /* Signed */ true);
     
       // Source of the copy.
    -  ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                  /*Id=*/nullptr, C.VoidPtrTy);
    +  ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       // Base address of the scratchpad array, with each element storing a
       // Reduce list per team.
    -  ImplicitParamDecl ScratchPadArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                  /*Id=*/nullptr, C.VoidPtrTy);
    +  ImplicitParamDecl ScratchPadArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       // A destination index into the scratchpad array, typically the team
       // identifier.
    -  ImplicitParamDecl IndexArg(C, /*DC=*/nullptr, SourceLocation(),
    -                             /*Id=*/nullptr, Int32Ty);
    +  ImplicitParamDecl IndexArg(C, Int32Ty, ImplicitParamDecl::Other);
       // Row width of an element in the scratchpad array, typically
       // the number of teams.
    -  ImplicitParamDecl WidthArg(C, /*DC=*/nullptr, SourceLocation(),
    -                             /*Id=*/nullptr, Int32Ty);
    +  ImplicitParamDecl WidthArg(C, Int32Ty, ImplicitParamDecl::Other);
     
       FunctionArgList Args;
       Args.push_back(&ReduceListArg);
    @@ -1475,13 +1466,12 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM,
       // ReduceList: thread local Reduce list.
       // At the stage of the computation when this function is called, partially
       // aggregated values reside in the first lane of every active warp.
    -  ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                  /*Id=*/nullptr, C.VoidPtrTy);
    +  ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       // NumWarps: number of warps active in the parallel region.  This could
       // be smaller than 32 (max warps in a CTA) for partial block reduction.
    -  ImplicitParamDecl NumWarpsArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                /*Id=*/nullptr,
    -                                C.getIntTypeForBitwidth(32, /* Signed */ true));
    +  ImplicitParamDecl NumWarpsArg(C,
    +                                C.getIntTypeForBitwidth(32, /* Signed */ true),
    +                                ImplicitParamDecl::Other);
       FunctionArgList Args;
       Args.push_back(&ReduceListArg);
       Args.push_back(&NumWarpsArg);
    @@ -1723,17 +1713,14 @@ emitShuffleAndReduceFunction(CodeGenModule &CGM,
       auto &C = CGM.getContext();
     
       // Thread local Reduce list used to host the values of data to be reduced.
    -  ImplicitParamDecl ReduceListArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                  /*Id=*/nullptr, C.VoidPtrTy);
    +  ImplicitParamDecl ReduceListArg(C, C.VoidPtrTy, ImplicitParamDecl::Other);
       // Current lane id; could be logical.
    -  ImplicitParamDecl LaneIDArg(C, /*DC=*/nullptr, SourceLocation(),
    -                              /*Id=*/nullptr, C.ShortTy);
    +  ImplicitParamDecl LaneIDArg(C, C.ShortTy, ImplicitParamDecl::Other);
       // Offset of the remote source lane relative to the current lane.
    -  ImplicitParamDecl RemoteLaneOffsetArg(C, /*DC=*/nullptr, SourceLocation(),
    -                                        /*Id=*/nullptr, C.ShortTy);
    +  ImplicitParamDecl RemoteLaneOffsetArg(C, C.ShortTy,
    +                                        ImplicitParamDecl::Other);
       // Algorithm version.  This is expected to be known at compile time.
    -  ImplicitParamDecl AlgoVerArg(C, /*DC=*/nullptr, SourceLocation(),
    -                               /*Id=*/nullptr, C.ShortTy);
    +  ImplicitParamDecl AlgoVerArg(C, C.ShortTy, ImplicitParamDecl::Other);
       FunctionArgList Args;
       Args.push_back(&ReduceListArg);
       Args.push_back(&LaneIDArg);
    diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
    index c8c71dd83e97..77f3c332a12f 100644
    --- a/lib/CodeGen/CGStmtOpenMP.cpp
    +++ b/lib/CodeGen/CGStmtOpenMP.cpp
    @@ -281,8 +281,9 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
           ArgType =
               getCanonicalParamType(getContext(), ArgType.getNonReferenceType());
         }
    -    Args.push_back(ImplicitParamDecl::Create(getContext(), nullptr,
    -                                             FD->getLocation(), II, ArgType));
    +    Args.push_back(ImplicitParamDecl::Create(getContext(), /*DC=*/nullptr,
    +                                             FD->getLocation(), II, ArgType,
    +                                             ImplicitParamDecl::Other));
         ++I;
       }
       Args.append(
    diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
    index b6d7f0255017..ac1a1334f103 100644
    --- a/lib/CodeGen/CodeGenFunction.cpp
    +++ b/lib/CodeGen/CodeGenFunction.cpp
    @@ -1083,10 +1083,9 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD,
           if (!Param->hasAttr())
             continue;
     
    -      IdentifierInfo *NoID = nullptr;
           auto *Implicit = ImplicitParamDecl::Create(
    -          getContext(), Param->getDeclContext(), Param->getLocation(), NoID,
    -          getContext().getSizeType());
    +          getContext(), Param->getDeclContext(), Param->getLocation(),
    +          /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamDecl::Other);
           SizeArguments[Param] = Implicit;
           Args.push_back(Implicit);
         }
    diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
    index dde8f2e36920..77adf7b441a2 100644
    --- a/lib/CodeGen/CodeGenModule.cpp
    +++ b/lib/CodeGen/CodeGenModule.cpp
    @@ -1026,9 +1026,25 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D,
                                               llvm::GlobalObject *GO) {
       SetCommonAttributes(D, GO);
     
    -  if (D)
    +  if (D) {
    +    if (auto *GV = dyn_cast(GO)) {
    +      if (auto *SA = D->getAttr())
    +        GV->addAttribute("bss-section", SA->getName());
    +      if (auto *SA = D->getAttr())
    +        GV->addAttribute("data-section", SA->getName());
    +      if (auto *SA = D->getAttr())
    +        GV->addAttribute("rodata-section", SA->getName());
    +    }
    +
    +    if (auto *F = dyn_cast(GO)) {
    +      if (auto *SA = D->getAttr())
    +       if (!D->getAttr())
    +         F->addFnAttr("implicit-section-name", SA->getName());
    +    }
    +
         if (const SectionAttr *SA = D->getAttr())
           GO->setSection(SA->getName());
    +  }
     
       getTargetCodeGenInfo().setTargetAttributes(D, GO, *this);
     }
    @@ -1127,6 +1143,10 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
     
       setLinkageAndVisibilityForGV(F, FD);
     
    +  if (FD->getAttr()) {
    +    F->addFnAttr("implicit-section-name");
    +  }
    +
       if (const SectionAttr *SA = FD->getAttr())
         F->setSection(SA->getName());
     
    @@ -2828,6 +2848,14 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
       if (D->hasAttr())
         return true;
     
    +  // A variable cannot be both common and exist in a section.
    +  // We dont try to determine which is the right section in the front-end.
    +  // If no specialized section name is applicable, it will resort to default.
    +  if (D->hasAttr() ||
    +      D->hasAttr() ||
    +      D->hasAttr())
    +    return true;
    +
       // Thread local vars aren't considered common linkage.
       if (D->getTLSKind())
         return true;
    diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
    index 62b0e6155f99..39efb9f43921 100644
    --- a/lib/CodeGen/ItaniumCXXABI.cpp
    +++ b/lib/CodeGen/ItaniumCXXABI.cpp
    @@ -1408,9 +1408,9 @@ void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
     
         // FIXME: avoid the fake decl
         QualType T = Context.getPointerType(Context.VoidPtrTy);
    -    ImplicitParamDecl *VTTDecl
    -      = ImplicitParamDecl::Create(Context, nullptr, MD->getLocation(),
    -                                  &Context.Idents.get("vtt"), T);
    +    auto *VTTDecl = ImplicitParamDecl::Create(
    +        Context, /*DC=*/nullptr, MD->getLocation(), &Context.Idents.get("vtt"),
    +        T, ImplicitParamDecl::CXXVTT);
         Params.insert(Params.begin() + 1, VTTDecl);
         getStructorImplicitParamDecl(CGF) = VTTDecl;
       }
    diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
    index ff5aca88131e..e68a16e0bd51 100644
    --- a/lib/CodeGen/MicrosoftCXXABI.cpp
    +++ b/lib/CodeGen/MicrosoftCXXABI.cpp
    @@ -1413,11 +1413,10 @@ void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
       const CXXMethodDecl *MD = cast(CGF.CurGD.getDecl());
       assert(isa(MD) || isa(MD));
       if (isa(MD) && MD->getParent()->getNumVBases()) {
    -    ImplicitParamDecl *IsMostDerived
    -      = ImplicitParamDecl::Create(Context, nullptr,
    -                                  CGF.CurGD.getDecl()->getLocation(),
    -                                  &Context.Idents.get("is_most_derived"),
    -                                  Context.IntTy);
    +    auto *IsMostDerived = ImplicitParamDecl::Create(
    +        Context, /*DC=*/nullptr, CGF.CurGD.getDecl()->getLocation(),
    +        &Context.Idents.get("is_most_derived"), Context.IntTy,
    +        ImplicitParamDecl::Other);
         // The 'most_derived' parameter goes second if the ctor is variadic and last
         // if it's not.  Dtors can't be variadic.
         const FunctionProtoType *FPT = MD->getType()->castAs();
    @@ -1427,11 +1426,10 @@ void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
           Params.push_back(IsMostDerived);
         getStructorImplicitParamDecl(CGF) = IsMostDerived;
       } else if (isDeletingDtor(CGF.CurGD)) {
    -    ImplicitParamDecl *ShouldDelete
    -      = ImplicitParamDecl::Create(Context, nullptr,
    -                                  CGF.CurGD.getDecl()->getLocation(),
    -                                  &Context.Idents.get("should_call_delete"),
    -                                  Context.IntTy);
    +    auto *ShouldDelete = ImplicitParamDecl::Create(
    +        Context, /*DC=*/nullptr, CGF.CurGD.getDecl()->getLocation(),
    +        &Context.Idents.get("should_call_delete"), Context.IntTy,
    +        ImplicitParamDecl::Other);
         Params.push_back(ShouldDelete);
         getStructorImplicitParamDecl(CGF) = ShouldDelete;
       }
    @@ -3875,18 +3873,21 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
       // Following the 'this' pointer is a reference to the source object that we
       // are copying from.
       ImplicitParamDecl SrcParam(
    -      getContext(), nullptr, SourceLocation(), &getContext().Idents.get("src"),
    +      getContext(), /*DC=*/nullptr, SourceLocation(),
    +      &getContext().Idents.get("src"),
           getContext().getLValueReferenceType(RecordTy,
    -                                          /*SpelledAsLValue=*/true));
    +                                          /*SpelledAsLValue=*/true),
    +      ImplicitParamDecl::Other);
       if (IsCopy)
         FunctionArgs.push_back(&SrcParam);
     
       // Constructors for classes which utilize virtual bases have an additional
       // parameter which indicates whether or not it is being delegated to by a more
       // derived constructor.
    -  ImplicitParamDecl IsMostDerived(getContext(), nullptr, SourceLocation(),
    +  ImplicitParamDecl IsMostDerived(getContext(), /*DC=*/nullptr,
    +                                  SourceLocation(),
                                       &getContext().Idents.get("is_most_derived"),
    -                                  getContext().IntTy);
    +                                  getContext().IntTy, ImplicitParamDecl::Other);
       // Only add the parameter to the list if thie class has virtual bases.
       if (RD->getNumVBases() > 0)
         FunctionArgs.push_back(&IsMostDerived);
    diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
    index 247626d8200e..b639927a95b6 100644
    --- a/lib/Driver/CMakeLists.txt
    +++ b/lib/Driver/CMakeLists.txt
    @@ -1,4 +1,5 @@
     set(LLVM_LINK_COMPONENTS
    +  BinaryFormat
       Option
       Support
       )
    diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
    index d07ac96a3108..eb504fd4e541 100644
    --- a/lib/Driver/Driver.cpp
    +++ b/lib/Driver/Driver.cpp
    @@ -68,6 +68,7 @@
     #include "llvm/Support/PrettyStackTrace.h"
     #include "llvm/Support/Process.h"
     #include "llvm/Support/Program.h"
    +#include "llvm/Support/TargetRegistry.h"
     #include "llvm/Support/raw_ostream.h"
     #include 
     #include 
    @@ -1161,6 +1162,10 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
       if (C.getArgs().hasArg(options::OPT__version)) {
         // Follow gcc behavior and use stdout for --version and stderr for -v.
         PrintVersion(C, llvm::outs());
    +
    +    // Print registered targets.
    +    llvm::outs() << '\n';
    +    llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs());
         return false;
       }
     
    @@ -2667,6 +2672,8 @@ Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args,
           OutputTy = Input->getType();
           if (!Args.hasFlag(options::OPT_frewrite_includes,
                             options::OPT_fno_rewrite_includes, false) &&
    +          !Args.hasFlag(options::OPT_frewrite_imports,
    +                        options::OPT_fno_rewrite_imports, false) &&
               !CCGenDiagnostics)
             OutputTy = types::getPreprocessedType(OutputTy);
           assert(OutputTy != types::TY_INVALID &&
    diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
    index ad2b4ada9a83..d6a9c35eda78 100644
    --- a/lib/Driver/SanitizerArgs.cpp
    +++ b/lib/Driver/SanitizerArgs.cpp
    @@ -31,8 +31,8 @@ enum : SanitizerMask {
       NotAllowedWithTrap = Vptr,
       RequiresPIE = DataFlow,
       NeedsUnwindTables = Address | Thread | Memory | DataFlow,
    -  SupportsCoverage =
    -      Address | Memory | Leak | Undefined | Integer | Nullability | DataFlow,
    +  SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined |
    +                     Integer | Nullability | DataFlow,
       RecoverableByDefault = Undefined | Integer | Nullability,
       Unrecoverable = Unreachable | Return,
       LegacyFsanitizeRecoverMask = Undefined | Integer,
    diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp
    index f33542477fb5..33eff32b9731 100644
    --- a/lib/Driver/ToolChains/Arch/Mips.cpp
    +++ b/lib/Driver/ToolChains/Arch/Mips.cpp
    @@ -298,6 +298,13 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
     
       AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
                        options::OPT_modd_spreg, "nooddspreg");
    +
    +  if (Arg *A = Args.getLastArg(options::OPT_mmadd4, options::OPT_mno_madd4)) {
    +    if (A->getOption().matches(options::OPT_mmadd4))
    +      Features.push_back("-nomadd4");
    +    else
    +      Features.push_back("+nomadd4");
    +  }
     }
     
     mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
    diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
    index 698c3aa326cb..6d3dbb5b5204 100644
    --- a/lib/Driver/ToolChains/Clang.cpp
    +++ b/lib/Driver/ToolChains/Clang.cpp
    @@ -4204,13 +4204,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       }
     #endif
     
    +  bool RewriteImports = Args.hasFlag(options::OPT_frewrite_imports,
    +                                     options::OPT_fno_rewrite_imports, false);
    +  if (RewriteImports)
    +    CmdArgs.push_back("-frewrite-imports");
    +
       // Enable rewrite includes if the user's asked for it or if we're generating
       // diagnostics.
       // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
       // nice to enable this when doing a crashdump for modules as well.
       if (Args.hasFlag(options::OPT_frewrite_includes,
                        options::OPT_fno_rewrite_includes, false) ||
    -      (C.isForDiagnostics() && !HaveAnyModules))
    +      (C.isForDiagnostics() && (RewriteImports || !HaveAnyModules)))
         CmdArgs.push_back("-frewrite-includes");
     
       // Only allow -traditional or -traditional-cpp outside in preprocessing modes.
    diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp
    index 9da366eb55fe..08a27fa7fed1 100644
    --- a/lib/Driver/ToolChains/Linux.cpp
    +++ b/lib/Driver/ToolChains/Linux.cpp
    @@ -822,8 +822,9 @@ SanitizerMask Linux::getSupportedSanitizers() const {
       const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 ||
                              getTriple().getArch() == llvm::Triple::aarch64_be;
       const bool IsArmArch = getTriple().getArch() == llvm::Triple::arm ||
    -                         llvm::Triple::thumb || llvm::Triple::armeb ||
    -                         llvm::Triple::thumbeb;
    +                         getTriple().getArch() == llvm::Triple::thumb ||
    +                         getTriple().getArch() == llvm::Triple::armeb ||
    +                         getTriple().getArch() == llvm::Triple::thumbeb;
       SanitizerMask Res = ToolChain::getSupportedSanitizers();
       Res |= SanitizerKind::Address;
       Res |= SanitizerKind::Fuzzer;
    diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp
    index 6f5f54165b3b..9e9d943610be 100644
    --- a/lib/Driver/ToolChains/MSVC.cpp
    +++ b/lib/Driver/ToolChains/MSVC.cpp
    @@ -529,9 +529,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       SkipSettingEnvironment:;
     #endif
       } else {
    -    linkPath = Linker;
    -    llvm::sys::path::replace_extension(linkPath, "exe");
    -    linkPath = TC.GetProgramPath(linkPath.c_str());
    +    linkPath = TC.GetProgramPath(Linker.str().c_str());
       }
     
       auto LinkCmd = llvm::make_unique(
    diff --git a/lib/Edit/EditedSource.cpp b/lib/Edit/EditedSource.cpp
    index 1a7a68cffb62..03d45cf185c9 100644
    --- a/lib/Edit/EditedSource.cpp
    +++ b/lib/Edit/EditedSource.cpp
    @@ -25,17 +25,16 @@ void EditsReceiver::remove(CharSourceRange range) {
     
     void EditedSource::deconstructMacroArgLoc(SourceLocation Loc,
                                               SourceLocation &ExpansionLoc,
    -                                          IdentifierInfo *&II) {
    +                                          MacroArgUse &ArgUse) {
       assert(SourceMgr.isMacroArgExpansion(Loc));
       SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first;
       ExpansionLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
       SmallString<20> Buf;
       StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
                                              Buf, SourceMgr, LangOpts);
    -  II = nullptr;
    -  if (!ArgName.empty()) {
    -    II = &IdentTable.get(ArgName);
    -  }
    +  ArgUse = {nullptr, SourceLocation()};
    +  if (!ArgName.empty())
    +    ArgUse = {&IdentTable.get(ArgName), SourceMgr.getSpellingLoc(DefArgLoc)};
     }
     
     void EditedSource::startingCommit() {}
    @@ -43,12 +42,11 @@ void EditedSource::startingCommit() {}
     void EditedSource::finishedCommit() {
       for (auto &ExpArg : CurrCommitMacroArgExps) {
         SourceLocation ExpLoc;
    -    IdentifierInfo *II;
    -    std::tie(ExpLoc, II) = ExpArg;
    -    auto &ArgNames = ExpansionToArgMap[ExpLoc.getRawEncoding()];
    -    if (std::find(ArgNames.begin(), ArgNames.end(), II) == ArgNames.end()) {
    -      ArgNames.push_back(II);
    -    }
    +    MacroArgUse ArgUse;
    +    std::tie(ExpLoc, ArgUse) = ExpArg;
    +    auto &ArgUses = ExpansionToArgMap[ExpLoc.getRawEncoding()];
    +    if (std::find(ArgUses.begin(), ArgUses.end(), ArgUse) == ArgUses.end())
    +      ArgUses.push_back(ArgUse);
       }
       CurrCommitMacroArgExps.clear();
     }
    @@ -66,12 +64,15 @@ bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
       }
     
       if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
    -    IdentifierInfo *II;
         SourceLocation ExpLoc;
    -    deconstructMacroArgLoc(OrigLoc, ExpLoc, II);
    +    MacroArgUse ArgUse;
    +    deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
         auto I = ExpansionToArgMap.find(ExpLoc.getRawEncoding());
         if (I != ExpansionToArgMap.end() &&
    -        std::find(I->second.begin(), I->second.end(), II) != I->second.end()) {
    +        std::find_if(
    +            I->second.begin(), I->second.end(), [&](const MacroArgUse &U) {
    +              return ArgUse.first == U.first && ArgUse.second != U.second;
    +            }) != I->second.end()) {
           // Trying to write in a macro argument input that has already been
           // written by a previous commit for another expansion of the same macro
           // argument name. For example:
    @@ -101,11 +102,11 @@ bool EditedSource::commitInsert(SourceLocation OrigLoc,
         return true;
     
       if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
    -    IdentifierInfo *II;
         SourceLocation ExpLoc;
    -    deconstructMacroArgLoc(OrigLoc, ExpLoc, II);
    -    if (II)
    -      CurrCommitMacroArgExps.emplace_back(ExpLoc, II);
    +    MacroArgUse ArgUse;
    +    deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
    +    if (ArgUse.first)
    +      CurrCommitMacroArgExps.emplace_back(ExpLoc, ArgUse);
       }
       
       FileEdit &FA = FileEdits[Offs];
    diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
    index ae1af753bf46..387923031f85 100644
    --- a/lib/Format/ContinuationIndenter.cpp
    +++ b/lib/Format/ContinuationIndenter.cpp
    @@ -1036,8 +1036,8 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
                                             State.Stack.back().NestedBlockIndent);
       if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) {
         if (Current.opensBlockOrBlockTypeList(Style)) {
    -      NewIndent = State.Stack.back().NestedBlockIndent + Style.IndentWidth;
    -      NewIndent = std::min(State.Column + 2, NewIndent);
    +      NewIndent = Style.IndentWidth +
    +                  std::min(State.Column, State.Stack.back().NestedBlockIndent);
         } else {
           NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth;
         }
    diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
    index 2af931cdf1ba..7ce699cf14a1 100644
    --- a/lib/Format/TokenAnnotator.cpp
    +++ b/lib/Format/TokenAnnotator.cpp
    @@ -135,8 +135,11 @@ class AnnotatingParser {
         if (Left->is(TT_OverloadedOperatorLParen)) {
           Contexts.back().IsExpression = false;
         } else if (Style.Language == FormatStyle::LK_JavaScript &&
    -               Line.startsWith(Keywords.kw_type, tok::identifier)) {
    +               (Line.startsWith(Keywords.kw_type, tok::identifier) ||
    +                Line.startsWith(tok::kw_export, Keywords.kw_type,
    +                                tok::identifier))) {
           // type X = (...);
    +      // export type X = (...);
           Contexts.back().IsExpression = false;
         } else if (Left->Previous &&
             (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
    @@ -979,9 +982,12 @@ class AnnotatingParser {
       void modifyContext(const FormatToken &Current) {
         if (Current.getPrecedence() == prec::Assignment &&
             !Line.First->isOneOf(tok::kw_template, tok::kw_using, tok::kw_return) &&
    -        // Type aliases use `type X = ...;` in TypeScript.
    +        // Type aliases use `type X = ...;` in TypeScript and can be exported
    +        // using `export type ...`.
             !(Style.Language == FormatStyle::LK_JavaScript &&
    -          Line.startsWith(Keywords.kw_type, tok::identifier)) &&
    +          (Line.startsWith(Keywords.kw_type, tok::identifier) ||
    +           Line.startsWith(tok::kw_export, Keywords.kw_type,
    +                           tok::identifier))) &&
             (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
           Contexts.back().IsExpression = true;
           if (!Line.startsWith(TT_UnaryOperator)) {
    diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
    index 3b6311d15487..4b4fd13145fb 100644
    --- a/lib/Format/WhitespaceManager.cpp
    +++ b/lib/Format/WhitespaceManager.cpp
    @@ -100,18 +100,56 @@ void WhitespaceManager::calculateLineBreakInformation() {
       Changes[0].PreviousEndOfTokenColumn = 0;
       Change *LastOutsideTokenChange = &Changes[0];
       for (unsigned i = 1, e = Changes.size(); i != e; ++i) {
    -    unsigned OriginalWhitespaceStart =
    -        SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin());
    -    unsigned PreviousOriginalWhitespaceEnd = SourceMgr.getFileOffset(
    -        Changes[i - 1].OriginalWhitespaceRange.getEnd());
    -    Changes[i - 1].TokenLength = OriginalWhitespaceStart -
    -                                 PreviousOriginalWhitespaceEnd +
    -                                 Changes[i].PreviousLinePostfix.size() +
    -                                 Changes[i - 1].CurrentLinePrefix.size();
    +    SourceLocation OriginalWhitespaceStart =
    +        Changes[i].OriginalWhitespaceRange.getBegin();
    +    SourceLocation PreviousOriginalWhitespaceEnd =
    +        Changes[i - 1].OriginalWhitespaceRange.getEnd();
    +    unsigned OriginalWhitespaceStartOffset =
    +        SourceMgr.getFileOffset(OriginalWhitespaceStart);
    +    unsigned PreviousOriginalWhitespaceEndOffset =
    +        SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
    +    assert(PreviousOriginalWhitespaceEndOffset <=
    +           OriginalWhitespaceStartOffset);
    +    const char *const PreviousOriginalWhitespaceEndData =
    +        SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);
    +    StringRef Text(PreviousOriginalWhitespaceEndData,
    +                   SourceMgr.getCharacterData(OriginalWhitespaceStart) -
    +                       PreviousOriginalWhitespaceEndData);
    +    // Usually consecutive changes would occur in consecutive tokens. This is
    +    // not the case however when analyzing some preprocessor runs of the
    +    // annotated lines. For example, in this code:
    +    //
    +    // #if A // line 1
    +    // int i = 1;
    +    // #else B // line 2
    +    // int i = 2;
    +    // #endif // line 3
    +    //
    +    // one of the runs will produce the sequence of lines marked with line 1, 2
    +    // and 3. So the two consecutive whitespace changes just before '// line 2'
    +    // and before '#endif // line 3' span multiple lines and tokens:
    +    //
    +    // #else B{change X}[// line 2
    +    // int i = 2;
    +    // ]{change Y}#endif // line 3
    +    //
    +    // For this reason, if the text between consecutive changes spans multiple
    +    // newlines, the token length must be adjusted to the end of the original
    +    // line of the token.
    +    auto NewlinePos = Text.find_first_of('\n');
    +    if (NewlinePos == StringRef::npos) {
    +      Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset -
    +                                   PreviousOriginalWhitespaceEndOffset +
    +                                   Changes[i].PreviousLinePostfix.size() +
    +                                   Changes[i - 1].CurrentLinePrefix.size();
    +    } else {
    +      Changes[i - 1].TokenLength =
    +          NewlinePos + Changes[i - 1].CurrentLinePrefix.size();
    +    }
     
         // If there are multiple changes in this token, sum up all the changes until
         // the end of the line.
    -    if (Changes[i - 1].IsInsideToken)
    +    if (Changes[i - 1].IsInsideToken && Changes[i - 1].NewlinesBefore == 0)
           LastOutsideTokenChange->TokenLength +=
               Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
         else
    @@ -434,7 +472,9 @@ void WhitespaceManager::alignTrailingComments() {
           continue;
     
         unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
    -    unsigned ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
    +    unsigned ChangeMaxColumn = Style.ColumnLimit >= Changes[i].TokenLength
    +                                   ? Style.ColumnLimit - Changes[i].TokenLength
    +                                   : ChangeMinColumn;
     
         // If we don't create a replacement for this change, we have to consider
         // it to be immovable.
    diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
    index 51064da270cc..986f98ae598b 100644
    --- a/lib/Frontend/ASTMerge.cpp
    +++ b/lib/Frontend/ASTMerge.cpp
    @@ -21,14 +21,13 @@ ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
       return AdaptedAction->CreateASTConsumer(CI, InFile);
     }
     
    -bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI,
    -                                           StringRef Filename) {
    +bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI) {
       // FIXME: This is a hack. We need a better way to communicate the
       // AST file, compiler instance, and file name than member variables
       // of FrontendAction.
       AdaptedAction->setCurrentInput(getCurrentInput(), takeCurrentASTUnit());
       AdaptedAction->setCompilerInstance(&CI);
    -  return AdaptedAction->BeginSourceFileAction(CI, Filename);
    +  return AdaptedAction->BeginSourceFileAction(CI);
     }
     
     void ASTMergeAction::ExecuteAction() {
    diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
    index 01f7ca8aba9b..8d139f2c0a6d 100644
    --- a/lib/Frontend/ASTUnit.cpp
    +++ b/lib/Frontend/ASTUnit.cpp
    @@ -486,6 +486,8 @@ namespace {
     class ASTInfoCollector : public ASTReaderListener {
       Preprocessor &PP;
       ASTContext &Context;
    +  HeaderSearchOptions &HSOpts;
    +  PreprocessorOptions &PPOpts;
       LangOptions &LangOpt;
       std::shared_ptr &TargetOpts;
       IntrusiveRefCntPtr &Target;
    @@ -493,11 +495,14 @@ class ASTInfoCollector : public ASTReaderListener {
     
       bool InitializedLanguage;
     public:
    -  ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
    +  ASTInfoCollector(Preprocessor &PP, ASTContext &Context,
    +                   HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,
    +                   LangOptions &LangOpt,
                        std::shared_ptr &TargetOpts,
                        IntrusiveRefCntPtr &Target, unsigned &Counter)
    -      : PP(PP), Context(Context), LangOpt(LangOpt), TargetOpts(TargetOpts),
    -        Target(Target), Counter(Counter), InitializedLanguage(false) {}
    +      : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts),
    +        LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),
    +        Counter(Counter), InitializedLanguage(false) {}
     
       bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
                                bool AllowCompatibleDifferences) override {
    @@ -511,6 +516,20 @@ class ASTInfoCollector : public ASTReaderListener {
         return false;
       }
     
    +  virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
    +                                       StringRef SpecificModuleCachePath,
    +                                       bool Complain) override {
    +    this->HSOpts = HSOpts;
    +    return false;
    +  }
    +
    +  virtual bool
    +  ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
    +                          std::string &SuggestedPredefines) override {
    +    this->PPOpts = PPOpts;
    +    return false;
    +  }
    +
       bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
                              bool AllowCompatibleDifferences) override {
         // If we've already initialized the target, don't do it again.
    @@ -667,6 +686,7 @@ std::unique_ptr ASTUnit::LoadFromASTFile(
     
       ConfigureDiags(Diags, *AST, CaptureDiagnostics);
     
    +  AST->LangOpts = std::make_shared();
       AST->OnlyLocalDecls = OnlyLocalDecls;
       AST->CaptureDiagnostics = CaptureDiagnostics;
       AST->Diagnostics = Diags;
    @@ -682,13 +702,12 @@ std::unique_ptr ASTUnit::LoadFromASTFile(
       AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,
                                              AST->getSourceManager(),
                                              AST->getDiagnostics(),
    -                                         AST->ASTFileLangOpts,
    +                                         AST->getLangOpts(),
                                              /*Target=*/nullptr));
    -
    -  auto PPOpts = std::make_shared();
    +  AST->PPOpts = std::make_shared();
     
       for (const auto &RemappedFile : RemappedFiles)
    -    PPOpts->addRemappedFile(RemappedFile.first, RemappedFile.second);
    +    AST->PPOpts->addRemappedFile(RemappedFile.first, RemappedFile.second);
     
       // Gather Info for preprocessor construction later on.
     
    @@ -696,13 +715,13 @@ std::unique_ptr ASTUnit::LoadFromASTFile(
       unsigned Counter;
     
       AST->PP = std::make_shared(
    -      std::move(PPOpts), AST->getDiagnostics(), AST->ASTFileLangOpts,
    -      AST->getSourceManager(), *AST->PCMCache, HeaderInfo, *AST,
    +      AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts,
    +      AST->getSourceManager(), *AST->PCMCache, HeaderInfo, AST->ModuleLoader,
           /*IILookup=*/nullptr,
           /*OwnsHeaderSearch=*/false);
       Preprocessor &PP = *AST->PP;
     
    -  AST->Ctx = new ASTContext(AST->ASTFileLangOpts, AST->getSourceManager(),
    +  AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),
                                 PP.getIdentifierTable(), PP.getSelectorTable(),
                                 PP.getBuiltinInfo());
       ASTContext &Context = *AST->Ctx;
    @@ -716,8 +735,8 @@ std::unique_ptr ASTUnit::LoadFromASTFile(
                                   AllowPCHWithCompilerErrors);
     
       AST->Reader->setListener(llvm::make_unique(
    -      *AST->PP, Context, AST->ASTFileLangOpts, AST->TargetOpts, AST->Target,
    -      Counter));
    +      *AST->PP, Context, *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,
    +      AST->TargetOpts, AST->Target, Counter));
     
       // Attach the AST reader to the AST context as an external AST
       // source, so that declarations will be deserialized from the
    @@ -1140,6 +1159,8 @@ bool ASTUnit::Parse(std::shared_ptr PCHContainerOps,
       if (SavedMainFileBuffer)
         TranslateStoredDiagnostics(getFileManager(), getSourceManager(),
                                    PreambleDiagnostics, StoredDiagnostics);
    +  else
    +    PreambleSrcLocCache.clear();
     
       if (!Act->Execute())
         goto error;
    @@ -1963,7 +1984,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
         unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
         bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
         bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
    -    bool UserFilesAreVolatile, bool ForSerialization,
    +    bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
         llvm::Optional ModuleFormat, std::unique_ptr *ErrAST,
         IntrusiveRefCntPtr VFS) {
       assert(Diags.get() && "no DiagnosticsEngine was provided");
    @@ -1992,6 +2013,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
       PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
       PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
       PPOpts.GeneratePreamble = PrecompilePreambleAfterNParses != 0;
    +  PPOpts.SingleFileParseMode = SingleFileParse;
       
       // Override the resources path.
       CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
    @@ -2582,11 +2604,9 @@ void ASTUnit::TranslateStoredDiagnostics(
       // remap all the locations to the new view. This includes the diag location,
       // any associated source ranges, and the source ranges of associated fix-its.
       // FIXME: There should be a cleaner way to do this.
    -
       SmallVector Result;
       Result.reserve(Diags.size());
    -  const FileEntry *PreviousFE = nullptr;
    -  FileID FID;
    +
       for (const StandaloneDiagnostic &SD : Diags) {
         // Rebuild the StoredDiagnostic.
         if (SD.Filename.empty())
    @@ -2594,11 +2614,16 @@ void ASTUnit::TranslateStoredDiagnostics(
         const FileEntry *FE = FileMgr.getFile(SD.Filename);
         if (!FE)
           continue;
    -    if (FE != PreviousFE) {
    -      FID = SrcMgr.translateFile(FE);
    -      PreviousFE = FE;
    +    SourceLocation FileLoc;
    +    auto ItFileID = PreambleSrcLocCache.find(SD.Filename);
    +    if (ItFileID == PreambleSrcLocCache.end()) {
    +      FileID FID = SrcMgr.translateFile(FE);
    +      FileLoc = SrcMgr.getLocForStartOfFile(FID);
    +      PreambleSrcLocCache[SD.Filename] = FileLoc;
    +    } else {
    +      FileLoc = ItFileID->getValue();
         }
    -    SourceLocation FileLoc = SrcMgr.getLocForStartOfFile(FID);
    +
         if (FileLoc.isInvalid())
           continue;
         SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);
    @@ -2879,7 +2904,32 @@ const FileEntry *ASTUnit::getPCHFile() {
     }
     
     bool ASTUnit::isModuleFile() {
    -  return isMainFileAST() && ASTFileLangOpts.isCompilingModule();
    +  return isMainFileAST() && getLangOpts().isCompilingModule();
    +}
    +
    +InputKind ASTUnit::getInputKind() const {
    +  auto &LangOpts = getLangOpts();
    +
    +  InputKind::Language Lang;
    +  if (LangOpts.OpenCL)
    +    Lang = InputKind::OpenCL;
    +  else if (LangOpts.CUDA)
    +    Lang = InputKind::CUDA;
    +  else if (LangOpts.RenderScript)
    +    Lang = InputKind::RenderScript;
    +  else if (LangOpts.CPlusPlus)
    +    Lang = LangOpts.ObjC1 ? InputKind::ObjCXX : InputKind::CXX;
    +  else
    +    Lang = LangOpts.ObjC1 ? InputKind::ObjC : InputKind::C;
    +
    +  InputKind::Format Fmt = InputKind::Source;
    +  if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap)
    +    Fmt = InputKind::ModuleMap;
    +
    +  // We don't know if input was preprocessed. Assume not.
    +  bool PP = false;
    +
    +  return InputKind(Lang, Fmt, PP);
     }
     
     void ASTUnit::PreambleData::countLines() const {
    diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
    index e92672a785da..72a8c3818093 100644
    --- a/lib/Frontend/CompilerInstance.cpp
    +++ b/lib/Frontend/CompilerInstance.cpp
    @@ -667,6 +667,11 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) {
           llvm::sys::fs::remove(OF.Filename);
       }
       OutputFiles.clear();
    +  if (DeleteBuiltModules) {
    +    for (auto &Module : BuiltModules)
    +      llvm::sys::fs::remove(Module.second);
    +    BuiltModules.clear();
    +  }
       NonSeekStream.reset();
     }
     
    @@ -1029,13 +1034,14 @@ static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) {
     /// \brief Compile a module file for the given module, using the options 
     /// provided by the importing compiler instance. Returns true if the module
     /// was built without errors.
    -static bool compileModuleImpl(CompilerInstance &ImportingInstance,
    -                              SourceLocation ImportLoc,
    -                              Module *Module,
    -                              StringRef ModuleFileName) {
    -  ModuleMap &ModMap 
    -    = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
    -    
    +static bool
    +compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
    +                  StringRef ModuleName, FrontendInputFile Input,
    +                  StringRef OriginalModuleMapFile, StringRef ModuleFileName,
    +                  llvm::function_ref PreBuildStep =
    +                      [](CompilerInstance &) {},
    +                  llvm::function_ref PostBuildStep =
    +                      [](CompilerInstance &) {}) {
       // Construct a compiler invocation for creating this module.
       auto Invocation =
           std::make_shared(ImportingInstance.getInvocation());
    @@ -1060,7 +1066,7 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
           PPOpts.Macros.end());
     
       // Note the name of the module we're building.
    -  Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName();
    +  Invocation->getLangOpts()->CurrentModule = ModuleName;
     
       // Make sure that the failed-module structure has been allocated in
       // the importing instance, and propagate the pointer to the newly-created
    @@ -1080,13 +1086,10 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
       FrontendOpts.DisableFree = false;
       FrontendOpts.GenerateGlobalModuleIndex = false;
       FrontendOpts.BuildingImplicitModule = true;
    -  FrontendOpts.OriginalModuleMap =
    -      ModMap.getModuleMapFileForUniquing(Module)->getName();
    +  FrontendOpts.OriginalModuleMap = OriginalModuleMapFile;
       // Force implicitly-built modules to hash the content of the module file.
       HSOpts.ModulesHashContent = true;
    -  FrontendOpts.Inputs.clear();
    -  InputKind IK(getLanguageFromOptions(*Invocation->getLangOpts()),
    -               InputKind::ModuleMap);
    +  FrontendOpts.Inputs = {Input};
     
       // Don't free the remapped file buffers; they are owned by our caller.
       PPOpts.RetainRemappedFileBuffers = true;
    @@ -1117,7 +1120,7 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
       SourceManager &SourceMgr = Instance.getSourceManager();
       SourceMgr.setModuleBuildStack(
         ImportingInstance.getSourceManager().getModuleBuildStack());
    -  SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(),
    +  SourceMgr.pushModuleBuildStack(ModuleName,
         FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager()));
     
       // If we're collecting module dependencies, we need to share a collector
    @@ -1126,32 +1129,11 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
       Instance.setModuleDepCollector(ImportingInstance.getModuleDepCollector());
       Inv.getDependencyOutputOpts() = DependencyOutputOptions();
     
    -  // Get or create the module map that we'll use to build this module.
    -  std::string InferredModuleMapContent;
    -  if (const FileEntry *ModuleMapFile =
    -          ModMap.getContainingModuleMapFile(Module)) {
    -    // Use the module map where this module resides.
    -    FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK,
    -                                     +Module->IsSystem);
    -  } else {
    -    SmallString<128> FakeModuleMapFile(Module->Directory->getName());
    -    llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map");
    -    FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK, +Module->IsSystem);
    -
    -    llvm::raw_string_ostream OS(InferredModuleMapContent);
    -    Module->print(OS);
    -    OS.flush();
    -
    -    std::unique_ptr ModuleMapBuffer =
    -        llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
    -    ModuleMapFile = Instance.getFileManager().getVirtualFile(
    -        FakeModuleMapFile, InferredModuleMapContent.size(), 0);
    -    SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer));
    -  }
    -
       ImportingInstance.getDiagnostics().Report(ImportLoc,
                                                 diag::remark_module_build)
    -    << Module->Name << ModuleFileName;
    +    << ModuleName << ModuleFileName;
    +
    +  PreBuildStep(Instance);
     
       // Execute the action to actually build the module in-place. Use a separate
       // thread so that we get a stack large enough.
    @@ -1164,9 +1146,11 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
           },
           ThreadStackSize);
     
    +  PostBuildStep(Instance);
    +
       ImportingInstance.getDiagnostics().Report(ImportLoc,
                                                 diag::remark_module_build_done)
    -    << Module->Name;
    +    << ModuleName;
     
       // Delete the temporary module map file.
       // FIXME: Even though we're executing under crash protection, it would still
    @@ -1174,13 +1158,66 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
       // doesn't make sense for all clients, so clean this up manually.
       Instance.clearOutputFiles(/*EraseFiles=*/true);
     
    +  return !Instance.getDiagnostics().hasErrorOccurred();
    +}
    +
    +/// \brief Compile a module file for the given module, using the options 
    +/// provided by the importing compiler instance. Returns true if the module
    +/// was built without errors.
    +static bool compileModuleImpl(CompilerInstance &ImportingInstance,
    +                              SourceLocation ImportLoc,
    +                              Module *Module,
    +                              StringRef ModuleFileName) {
    +  InputKind IK(getLanguageFromOptions(ImportingInstance.getLangOpts()),
    +               InputKind::ModuleMap);
    +
    +  // Get or create the module map that we'll use to build this module.
    +  ModuleMap &ModMap 
    +    = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
    +  bool Result;
    +  if (const FileEntry *ModuleMapFile =
    +          ModMap.getContainingModuleMapFile(Module)) {
    +    // Use the module map where this module resides.
    +    Result = compileModuleImpl(
    +        ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
    +        FrontendInputFile(ModuleMapFile->getName(), IK, +Module->IsSystem),
    +        ModMap.getModuleMapFileForUniquing(Module)->getName(),
    +        ModuleFileName);
    +  } else {
    +    // FIXME: We only need to fake up an input file here as a way of
    +    // transporting the module's directory to the module map parser. We should
    +    // be able to do that more directly, and parse from a memory buffer without
    +    // inventing this file.
    +    SmallString<128> FakeModuleMapFile(Module->Directory->getName());
    +    llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map");
    +
    +    std::string InferredModuleMapContent;
    +    llvm::raw_string_ostream OS(InferredModuleMapContent);
    +    Module->print(OS);
    +    OS.flush();
    +
    +    Result = compileModuleImpl(
    +        ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
    +        FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
    +        ModMap.getModuleMapFileForUniquing(Module)->getName(),
    +        ModuleFileName,
    +        [&](CompilerInstance &Instance) {
    +      std::unique_ptr ModuleMapBuffer =
    +          llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
    +      ModuleMapFile = Instance.getFileManager().getVirtualFile(
    +          FakeModuleMapFile, InferredModuleMapContent.size(), 0);
    +      Instance.getSourceManager().overrideFileContents(
    +          ModuleMapFile, std::move(ModuleMapBuffer));
    +    });
    +  }
    +
       // We've rebuilt a module. If we're allowed to generate or update the global
       // module index, record that fact in the importing compiler instance.
       if (ImportingInstance.getFrontendOpts().GenerateGlobalModuleIndex) {
         ImportingInstance.setBuildGlobalModuleIndex(true);
       }
     
    -  return !Instance.getDiagnostics().hasErrorOccurred();
    +  return Result;
     }
     
     static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
    @@ -1586,24 +1623,36 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
             PP->getHeaderSearchInfo().getHeaderSearchOpts();
     
         std::string ModuleFileName;
    -    bool LoadFromPrebuiltModulePath = false;
    -    // We try to load the module from the prebuilt module paths. If not
    -    // successful, we then try to find it in the module cache.
    -    if (!HSOpts.PrebuiltModulePaths.empty()) {
    -      // Load the module from the prebuilt module path.
    +    enum ModuleSource {
    +      ModuleNotFound, ModuleCache, PrebuiltModulePath, ModuleBuildPragma
    +    } Source = ModuleNotFound;
    +
    +    // Check to see if the module has been built as part of this compilation
    +    // via a module build pragma.
    +    auto BuiltModuleIt = BuiltModules.find(ModuleName);
    +    if (BuiltModuleIt != BuiltModules.end()) {
    +      ModuleFileName = BuiltModuleIt->second;
    +      Source = ModuleBuildPragma;
    +    }
    +
    +    // Try to load the module from the prebuilt module path.
    +    if (Source == ModuleNotFound && !HSOpts.PrebuiltModulePaths.empty()) {
           ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(
               ModuleName, "", /*UsePrebuiltPath*/ true);
           if (!ModuleFileName.empty())
    -        LoadFromPrebuiltModulePath = true;
    +        Source = PrebuiltModulePath;
         }
    -    if (!LoadFromPrebuiltModulePath && Module) {
    -      // Load the module from the module cache.
    +
    +    // Try to load the module from the module cache.
    +    if (Source == ModuleNotFound && Module) {
           ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
    -    } else if (!LoadFromPrebuiltModulePath) {
    +      Source = ModuleCache;
    +    }
    +
    +    if (Source == ModuleNotFound) {
           // We can't find a module, error out here.
           getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
    -      << ModuleName
    -      << SourceRange(ImportLoc, ModuleNameLoc);
    +          << ModuleName << SourceRange(ImportLoc, ModuleNameLoc);
           ModuleBuildFailed = true;
           return ModuleLoadResult();
         }
    @@ -1631,20 +1680,20 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
                      *FrontendTimerGroup);
         llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
     
    -    // Try to load the module file. If we are trying to load from the prebuilt
    -    // module path, we don't have the module map files and don't know how to
    -    // rebuild modules.
    -    unsigned ARRFlags = LoadFromPrebuiltModulePath ?
    -                        ASTReader::ARR_ConfigurationMismatch :
    -                        ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
    +    // Try to load the module file. If we are not trying to load from the
    +    // module cache, we don't know how to rebuild modules.
    +    unsigned ARRFlags = Source == ModuleCache ?
    +                        ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing :
    +                        ASTReader::ARR_ConfigurationMismatch;
         switch (ModuleManager->ReadAST(ModuleFileName,
    -                                   LoadFromPrebuiltModulePath ?
    -                                   serialization::MK_PrebuiltModule :
    -                                   serialization::MK_ImplicitModule,
    -                                   ImportLoc,
    -                                   ARRFlags)) {
    +                                   Source == PrebuiltModulePath
    +                                       ? serialization::MK_PrebuiltModule
    +                                       : Source == ModuleBuildPragma
    +                                             ? serialization::MK_ExplicitModule
    +                                             : serialization::MK_ImplicitModule,
    +                                   ImportLoc, ARRFlags)) {
         case ASTReader::Success: {
    -      if (LoadFromPrebuiltModulePath && !Module) {
    +      if (Source != ModuleCache && !Module) {
             Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
             if (!Module || !Module->getASTFile() ||
                 FileMgr->getFile(ModuleFileName) != Module->getASTFile()) {
    @@ -1662,10 +1711,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
     
         case ASTReader::OutOfDate:
         case ASTReader::Missing: {
    -      if (LoadFromPrebuiltModulePath) {
    -        // We can't rebuild the module without a module map. Since ReadAST
    -        // already produces diagnostics for these two cases, we simply
    -        // error out here.
    +      if (Source != ModuleCache) {
    +        // We don't know the desired configuration for this module and don't
    +        // necessarily even have a module map. Since ReadAST already produces
    +        // diagnostics for these two cases, we simply error out here.
             ModuleBuildFailed = true;
             KnownModules[Path[0].first] = nullptr;
             return ModuleLoadResult();
    @@ -1722,7 +1771,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
         }
     
         case ASTReader::ConfigurationMismatch:
    -      if (LoadFromPrebuiltModulePath)
    +      if (Source == PrebuiltModulePath)
    +        // FIXME: We shouldn't be setting HadFatalFailure below if we only
    +        // produce a warning here!
             getDiagnostics().Report(SourceLocation(),
                                     diag::warn_module_config_mismatch)
                 << ModuleFileName;
    @@ -1751,7 +1802,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
       // If we never found the module, fail.
       if (!Module)
         return ModuleLoadResult();
    -  
    +
       // Verify that the rest of the module path actually corresponds to
       // a submodule.
       if (Path.size() > 1) {
    @@ -1824,20 +1875,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
         }
     
         // Check whether this module is available.
    -    clang::Module::Requirement Requirement;
    -    clang::Module::UnresolvedHeaderDirective MissingHeader;
    -    if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement,
    -                             MissingHeader)) {
    -      if (MissingHeader.FileNameLoc.isValid()) {
    -        getDiagnostics().Report(MissingHeader.FileNameLoc,
    -                                diag::err_module_header_missing)
    -          << MissingHeader.IsUmbrella << MissingHeader.FileName;
    -      } else {
    -        getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
    -          << Module->getFullModuleName()
    -          << Requirement.second << Requirement.first
    -          << SourceRange(Path.front().second, Path.back().second);
    -      }
    +    if (Preprocessor::checkModuleIsAvailable(getLangOpts(), getTarget(),
    +                                             getDiagnostics(), Module)) {
    +      getDiagnostics().Report(ImportLoc, diag::note_module_import_here)
    +        << SourceRange(Path.front().second, Path.back().second);
           LastModuleImportLoc = ImportLoc;
           LastModuleImportResult = ModuleLoadResult();
           return ModuleLoadResult();
    @@ -1858,6 +1899,53 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
       return LastModuleImportResult;
     }
     
    +void CompilerInstance::loadModuleFromSource(SourceLocation ImportLoc,
    +                                            StringRef ModuleName,
    +                                            StringRef Source) {
    +  // FIXME: Using a randomized filename here means that our intermediate .pcm
    +  // output is nondeterministic (as .pcm files refer to each other by name).
    +  // Can this affect the output in any way?
    +  SmallString<128> ModuleFileName;
    +  if (std::error_code EC = llvm::sys::fs::createTemporaryFile(
    +          ModuleName, "pcm", ModuleFileName)) {
    +    getDiagnostics().Report(ImportLoc, diag::err_fe_unable_to_open_output)
    +        << ModuleFileName << EC.message();
    +    return;
    +  }
    +  std::string ModuleMapFileName = (ModuleName + ".map").str();
    +
    +  FrontendInputFile Input(
    +      ModuleMapFileName,
    +      InputKind(getLanguageFromOptions(*Invocation->getLangOpts()),
    +                InputKind::ModuleMap, /*Preprocessed*/true));
    +
    +  std::string NullTerminatedSource(Source.str());
    +
    +  auto PreBuildStep = [&](CompilerInstance &Other) {
    +    // Create a virtual file containing our desired source.
    +    // FIXME: We shouldn't need to do this.
    +    const FileEntry *ModuleMapFile = Other.getFileManager().getVirtualFile(
    +        ModuleMapFileName, NullTerminatedSource.size(), 0);
    +    Other.getSourceManager().overrideFileContents(
    +        ModuleMapFile,
    +        llvm::MemoryBuffer::getMemBuffer(NullTerminatedSource.c_str()));
    +
    +    Other.BuiltModules = std::move(BuiltModules);
    +    Other.DeleteBuiltModules = false;
    +  };
    +
    +  auto PostBuildStep = [this](CompilerInstance &Other) {
    +    BuiltModules = std::move(Other.BuiltModules);
    +  };
    +
    +  // Build the module, inheriting any modules that we've built locally.
    +  if (compileModuleImpl(*this, ImportLoc, ModuleName, Input, StringRef(),
    +                        ModuleFileName, PreBuildStep, PostBuildStep)) {
    +    BuiltModules[ModuleName] = ModuleFileName.str();
    +    llvm::sys::RemoveFileOnSignal(ModuleFileName);
    +  }
    +}
    +
     void CompilerInstance::makeModuleVisible(Module *Mod,
                                              Module::NameVisibilityKind Visibility,
                                              SourceLocation ImportLoc) {
    diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
    index adb15f1730bf..bb635b7ad714 100644
    --- a/lib/Frontend/CompilerInvocation.cpp
    +++ b/lib/Frontend/CompilerInvocation.cpp
    @@ -739,7 +739,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
       Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
       Opts.CallFEntry = Args.hasArg(OPT_mfentry);
       Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
    -  Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
    +  // TODO: map this from -gz in the driver and give it a named value
    +  if (Args.hasArg(OPT_compress_debug_sections))
    +    Opts.setCompressDebugSections(llvm::DebugCompressionType::GNU);
       Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
       Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
       for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) {
    @@ -2499,6 +2501,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
       Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
       Opts.ShowIncludeDirectives = Args.hasArg(OPT_dI);
       Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes);
    +  Opts.RewriteImports = Args.hasArg(OPT_frewrite_imports);
       Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives);
     }
     
    diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
    index e2fbe965349f..7c0b854648bd 100644
    --- a/lib/Frontend/FrontendAction.cpp
    +++ b/lib/Frontend/FrontendAction.cpp
    @@ -387,8 +387,7 @@ static std::error_code collectModuleHeaderIncludes(
       return std::error_code();
     }
     
    -static bool loadModuleMapForModuleBuild(CompilerInstance &CI,
    -                                        StringRef Filename, bool IsSystem,
    +static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem,
                                             bool IsPreprocessed,
                                             std::string &PresumedModuleMapFile,
                                             unsigned &Offset) {
    @@ -444,21 +443,9 @@ static Module *prepareToBuildModule(CompilerInstance &CI,
       }
     
       // Check whether we can build this module at all.
    -  clang::Module::Requirement Requirement;
    -  clang::Module::UnresolvedHeaderDirective MissingHeader;
    -  if (!M->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement,
    -                      MissingHeader)) {
    -    if (MissingHeader.FileNameLoc.isValid()) {
    -      CI.getDiagnostics().Report(MissingHeader.FileNameLoc,
    -                                 diag::err_module_header_missing)
    -        << MissingHeader.IsUmbrella << MissingHeader.FileName;
    -    } else {
    -      CI.getDiagnostics().Report(diag::err_module_unavailable)
    -        << M->getFullModuleName() << Requirement.second << Requirement.first;
    -    }
    -
    +  if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(),
    +                                           CI.getDiagnostics(), M))
         return nullptr;
    -  }
     
       // Inform the preprocessor that includes from within the input buffer should
       // be resolved relative to the build directory of the module map file.
    @@ -523,7 +510,8 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) {
     }
     
     bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
    -                                     const FrontendInputFile &Input) {
    +                                     const FrontendInputFile &RealInput) {
    +  FrontendInputFile Input(RealInput);
       assert(!Instance && "Already processing a source file!");
       assert(!Input.isEmpty() && "Unexpected empty filename!");
       setCurrentInput(Input);
    @@ -531,15 +519,72 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
     
       StringRef InputFile = Input.getFile();
       bool HasBegunSourceFile = false;
    +  bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled &&
    +                       usesPreprocessorOnly();
       if (!BeginInvocation(CI))
         goto failure;
     
    +  // If we're replaying the build of an AST file, import it and set up
    +  // the initial state from its build.
    +  if (ReplayASTFile) {
    +    IntrusiveRefCntPtr Diags(&CI.getDiagnostics());
    +
    +    // The AST unit populates its own diagnostics engine rather than ours.
    +    IntrusiveRefCntPtr ASTDiags(
    +        new DiagnosticsEngine(Diags->getDiagnosticIDs(),
    +                              &Diags->getDiagnosticOptions()));
    +    ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);
    +
    +    std::unique_ptr AST = ASTUnit::LoadFromASTFile(
    +        InputFile, CI.getPCHContainerReader(), ASTDiags, CI.getFileSystemOpts(),
    +        CI.getCodeGenOpts().DebugTypeExtRefs);
    +    if (!AST)
    +      goto failure;
    +
    +    // Options relating to how we treat the input (but not what we do with it)
    +    // are inherited from the AST unit.
    +    CI.getHeaderSearchOpts() = AST->getHeaderSearchOpts();
    +    CI.getPreprocessorOpts() = AST->getPreprocessorOpts();
    +    CI.getLangOpts() = AST->getLangOpts();
    +
    +    // Preload all the module files loaded transitively by the AST unit.
    +    if (auto ASTReader = AST->getASTReader()) {
    +      auto &MM = ASTReader->getModuleManager();
    +      for (ModuleFile &MF : MM)
    +        if (&MF != &MM.getPrimaryModule())
    +          CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName);
    +    }
    +    // FIXME: Preload module maps loaded by the AST unit.
    +
    +    // Set the shared objects, these are reset when we finish processing the
    +    // file, otherwise the CompilerInstance will happily destroy them.
    +    CI.setFileManager(&AST->getFileManager());
    +    CI.createSourceManager(CI.getFileManager());
    +    CI.getSourceManager().initializeForReplay(AST->getSourceManager());
    +    CI.createPreprocessor(getTranslationUnitKind());
    +
    +    // Set up the input file for replay purposes.
    +    auto Kind = AST->getInputKind();
    +    if (Kind.getFormat() == InputKind::ModuleMap) {
    +      Module *ASTModule =
    +          AST->getPreprocessor().getHeaderSearchInfo().lookupModule(
    +              AST->getLangOpts().CurrentModule, /*AllowSearch*/ false);
    +      Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind);
    +    } else {
    +      auto &SM = CI.getSourceManager();
    +      FileID ID = SM.getMainFileID();
    +      if (auto *File = SM.getFileEntryForID(ID))
    +        Input = FrontendInputFile(File->getName(), Kind);
    +      else
    +        Input = FrontendInputFile(SM.getBuffer(ID), Kind);
    +    }
    +    setCurrentInput(Input, std::move(AST));
    +  }
    +
       // AST files follow a very different path, since they share objects via the
       // AST unit.
       if (Input.getKind().getFormat() == InputKind::Precompiled) {
    -    // FIXME: We should not be asserting on bad command-line arguments.
    -    assert(!usesPreprocessorOnly() &&
    -           "Attempt to pass AST file to preprocessor only action!");
    +    assert(!usesPreprocessorOnly() && "this case was handled above");
         assert(hasASTFileSupport() &&
                "This action does not have AST file support!");
     
    @@ -569,7 +614,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
         setCurrentInput(Input, std::move(AST));
     
         // Initialize the action.
    -    if (!BeginSourceFileAction(CI, InputFile))
    +    if (!BeginSourceFileAction(CI))
           goto failure;
     
         // Create the AST consumer.
    @@ -616,7 +661,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
         HasBegunSourceFile = true;
     
         // Initialize the action.
    -    if (!BeginSourceFileAction(CI, InputFile))
    +    if (!BeginSourceFileAction(CI))
           goto failure;
     
         // Initialize the main file entry.
    @@ -680,7 +725,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
     
         std::string PresumedModuleMapFile;
         unsigned OffsetToContents;
    -    if (loadModuleMapForModuleBuild(CI, Input.getFile(), Input.isSystem(),
    +    if (loadModuleMapForModuleBuild(CI, Input.isSystem(),
                                         Input.isPreprocessed(),
                                         PresumedModuleMapFile, OffsetToContents))
           goto failure;
    @@ -709,7 +754,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
       }
     
       // Initialize the action.
    -  if (!BeginSourceFileAction(CI, InputFile))
    +  if (!BeginSourceFileAction(CI))
         goto failure;
     
       // Create the AST context and consumer unless this is a preprocessor only
    @@ -829,14 +874,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
     
       // If we failed, reset state since the client will not end up calling the
       // matching EndSourceFile().
    -  failure:
    -  if (isCurrentFileAST()) {
    -    CI.setASTContext(nullptr);
    -    CI.setPreprocessor(nullptr);
    -    CI.setSourceManager(nullptr);
    -    CI.setFileManager(nullptr);
    -  }
    -
    +failure:
       if (HasBegunSourceFile)
         CI.getDiagnosticClient().EndSourceFile();
       CI.clearOutputFiles(/*EraseFiles=*/true);
    @@ -914,6 +952,7 @@ void FrontendAction::EndSourceFile() {
           CI.resetAndLeakPreprocessor();
           CI.resetAndLeakSourceManager();
           CI.resetAndLeakFileManager();
    +      BuryPointer(CurrentASTUnit.release());
         } else {
           CI.setPreprocessor(nullptr);
           CI.setSourceManager(nullptr);
    @@ -973,11 +1012,10 @@ WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,
     bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) {
       return WrappedAction->BeginInvocation(CI);
     }
    -bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI,
    -                                                  StringRef Filename) {
    +bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI) {
       WrappedAction->setCurrentInput(getCurrentInput());
       WrappedAction->setCompilerInstance(&CI);
    -  auto Ret = WrappedAction->BeginSourceFileAction(CI, Filename);
    +  auto Ret = WrappedAction->BeginSourceFileAction(CI);
       // BeginSourceFileAction may change CurrentInput, e.g. during module builds.
       setCurrentInput(WrappedAction->getCurrentInput());
       return Ret;
    diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
    index 89ac385ca45d..c5567a09636b 100644
    --- a/lib/Frontend/FrontendActions.cpp
    +++ b/lib/Frontend/FrontendActions.cpp
    @@ -134,8 +134,7 @@ bool GeneratePCHAction::shouldEraseOutputFiles() {
       return ASTFrontendAction::shouldEraseOutputFiles();
     }
     
    -bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI,
    -                                              StringRef Filename) {
    +bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {
       CI.getLangOpts().CompilingPCH = true;
       return true;
     }
    @@ -164,11 +163,6 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
       return llvm::make_unique(std::move(Consumers));
     }
     
    -bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(
    -    CompilerInstance &CI, StringRef Filename) {
    -  return GenerateModuleAction::BeginSourceFileAction(CI, Filename);
    -}
    -
     std::unique_ptr
     GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
                                                         StringRef InFile) {
    @@ -194,8 +188,8 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
                                  /*CreateMissingDirectories=*/true);
     }
     
    -bool GenerateModuleInterfaceAction::BeginSourceFileAction(CompilerInstance &CI,
    -                                                          StringRef Filename) {
    +bool GenerateModuleInterfaceAction::BeginSourceFileAction(
    +    CompilerInstance &CI) {
       if (!CI.getLangOpts().ModulesTS) {
         CI.getDiagnostics().Report(diag::err_module_interface_requires_modules_ts);
         return false;
    @@ -203,7 +197,7 @@ bool GenerateModuleInterfaceAction::BeginSourceFileAction(CompilerInstance &CI,
     
       CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
     
    -  return GenerateModuleAction::BeginSourceFileAction(CI, Filename);
    +  return GenerateModuleAction::BeginSourceFileAction(CI);
     }
     
     std::unique_ptr
    diff --git a/lib/Frontend/Rewrite/CMakeLists.txt b/lib/Frontend/Rewrite/CMakeLists.txt
    index 924bf5d5ee28..61a22b5b13b4 100644
    --- a/lib/Frontend/Rewrite/CMakeLists.txt
    +++ b/lib/Frontend/Rewrite/CMakeLists.txt
    @@ -19,4 +19,5 @@ add_clang_library(clangRewriteFrontend
       clangFrontend
       clangLex
       clangRewrite
    +  clangSerialization
       )
    diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp
    index b2dfd2941130..45feffbcb5b5 100644
    --- a/lib/Frontend/Rewrite/FrontendActions.cpp
    +++ b/lib/Frontend/Rewrite/FrontendActions.cpp
    @@ -18,6 +18,11 @@
     #include "clang/Rewrite/Frontend/ASTConsumers.h"
     #include "clang/Rewrite/Frontend/FixItRewriter.h"
     #include "clang/Rewrite/Frontend/Rewriters.h"
    +#include "clang/Serialization/ASTReader.h"
    +#include "clang/Serialization/Module.h"
    +#include "clang/Serialization/ModuleManager.h"
    +#include "llvm/ADT/DenseSet.h"
    +#include "llvm/Support/CrashRecoveryContext.h"
     #include "llvm/Support/FileSystem.h"
     #include "llvm/Support/Path.h"
     #include "llvm/Support/raw_ostream.h"
    @@ -86,8 +91,7 @@ class FixItRewriteToTemp : public FixItOptions {
     };
     } // end anonymous namespace
     
    -bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
    -                                        StringRef Filename) {
    +bool FixItAction::BeginSourceFileAction(CompilerInstance &CI) {
       const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
       if (!FEOpts.FixItSuffix.empty()) {
         FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix,
    @@ -190,27 +194,112 @@ void RewriteTestAction::ExecuteAction() {
       DoRewriteTest(CI.getPreprocessor(), OS.get());
     }
     
    -void RewriteIncludesAction::ExecuteAction() {
    -  CompilerInstance &CI = getCompilerInstance();
    -  std::unique_ptr OS =
    -      CI.createDefaultOutputFile(true, getCurrentFile());
    -  if (!OS) return;
    +class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener {
    +  CompilerInstance &CI;
    +  std::weak_ptr Out;
    +
    +  llvm::DenseSet Rewritten;
    +
    +public:
    +  RewriteImportsListener(CompilerInstance &CI, std::shared_ptr Out)
    +      : CI(CI), Out(Out) {}
    +
    +  void visitModuleFile(StringRef Filename,
    +                       serialization::ModuleKind Kind) override {
    +    auto *File = CI.getFileManager().getFile(Filename);
    +    assert(File && "missing file for loaded module?");
    +
    +    // Only rewrite each module file once.
    +    if (!Rewritten.insert(File).second)
    +      return;
    +
    +    serialization::ModuleFile *MF =
    +        CI.getModuleManager()->getModuleManager().lookup(File);
    +    assert(File && "missing module file for loaded module?");
    +
    +    // Not interested in PCH / preambles.
    +    if (!MF->isModule())
    +      return;
    +
    +    auto OS = Out.lock();
    +    assert(OS && "loaded module file after finishing rewrite action?");
    +
    +    (*OS) << "#pragma clang module build " << MF->ModuleName << "\n";
    +
    +    // Rewrite the contents of the module in a separate compiler instance.
    +    CompilerInstance Instance(CI.getPCHContainerOperations(),
    +                              &CI.getPreprocessor().getPCMCache());
    +    Instance.setInvocation(
    +        std::make_shared(CI.getInvocation()));
    +    Instance.createDiagnostics(
    +        new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
    +        /*ShouldOwnClient=*/true);
    +    Instance.getFrontendOpts().Inputs.clear();
    +    Instance.getFrontendOpts().Inputs.emplace_back(
    +        Filename, InputKind(InputKind::Unknown, InputKind::Precompiled));
    +    // Don't recursively rewrite imports. We handle them all at the top level.
    +    Instance.getPreprocessorOutputOpts().RewriteImports = false;
    +
    +    llvm::CrashRecoveryContext().RunSafelyOnThread([&]() {
    +      RewriteIncludesAction Action;
    +      Action.OutputStream = OS;
    +      Instance.ExecuteAction(Action);
    +    });
    +
    +    (*OS) << "#pragma clang module endbuild /*" << MF->ModuleName << "*/\n";
    +  }
    +};
    +
    +bool RewriteIncludesAction::BeginSourceFileAction(CompilerInstance &CI) {
    +  if (!OutputStream) {
    +    OutputStream = CI.createDefaultOutputFile(true, getCurrentFile());
    +    if (!OutputStream)
    +      return false;
    +  }
    +
    +  auto &OS = *OutputStream;
     
       // If we're preprocessing a module map, start by dumping the contents of the
       // module itself before switching to the input buffer.
       auto &Input = getCurrentInput();
       if (Input.getKind().getFormat() == InputKind::ModuleMap) {
         if (Input.isFile()) {
    -      (*OS) << "# 1 \"";
    -      OS->write_escaped(Input.getFile());
    -      (*OS) << "\"\n";
    +      OS << "# 1 \"";
    +      OS.write_escaped(Input.getFile());
    +      OS << "\"\n";
         }
    -    // FIXME: Include additional information here so that we don't need the
    -    // original source files to exist on disk.
    -    getCurrentModule()->print(*OS);
    -    (*OS) << "#pragma clang module contents\n";
    +    getCurrentModule()->print(OS);
    +    OS << "#pragma clang module contents\n";
       }
     
    -  RewriteIncludesInInput(CI.getPreprocessor(), OS.get(),
    -                         CI.getPreprocessorOutputOpts());
    +  // If we're rewriting imports, set up a listener to track when we import
    +  // module files.
    +  if (CI.getPreprocessorOutputOpts().RewriteImports) {
    +    CI.createModuleManager();
    +    CI.getModuleManager()->addListener(
    +        llvm::make_unique(CI, OutputStream));
    +  }
    +
    +  return true;
    +}
    +
    +void RewriteIncludesAction::ExecuteAction() {
    +  CompilerInstance &CI = getCompilerInstance();
    +
    +  // If we're rewriting imports, emit the module build output first rather
    +  // than switching back and forth (potentially in the middle of a line).
    +  if (CI.getPreprocessorOutputOpts().RewriteImports) {
    +    std::string Buffer;
    +    llvm::raw_string_ostream OS(Buffer);
    +
    +    RewriteIncludesInInput(CI.getPreprocessor(), &OS,
    +                           CI.getPreprocessorOutputOpts());
    +
    +    (*OutputStream) << OS.str();
    +  } else {
    +    RewriteIncludesInInput(CI.getPreprocessor(), OutputStream.get(),
    +                           CI.getPreprocessorOutputOpts());
    +  }
    +
    +  OutputStream.reset();
     }
    diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
    index 1f7493c9e398..a7c140188b35 100644
    --- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp
    +++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
    @@ -85,7 +85,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
       case PrintDeclContext:       return llvm::make_unique();
       case PrintPreamble:          return llvm::make_unique();
       case PrintPreprocessedInput: {
    -    if (CI.getPreprocessorOutputOpts().RewriteIncludes)
    +    if (CI.getPreprocessorOutputOpts().RewriteIncludes ||
    +        CI.getPreprocessorOutputOpts().RewriteImports)
           return llvm::make_unique();
         return llvm::make_unique();
       }
    diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h
    index 15d28259dcc0..78bb70740bbf 100644
    --- a/lib/Headers/avxintrin.h
    +++ b/lib/Headers/avxintrin.h
    @@ -3603,7 +3603,7 @@ _mm256_stream_si256(__m256i *__a, __m256i __b)
     ///
     /// \param __a
     ///    A pointer to a 32-byte aligned memory location that will receive the
    -///    integer values.
    +///    double-precision floating-point values.
     /// \param __b
     ///    A 256-bit vector of [4 x double] containing the values to be moved.
     static __inline void __DEFAULT_FN_ATTRS
    diff --git a/lib/Headers/bmiintrin.h b/lib/Headers/bmiintrin.h
    index e590cf8bc1ae..361e5f720ea1 100644
    --- a/lib/Headers/bmiintrin.h
    +++ b/lib/Headers/bmiintrin.h
    @@ -148,7 +148,7 @@ __blsi_u32(unsigned int __X)
     }
     
     /// \brief Creates a mask whose bits are set to 1, using bit 0 up to and
    -///    including the least siginificant bit that is set to 1 in the source
    +///    including the least significant bit that is set to 1 in the source
     ///    operand and returns the result.
     ///
     /// \headerfile 
    @@ -164,7 +164,7 @@ __blsmsk_u32(unsigned int __X)
       return __X ^ (__X - 1);
     }
     
    -/// \brief Clears the least siginificant bit that is set to 1 in the source
    +/// \brief Clears the least significant bit that is set to 1 in the source
     ///    operand and returns the result.
     ///
     /// \headerfile 
    @@ -309,7 +309,7 @@ __blsi_u64(unsigned long long __X)
     }
     
     /// \brief Creates a mask whose bits are set to 1, using bit 0 up to and
    -///    including the least siginificant bit that is set to 1 in the source
    +///    including the least significant bit that is set to 1 in the source
     ///    operand and returns the result.
     ///
     /// \headerfile 
    @@ -325,7 +325,7 @@ __blsmsk_u64(unsigned long long __X)
       return __X ^ (__X - 1);
     }
     
    -/// \brief Clears the least siginificant bit that is set to 1 in the source
    +/// \brief Clears the least significant bit that is set to 1 in the source
     ///    operand and returns the result.
     ///
     /// \headerfile 
    diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h
    index fa5cefadc52c..709815cbb4c2 100644
    --- a/lib/Headers/emmintrin.h
    +++ b/lib/Headers/emmintrin.h
    @@ -302,7 +302,7 @@ _mm_min_pd(__m128d __a, __m128d __b)
       return __builtin_ia32_minpd((__v2df)__a, (__v2df)__b);
     }
     
    -/// \brief Compares lower 64-bits double-precision values of both operands, and
    +/// \brief Compares lower 64-bit double-precision values of both operands, and
     ///    returns the greater of the pair of values in the lower 64-bits of the
     ///    result. The upper 64 bits of the result are copied from the upper double-
     ///    precision value of the first operand.
    @@ -1652,7 +1652,7 @@ _mm_loadu_pd(double const *__dp)
     ///
     /// This intrinsic corresponds to the  VMOVQ / MOVQ  instruction.
     ///
    -/// \param __dp
    +/// \param __a
     ///    A pointer to a 64-bit memory location. The address of the memory
     ///    location does not have to be aligned.
     /// \returns A 128-bit vector of [2 x i64] containing the loaded value.
    @@ -1674,7 +1674,7 @@ _mm_loadu_si64(void const *__a)
     /// This intrinsic corresponds to the  VMOVSD / MOVSD  instruction.
     ///
     /// \param __dp
    -///    An pointer to a memory location containing a double-precision value.
    +///    A pointer to a memory location containing a double-precision value.
     ///    The address of the memory location does not have to be aligned.
     /// \returns A 128-bit vector of [2 x double] containing the loaded value.
     static __inline__ __m128d __DEFAULT_FN_ATTRS
    @@ -1911,12 +1911,38 @@ _mm_store_sd(double *__dp, __m128d __a)
       ((struct __mm_store_sd_struct*)__dp)->__u = __a[0];
     }
     
    +/// \brief Moves packed double-precision values from a 128-bit vector of
    +///    [2 x double] to a memory location.
    +///
    +/// \headerfile 
    +///
    +/// This intrinsic corresponds to the VMOVAPD / MOVAPS instruction.
    +///
    +/// \param __dp
    +///    A pointer to an aligned memory location that can store two
    +///    double-precision values.
    +/// \param __a
    +///    A packed 128-bit vector of [2 x double] containing the values to be
    +///    moved.
     static __inline__ void __DEFAULT_FN_ATTRS
     _mm_store_pd(double *__dp, __m128d __a)
     {
       *(__m128d*)__dp = __a;
     }
     
    +/// \brief Moves the lower 64 bits of a 128-bit vector of [2 x double] twice to
    +///    the upper and lower 64 bits of a memory location.
    +///
    +/// \headerfile 
    +///
    +/// This intrinsic corresponds to the VMOVDDUP + VMOVAPD / MOVLHPS + MOVAPS  instruction.
    +///
    +/// \param __dp
    +///    A pointer to a memory location that can store two double-precision
    +///    values.
    +/// \param __a
    +///    A 128-bit vector of [2 x double] whose lower 64 bits are copied to each
    +///    of the values in \a dp.
     static __inline__ void __DEFAULT_FN_ATTRS
     _mm_store1_pd(double *__dp, __m128d __a)
     {
    diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h
    index 5a1c572ce614..bbc2117b4ea1 100644
    --- a/lib/Headers/xmmintrin.h
    +++ b/lib/Headers/xmmintrin.h
    @@ -2099,7 +2099,7 @@ _mm_stream_pi(__m64 *__p, __m64 __a)
     ///
     /// \param __p
     ///    A pointer to a 128-bit aligned memory location that will receive the
    -///    integer values.
    +///    single-precision floating-point values.
     /// \param __a
     ///    A 128-bit vector of [4 x float] containing the values to be moved.
     static __inline__ void __DEFAULT_FN_ATTRS
    diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
    index 2d3ad690987e..89c2ebd00a68 100644
    --- a/lib/Lex/PPDirectives.cpp
    +++ b/lib/Lex/PPDirectives.cpp
    @@ -30,6 +30,7 @@
     #include "clang/Lex/PPCallbacks.h"
     #include "clang/Lex/Pragma.h"
     #include "clang/Lex/Preprocessor.h"
    +#include "clang/Lex/PreprocessorOptions.h"
     #include "clang/Lex/PTHLexer.h"
     #include "clang/Lex/Token.h"
     #include "llvm/ADT/ArrayRef.h"
    @@ -1654,6 +1655,26 @@ static bool trySimplifyPath(SmallVectorImpl &Components,
       return SuggestReplacement;
     }
     
    +bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts,
    +                                          const TargetInfo &TargetInfo,
    +                                          DiagnosticsEngine &Diags, Module *M) {
    +  Module::Requirement Requirement;
    +  Module::UnresolvedHeaderDirective MissingHeader;
    +  if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader))
    +    return false;
    +
    +  if (MissingHeader.FileNameLoc.isValid()) {
    +    Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)
    +        << MissingHeader.IsUmbrella << MissingHeader.FileName;
    +  } else {
    +    // FIXME: Track the location at which the requirement was specified, and
    +    // use it here.
    +    Diags.Report(M->DefinitionLoc, diag::err_module_unavailable)
    +        << M->getFullModuleName() << Requirement.second << Requirement.first;
    +  }
    +  return true;
    +}
    +
     /// HandleIncludeDirective - The "\#include" tokens have just been read, read
     /// the file to be included from the lexer, then include it!  This is a common
     /// routine with functionality shared between \#include, \#include_next and
    @@ -1825,33 +1846,24 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
       // we've imported or already built.
       bool ShouldEnter = true;
     
    +  if (PPOpts->SingleFileParseMode)
    +    ShouldEnter = false;
    +
       // Determine whether we should try to import the module for this #include, if
       // there is one. Don't do so if precompiled module support is disabled or we
       // are processing this module textually (because we're building the module).
    -  if (File && SuggestedModule && getLangOpts().Modules &&
    +  if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules &&
           SuggestedModule.getModule()->getTopLevelModuleName() !=
               getLangOpts().CurrentModule) {
         // If this include corresponds to a module but that module is
         // unavailable, diagnose the situation and bail out.
         // FIXME: Remove this; loadModule does the same check (but produces
         // slightly worse diagnostics).
    -    if (!SuggestedModule.getModule()->isAvailable()) {
    -      Module::Requirement Requirement;
    -      Module::UnresolvedHeaderDirective MissingHeader;
    -      Module *M = SuggestedModule.getModule();
    -      // Identify the cause.
    -      (void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement,
    -                           MissingHeader);
    -      if (MissingHeader.FileNameLoc.isValid()) {
    -        Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing)
    -            << MissingHeader.IsUmbrella << MissingHeader.FileName;
    -      } else {
    -        Diag(M->DefinitionLoc, diag::err_module_unavailable)
    -            << M->getFullModuleName() << Requirement.second << Requirement.first;
    -      }
    +    if (checkModuleIsAvailable(getLangOpts(), getTargetInfo(), getDiagnostics(),
    +                               SuggestedModule.getModule())) {
           Diag(FilenameTok.getLocation(),
                diag::note_implicit_top_level_module_import_here)
    -          << M->getTopLevelModuleName();
    +          << SuggestedModule.getModule()->getTopLevelModuleName();
           return;
         }
     
    diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
    index e1d981527bec..c16478dd2be4 100644
    --- a/lib/Lex/Pragma.cpp
    +++ b/lib/Lex/Pragma.cpp
    @@ -754,6 +754,88 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
       getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName);
     }
     
    +void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
    +  SourceLocation Loc = Tok.getLocation();
    +
    +  LexUnexpandedToken(Tok);
    +  if (Tok.isAnnotation() || !Tok.getIdentifierInfo()) {
    +    Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << true;
    +    return;
    +  }
    +  IdentifierInfo *ModuleName = Tok.getIdentifierInfo();
    +
    +  LexUnexpandedToken(Tok);
    +  if (Tok.isNot(tok::eod)) {
    +    Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
    +    DiscardUntilEndOfDirective();
    +  }
    +
    +  if (CurPTHLexer) {
    +    // FIXME: Support this somehow?
    +    Diag(Loc, diag::err_pp_module_build_pth);
    +    return;
    +  }
    +
    +  CurLexer->LexingRawMode = true;
    +
    +  auto TryConsumeIdentifier = [&](StringRef Ident) -> bool {
    +    if (Tok.getKind() != tok::raw_identifier ||
    +        Tok.getRawIdentifier() != Ident)
    +      return false;
    +    CurLexer->Lex(Tok);
    +    return true;
    +  };
    +
    +  // Scan forward looking for the end of the module.
    +  const char *Start = CurLexer->getBufferLocation();
    +  const char *End = nullptr;
    +  unsigned NestingLevel = 1;
    +  while (true) {
    +    End = CurLexer->getBufferLocation();
    +    CurLexer->Lex(Tok);
    +
    +    if (Tok.is(tok::eof)) {
    +      Diag(Loc, diag::err_pp_module_build_missing_end);
    +      break;
    +    }
    +
    +    if (Tok.isNot(tok::hash) || !Tok.isAtStartOfLine()) {
    +      // Token was part of module; keep going.
    +      continue;
    +    }
    +
    +    // We hit something directive-shaped; check to see if this is the end
    +    // of the module build.
    +    CurLexer->ParsingPreprocessorDirective = true;
    +    CurLexer->Lex(Tok);
    +    if (TryConsumeIdentifier("pragma") && TryConsumeIdentifier("clang") &&
    +        TryConsumeIdentifier("module")) {
    +      if (TryConsumeIdentifier("build"))
    +        // #pragma clang module build -> entering a nested module build.
    +        ++NestingLevel;
    +      else if (TryConsumeIdentifier("endbuild")) {
    +        // #pragma clang module endbuild -> leaving a module build.
    +        if (--NestingLevel == 0)
    +          break;
    +      }
    +      // We should either be looking at the EOD or more of the current directive
    +      // preceding the EOD. Either way we can ignore this token and keep going.
    +      assert(Tok.getKind() != tok::eof && "missing EOD before EOF");
    +    }
    +  }
    +
    +  CurLexer->LexingRawMode = false;
    +
    +  // Load the extracted text as a preprocessed module.
    +  assert(CurLexer->getBuffer().begin() <= Start &&
    +         Start <= CurLexer->getBuffer().end() &&
    +         CurLexer->getBuffer().begin() <= End &&
    +         End <= CurLexer->getBuffer().end() &&
    +         "module source range not contained within same file buffer");
    +  TheModuleLoader.loadModuleFromSource(Loc, ModuleName->getName(),
    +                                       StringRef(Start, End - Start));
    +}
    +
     /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
     /// If 'Namespace' is non-null, then it is a token required to exist on the
     /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
    @@ -1408,18 +1490,8 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
         }
     
         // If the module isn't available, it doesn't make sense to enter it.
    -    if (!M->isAvailable()) {
    -      Module::Requirement Requirement;
    -      Module::UnresolvedHeaderDirective MissingHeader;
    -      (void)M->isAvailable(PP.getLangOpts(), PP.getTargetInfo(),
    -                           Requirement, MissingHeader);
    -      if (MissingHeader.FileNameLoc.isValid()) {
    -        PP.Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing)
    -          << MissingHeader.IsUmbrella << MissingHeader.FileName;
    -      } else {
    -        PP.Diag(M->DefinitionLoc, diag::err_module_unavailable)
    -          << M->getFullModuleName() << Requirement.second << Requirement.first;
    -      }
    +    if (Preprocessor::checkModuleIsAvailable(
    +            PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics(), M)) {
           PP.Diag(BeginLoc, diag::note_pp_module_begin_here)
             << M->getTopLevelModuleName();
           return;
    @@ -1452,6 +1524,39 @@ struct PragmaModuleEndHandler : public PragmaHandler {
       }
     };
     
    +/// Handle the clang \#pragma module build extension.
    +struct PragmaModuleBuildHandler : public PragmaHandler {
    +  PragmaModuleBuildHandler() : PragmaHandler("build") {}
    +
    +  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
    +                    Token &Tok) override {
    +    PP.HandlePragmaModuleBuild(Tok);
    +  }
    +};
    +
    +/// Handle the clang \#pragma module load extension.
    +struct PragmaModuleLoadHandler : public PragmaHandler {
    +  PragmaModuleLoadHandler() : PragmaHandler("load") {}
    +
    +  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
    +                    Token &Tok) override {
    +    SourceLocation Loc = Tok.getLocation();
    +
    +    // Read the module name.
    +    llvm::SmallVector, 8>
    +        ModuleName;
    +    if (LexModuleName(PP, Tok, ModuleName))
    +      return;
    +
    +    if (Tok.isNot(tok::eod))
    +      PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
    +
    +    // Load the module, don't make it visible.
    +    PP.getModuleLoader().loadModule(Loc, ModuleName, Module::Hidden,
    +                                    /*IsIncludeDirective=*/false);
    +  }
    +};
    +
     /// PragmaPushMacroHandler - "\#pragma push_macro" saves the value of the
     /// macro on the top of the stack.
     struct PragmaPushMacroHandler : public PragmaHandler {
    @@ -1681,6 +1786,8 @@ void Preprocessor::RegisterBuiltinPragmas() {
       ModuleHandler->AddPragma(new PragmaModuleImportHandler());
       ModuleHandler->AddPragma(new PragmaModuleBeginHandler());
       ModuleHandler->AddPragma(new PragmaModuleEndHandler());
    +  ModuleHandler->AddPragma(new PragmaModuleBuildHandler());
    +  ModuleHandler->AddPragma(new PragmaModuleLoadHandler());
     
       AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());
       AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler());
    diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
    index 3596337c245e..f9a399cd7fd7 100644
    --- a/lib/Lex/Preprocessor.cpp
    +++ b/lib/Lex/Preprocessor.cpp
    @@ -580,7 +580,11 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const {
     
       // Update the token info (identifier info and appropriate token kind).
       Identifier.setIdentifierInfo(II);
    -  Identifier.setKind(II->getTokenID());
    +  if (getLangOpts().MSVCCompat && II->isCPlusPlusOperatorKeyword() &&
    +      getSourceManager().isInSystemHeader(Identifier.getLocation()))
    +    Identifier.setKind(clang::tok::identifier);
    +  else
    +    Identifier.setKind(II->getTokenID());
     
       return II;
     }
    @@ -709,7 +713,9 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
       // C++ 2.11p2: If this is an alternative representation of a C++ operator,
       // then we act as if it is the actual operator and not the textual
       // representation of it.
    -  if (II.isCPlusPlusOperatorKeyword())
    +  if (II.isCPlusPlusOperatorKeyword() &&
    +      !(getLangOpts().MSVCCompat &&
    +        getSourceManager().isInSystemHeader(Identifier.getLocation())))
         Identifier.setIdentifierInfo(nullptr);
     
       // If this is an extension token, diagnose its use.
    diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
    index 4c117f531ef1..1a4607a84cff 100644
    --- a/lib/Parse/ParseDeclCXX.cpp
    +++ b/lib/Parse/ParseDeclCXX.cpp
    @@ -840,7 +840,9 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
         return nullptr;
       }
     
    -  ExprResult AssertExpr(ParseConstantExpression());
    +  EnterExpressionEvaluationContext ConstantEvaluated(
    +      Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
    +  ExprResult AssertExpr(ParseConstantExpressionInExprEvalContext());
       if (AssertExpr.isInvalid()) {
         SkipMalformedDecl();
         return nullptr;
    diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
    index 18aebe658073..262743756a6b 100644
    --- a/lib/Parse/ParsePragma.cpp
    +++ b/lib/Parse/ParsePragma.cpp
    @@ -49,6 +49,15 @@ struct PragmaPackHandler : public PragmaHandler {
                         Token &FirstToken) override;
     };
     
    +struct PragmaClangSectionHandler : public PragmaHandler {
    +  explicit PragmaClangSectionHandler(Sema &S)
    +             : PragmaHandler("section"), Actions(S) {}
    +  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
    +                    Token &FirstToken) override;
    +private:
    +  Sema &Actions;
    +};
    +
     struct PragmaMSStructHandler : public PragmaHandler {
       explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
       void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
    @@ -224,6 +233,9 @@ void Parser::initializePragmaHandlers() {
       FPContractHandler.reset(new PragmaFPContractHandler());
       PP.AddPragmaHandler("STDC", FPContractHandler.get());
     
    +  PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
    +  PP.AddPragmaHandler("clang", PCSectionHandler.get());
    +
       if (getLangOpts().OpenCL) {
         OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
         PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
    @@ -323,6 +335,9 @@ void Parser::resetPragmaHandlers() {
         MSCommentHandler.reset();
       }
     
    +  PP.RemovePragmaHandler("clang", PCSectionHandler.get());
    +  PCSectionHandler.reset();
    +
       if (getLangOpts().MicrosoftExt) {
         PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
         MSDetectMismatchHandler.reset();
    @@ -1614,6 +1629,51 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
       PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
     }
     
    +// #pragma clang section bss="abc" data="" rodata="def" text=""
    +void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
    +             PragmaIntroducerKind Introducer, Token &FirstToken) {
    +
    +  Token Tok;
    +  auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
    +
    +  PP.Lex(Tok); // eat 'section'
    +  while (Tok.isNot(tok::eod)) {
    +    if (Tok.isNot(tok::identifier)) {
    +      PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
    +      return;
    +    }
    +
    +    const IdentifierInfo *SecType = Tok.getIdentifierInfo();
    +    if (SecType->isStr("bss"))
    +      SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
    +    else if (SecType->isStr("data"))
    +      SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
    +    else if (SecType->isStr("rodata"))
    +      SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
    +    else if (SecType->isStr("text"))
    +      SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
    +    else {
    +      PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
    +      return;
    +    }
    +
    +    PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
    +    if (Tok.isNot(tok::equal)) {
    +      PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
    +      return;
    +    }
    +
    +    std::string SecName;
    +    if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
    +      return;
    +
    +    Actions.ActOnPragmaClangSection(Tok.getLocation(),
    +      (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
    +                       Sema::PragmaClangSectionAction::PCSA_Clear),
    +       SecKind, SecName);
    +  }
    +}
    +
     // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
     // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
     static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
    diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
    index 76ca65373dda..8c13ead64457 100644
    --- a/lib/Sema/SemaAttr.cpp
    +++ b/lib/Sema/SemaAttr.cpp
    @@ -126,6 +126,36 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
       PackStack.Act(PragmaLoc, Action, StringRef(), Alignment);
     }
     
    +void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action,
    +                                   PragmaClangSectionKind SecKind, StringRef SecName) {
    +  PragmaClangSection *CSec;
    +  switch (SecKind) {
    +    case PragmaClangSectionKind::PCSK_BSS:
    +      CSec = &PragmaClangBSSSection;
    +      break;
    +    case PragmaClangSectionKind::PCSK_Data:
    +      CSec = &PragmaClangDataSection;
    +      break;
    +    case PragmaClangSectionKind::PCSK_Rodata:
    +      CSec = &PragmaClangRodataSection;
    +      break;
    +    case PragmaClangSectionKind::PCSK_Text:
    +      CSec = &PragmaClangTextSection;
    +      break;
    +    default:
    +      llvm_unreachable("invalid clang section kind");
    +  }
    +
    +  if (Action == PragmaClangSectionAction::PCSA_Clear) {
    +    CSec->Valid = false;
    +    return;
    +  }
    +
    +  CSec->Valid = true;
    +  CSec->SectionName = SecName;
    +  CSec->PragmaLocation = PragmaLoc;
    +}
    +
     void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
                                StringRef SlotLabel, Expr *alignment) {
       Expr *Alignment = static_cast(alignment);
    diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
    index 224d9e9a0ee2..b9349dc06bff 100644
    --- a/lib/Sema/SemaCodeComplete.cpp
    +++ b/lib/Sema/SemaCodeComplete.cpp
    @@ -1860,6 +1860,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
     
         AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
       }
    +  LLVM_FALLTHROUGH;
     
       // Fall through (for statement expressions).
       case Sema::PCC_ForInit:
    diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
    index ef6dfaa2f28c..cba220daf774 100644
    --- a/lib/Sema/SemaDecl.cpp
    +++ b/lib/Sema/SemaDecl.cpp
    @@ -8651,6 +8651,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
         NewFD->setInvalidDecl();
       }
     
    +  // Apply an implicit SectionAttr if '#pragma clang section text' is active
    +  if (PragmaClangTextSection.Valid && D.isFunctionDefinition() &&
    +      !NewFD->hasAttr()) {
    +    NewFD->addAttr(PragmaClangTextSectionAttr::CreateImplicit(Context,
    +                                                 PragmaClangTextSection.SectionName,
    +                                                 PragmaClangTextSection.PragmaLocation));
    +  }
    +
       // Apply an implicit SectionAttr if #pragma code_seg is active.
       if (CodeSegStack.CurrentValue && D.isFunctionDefinition() &&
           !NewFD->hasAttr()) {
    @@ -11175,6 +11183,23 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
       if (!VD)
         return;
     
    +  // Apply an implicit SectionAttr if '#pragma clang section bss|data|rodata' is active
    +  if (VD->hasGlobalStorage() && VD->isThisDeclarationADefinition() &&
    +      !inTemplateInstantiation() && !VD->hasAttr()) {
    +    if (PragmaClangBSSSection.Valid)
    +      VD->addAttr(PragmaClangBSSSectionAttr::CreateImplicit(Context,
    +                                                            PragmaClangBSSSection.SectionName,
    +                                                            PragmaClangBSSSection.PragmaLocation));
    +    if (PragmaClangDataSection.Valid)
    +      VD->addAttr(PragmaClangDataSectionAttr::CreateImplicit(Context,
    +                                                             PragmaClangDataSection.SectionName,
    +                                                             PragmaClangDataSection.PragmaLocation));
    +    if (PragmaClangRodataSection.Valid)
    +      VD->addAttr(PragmaClangRodataSectionAttr::CreateImplicit(Context,
    +                                                               PragmaClangRodataSection.SectionName,
    +                                                               PragmaClangRodataSection.PragmaLocation));
    +  }
    +
       if (auto *DD = dyn_cast(ThisDecl)) {
         for (auto *BD : DD->bindings()) {
           FinalizeDeclaration(BD);
    diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
    index acacdc263c08..844299bb87cf 100644
    --- a/lib/Sema/SemaDeclCXX.cpp
    +++ b/lib/Sema/SemaDeclCXX.cpp
    @@ -547,17 +547,23 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
           Diag(OldParam->getLocation(), diag::note_previous_definition)
             << OldParam->getDefaultArgRange();
         } else if (OldParamHasDfl) {
    -      // Merge the old default argument into the new parameter.
    -      // It's important to use getInit() here;  getDefaultArg()
    -      // strips off any top-level ExprWithCleanups.
    -      NewParam->setHasInheritedDefaultArg();
    -      if (OldParam->hasUnparsedDefaultArg())
    -        NewParam->setUnparsedDefaultArg();
    -      else if (OldParam->hasUninstantiatedDefaultArg())
    -        NewParam->setUninstantiatedDefaultArg(
    -                                      OldParam->getUninstantiatedDefaultArg());
    -      else
    -        NewParam->setDefaultArg(OldParam->getInit());
    +      // Merge the old default argument into the new parameter unless the new
    +      // function is a friend declaration in a template class. In the latter
    +      // case the default arguments will be inherited when the friend
    +      // declaration will be instantiated.
    +      if (New->getFriendObjectKind() == Decl::FOK_None ||
    +          !New->getLexicalDeclContext()->isDependentContext()) {
    +        // It's important to use getInit() here;  getDefaultArg()
    +        // strips off any top-level ExprWithCleanups.
    +        NewParam->setHasInheritedDefaultArg();
    +        if (OldParam->hasUnparsedDefaultArg())
    +          NewParam->setUnparsedDefaultArg();
    +        else if (OldParam->hasUninstantiatedDefaultArg())
    +          NewParam->setUninstantiatedDefaultArg(
    +                                       OldParam->getUninstantiatedDefaultArg());
    +        else
    +          NewParam->setDefaultArg(OldParam->getInit());
    +      }
         } else if (NewParamHasDfl) {
           if (New->getDescribedFunctionTemplate()) {
             // Paragraph 4, quoted above, only applies to non-template functions.
    @@ -638,7 +644,12 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
         Diag(Old->getLocation(), diag::note_previous_declaration);
         Invalid = true;
       } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
    -             Old->isDefined(Def)) {
    +             Old->isDefined(Def) &&
    +             // If a friend function is inlined but does not have 'inline'
    +             // specifier, it is a definition. Do not report attribute conflict
    +             // in this case, redefinition will be diagnosed later.
    +             (New->isInlineSpecified() ||
    +              New->getFriendObjectKind() == Decl::FOK_None)) {
         // C++11 [dcl.fcn.spec]p4:
         //   If the definition of a function appears in a translation unit before its
         //   first declaration as inline, the program is ill-formed.
    @@ -13232,6 +13243,14 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
         }
       }
     
    +  ExprResult FullAssertExpr = ActOnFinishFullExpr(AssertExpr, StaticAssertLoc,
    +                                                  /*DiscardedValue*/false,
    +                                                  /*IsConstexpr*/true);
    +  if (FullAssertExpr.isInvalid())
    +    Failed = true;
    +  else
    +    AssertExpr = FullAssertExpr.get();
    +
       Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc,
                                             AssertExpr, AssertMessage, RParenLoc,
                                             Failed);
    diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
    index 4e7fb19b282b..0f8f5c253ac6 100644
    --- a/lib/Sema/SemaExpr.cpp
    +++ b/lib/Sema/SemaExpr.cpp
    @@ -11828,6 +11828,28 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
               RHSExpr->getType()->isOverloadableType())
             return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
         }
    +
    +    // If we're instantiating "a.x < b" or "A::x < b" and 'x' names a function
    +    // template, diagnose the missing 'template' keyword instead of diagnosing
    +    // an invalid use of a bound member function.
    +    //
    +    // Note that "A::x < b" might be valid if 'b' has an overloadable type due
    +    // to C++1z [over.over]/1.4, but we already checked for that case above.
    +    if (Opc == BO_LT && inTemplateInstantiation() &&
    +        (pty->getKind() == BuiltinType::BoundMember ||
    +         pty->getKind() == BuiltinType::Overload)) {
    +      auto *OE = dyn_cast(LHSExpr);
    +      if (OE && !OE->hasTemplateKeyword() && !OE->hasExplicitTemplateArgs() &&
    +          std::any_of(OE->decls_begin(), OE->decls_end(), [](NamedDecl *ND) {
    +            return isa(ND);
    +          })) {
    +        Diag(OE->getQualifier() ? OE->getQualifierLoc().getBeginLoc()
    +                                : OE->getNameLoc(),
    +             diag::err_template_kw_missing)
    +          << OE->getName().getAsString() << "";
    +        return ExprError();
    +      }
    +    }
             
         ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
         if (LHS.isInvalid()) return ExprError();
    @@ -11953,16 +11975,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
               << resultType << Input.get()->getSourceRange();
         else if (resultType->hasIntegerRepresentation())
           break;
    -    else if (resultType->isExtVectorType()) {
    -      if (Context.getLangOpts().OpenCL) {
    -        // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate
    -        // on vector float types.
    -        QualType T = resultType->getAs()->getElementType();
    -        if (!T->isIntegerType())
    -          return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
    -                           << resultType << Input.get()->getSourceRange());
    -      }
    -      break;
    +    else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) {
    +      // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate
    +      // on vector float types.
    +      QualType T = resultType->getAs()->getElementType();
    +      if (!T->isIntegerType())
    +        return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
    +                          << resultType << Input.get()->getSourceRange());
         } else {
           return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
                            << resultType << Input.get()->getSourceRange());
    diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
    index a05f7a7e406b..00a4b39f1423 100644
    --- a/lib/Sema/SemaExprCXX.cpp
    +++ b/lib/Sema/SemaExprCXX.cpp
    @@ -2658,6 +2658,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
             Context, GlobalCtx, SourceLocation(), SourceLocation(), Name,
             FnType, /*TInfo=*/nullptr, SC_None, false, true);
         Alloc->setImplicit();
    +    // Global allocation functions should always be visible.
    +    Alloc->setHidden(false);
     
         // Implicit sized deallocation functions always have default visibility.
         Alloc->addAttr(
    @@ -5104,7 +5106,9 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
           return QualType();
     
         // Cast LHS to type of use.
    -    QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
    +    QualType UseType = Context.getQualifiedType(Class, LHSType.getQualifiers());
    +    if (isIndirect)
    +      UseType = Context.getPointerType(UseType);
         ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind();
         LHS = ImpCastExprToType(LHS.get(), UseType, CK_DerivedToBase, VK,
                                 &BasePath);
    @@ -5281,16 +5285,16 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS
       switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) {
         case OR_Success: {
           // We found a match. Perform the conversions on the arguments and move on.
    -      ExprResult LHSRes =
    -        Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0],
    -                                       Best->Conversions[0], Sema::AA_Converting);
    +      ExprResult LHSRes = Self.PerformImplicitConversion(
    +          LHS.get(), Best->BuiltinParamTypes[0], Best->Conversions[0],
    +          Sema::AA_Converting);
           if (LHSRes.isInvalid())
             break;
           LHS = LHSRes;
     
    -      ExprResult RHSRes =
    -        Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1],
    -                                       Best->Conversions[1], Sema::AA_Converting);
    +      ExprResult RHSRes = Self.PerformImplicitConversion(
    +          RHS.get(), Best->BuiltinParamTypes[1], Best->Conversions[1],
    +          Sema::AA_Converting);
           if (RHSRes.isInvalid())
             break;
           RHS = RHSRes;
    diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
    index 1d32e5796812..1fb25f4e0e7c 100644
    --- a/lib/Sema/SemaLookup.cpp
    +++ b/lib/Sema/SemaLookup.cpp
    @@ -3747,20 +3747,19 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
                                           bool FindHidden);
     
     /// \brief Check whether the declarations found for a typo correction are
    -/// visible, and if none of them are, convert the correction to an 'import
    -/// a module' correction.
    +/// visible. Set the correction's RequiresImport flag to true if none of the
    +/// declarations are visible, false otherwise.
     static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
    -  if (TC.begin() == TC.end())
    -    return;
    -
       TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end();
     
       for (/**/; DI != DE; ++DI)
         if (!LookupResult::isVisible(SemaRef, *DI))
           break;
    -  // Nothing to do if all decls are visible.
    -  if (DI == DE)
    +  // No filtering needed if all decls are visible.
    +  if (DI == DE) {
    +    TC.setRequiresImport(false);
         return;
    +  }
     
       llvm::SmallVector NewDecls(TC.begin(), DI);
       bool AnyVisibleDecls = !NewDecls.empty();
    diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
    index 7bdd8872456a..5cc13f391d11 100644
    --- a/lib/Sema/SemaOverload.cpp
    +++ b/lib/Sema/SemaOverload.cpp
    @@ -7136,8 +7136,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
     /// operator. NumContextualBoolArguments is the number of arguments
     /// (at the beginning of the argument list) that will be contextually
     /// converted to bool.
    -void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
    -                               ArrayRef Args,
    +void Sema::AddBuiltinCandidate(QualType *ParamTys, ArrayRef Args,
                                    OverloadCandidateSet& CandidateSet,
                                    bool IsAssignmentOperator,
                                    unsigned NumContextualBoolArguments) {
    @@ -7151,9 +7150,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
       Candidate.Function = nullptr;
       Candidate.IsSurrogate = false;
       Candidate.IgnoreObjectArgument = false;
    -  Candidate.BuiltinTypes.ResultTy = ResultTy;
    -  for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx)
    -    Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx];
    +  std::copy(ParamTys, ParamTys + Args.size(), Candidate.BuiltinParamTypes);
     
       // Determine the implicit conversion sequences for each of the
       // arguments.
    @@ -7492,7 +7489,7 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
       // T& operator=(T&, T)
       ParamTypes[0] = S.Context.getLValueReferenceType(T);
       ParamTypes[1] = T;
    -  S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +  S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                             /*IsAssignmentOperator=*/true);
     
       if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
    @@ -7500,7 +7497,7 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
         ParamTypes[0]
           = S.Context.getLValueReferenceType(S.Context.getVolatileType(T));
         ParamTypes[1] = T;
    -    S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +    S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                               /*IsAssignmentOperator=*/true);
       }
     }
    @@ -7620,64 +7617,6 @@ class BuiltinOperatorOverloadBuilder {
         return S.Context.*ArithmeticTypes[index];
       }
     
    -  /// \brief Gets the canonical type resulting from the usual arithemetic
    -  /// converions for the given arithmetic types.
    -  CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) {
    -    // Accelerator table for performing the usual arithmetic conversions.
    -    // The rules are basically:
    -    //   - if either is floating-point, use the wider floating-point
    -    //   - if same signedness, use the higher rank
    -    //   - if same size, use unsigned of the higher rank
    -    //   - use the larger type
    -    // These rules, together with the axiom that higher ranks are
    -    // never smaller, are sufficient to precompute all of these results
    -    // *except* when dealing with signed types of higher rank.
    -    // (we could precompute SLL x UI for all known platforms, but it's
    -    // better not to make any assumptions).
    -    // We assume that int128 has a higher rank than long long on all platforms.
    -    enum PromotedType : int8_t {
    -            Dep=-1,
    -            Flt,  Dbl, LDbl,   SI,   SL,  SLL, S128,   UI,   UL,  ULL, U128
    -    };
    -    static const PromotedType ConversionsTable[LastPromotedArithmeticType]
    -                                        [LastPromotedArithmeticType] = {
    -/* Flt*/ {  Flt,  Dbl, LDbl,  Flt,  Flt,  Flt,  Flt,  Flt,  Flt,  Flt,  Flt },
    -/* Dbl*/ {  Dbl,  Dbl, LDbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl },
    -/*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl },
    -/*  SI*/ {  Flt,  Dbl, LDbl,   SI,   SL,  SLL, S128,   UI,   UL,  ULL, U128 },
    -/*  SL*/ {  Flt,  Dbl, LDbl,   SL,   SL,  SLL, S128,  Dep,   UL,  ULL, U128 },
    -/* SLL*/ {  Flt,  Dbl, LDbl,  SLL,  SLL,  SLL, S128,  Dep,  Dep,  ULL, U128 },
    -/*S128*/ {  Flt,  Dbl, LDbl, S128, S128, S128, S128, S128, S128, S128, U128 },
    -/*  UI*/ {  Flt,  Dbl, LDbl,   UI,  Dep,  Dep, S128,   UI,   UL,  ULL, U128 },
    -/*  UL*/ {  Flt,  Dbl, LDbl,   UL,   UL,  Dep, S128,   UL,   UL,  ULL, U128 },
    -/* ULL*/ {  Flt,  Dbl, LDbl,  ULL,  ULL,  ULL, S128,  ULL,  ULL,  ULL, U128 },
    -/*U128*/ {  Flt,  Dbl, LDbl, U128, U128, U128, U128, U128, U128, U128, U128 },
    -    };
    -
    -    assert(L < LastPromotedArithmeticType);
    -    assert(R < LastPromotedArithmeticType);
    -    int Idx = ConversionsTable[L][R];
    -
    -    // Fast path: the table gives us a concrete answer.
    -    if (Idx != Dep) return getArithmeticType(Idx);
    -
    -    // Slow path: we need to compare widths.
    -    // An invariant is that the signed type has higher rank.
    -    CanQualType LT = getArithmeticType(L),
    -                RT = getArithmeticType(R);
    -    unsigned LW = S.Context.getIntWidth(LT),
    -             RW = S.Context.getIntWidth(RT);
    -
    -    // If they're different widths, use the signed type.
    -    if (LW > RW) return LT;
    -    else if (LW < RW) return RT;
    -
    -    // Otherwise, use the unsigned type of the signed type's rank.
    -    if (L == SL || R == SL) return S.Context.UnsignedLongTy;
    -    assert(L == SLL || R == SLL);
    -    return S.Context.UnsignedLongLongTy;
    -  }
    -
       /// \brief Helper method to factor out the common pattern of adding overloads
       /// for '++' and '--' builtin operators.
       void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
    @@ -7689,10 +7628,7 @@ class BuiltinOperatorOverloadBuilder {
         };
     
         // Non-volatile version.
    -    if (Args.size() == 1)
    -      S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
    -    else
    -      S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet);
    +    S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
     
         // Use a heuristic to reduce number of builtin candidates in the set:
         // add volatile version only if there are conversions to a volatile type.
    @@ -7700,10 +7636,7 @@ class BuiltinOperatorOverloadBuilder {
           ParamTypes[0] =
             S.Context.getLValueReferenceType(
               S.Context.getVolatileType(CandidateTy));
    -      if (Args.size() == 1)
    -        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
    -      else
    -        S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet);
    +      S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
         }
     
         // Add restrict version only if there are conversions to a restrict type
    @@ -7713,10 +7646,7 @@ class BuiltinOperatorOverloadBuilder {
           ParamTypes[0]
             = S.Context.getLValueReferenceType(
                 S.Context.getCVRQualifiedType(CandidateTy, Qualifiers::Restrict));
    -      if (Args.size() == 1)
    -        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
    -      else
    -        S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet);
    +      S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
     
           if (HasVolatile) {
             ParamTypes[0]
    @@ -7724,10 +7654,7 @@ class BuiltinOperatorOverloadBuilder {
                   S.Context.getCVRQualifiedType(CandidateTy,
                                                 (Qualifiers::Volatile |
                                                  Qualifiers::Restrict)));
    -        if (Args.size() == 1)
    -          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
    -        else
    -          S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet);
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
           }
         }
     
    @@ -7841,8 +7768,7 @@ class BuiltinOperatorOverloadBuilder {
             if (Proto->getTypeQuals() || Proto->getRefQualifier())
               continue;
     
    -      S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy),
    -                            &ParamTy, Args, CandidateSet);
    +      S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet);
         }
       }
     
    @@ -7859,7 +7785,7 @@ class BuiltinOperatorOverloadBuilder {
         for (unsigned Arith = FirstPromotedArithmeticType;
              Arith < LastPromotedArithmeticType; ++Arith) {
           QualType ArithTy = getArithmeticType(Arith);
    -      S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, CandidateSet);
    +      S.AddBuiltinCandidate(&ArithTy, Args, CandidateSet);
         }
     
         // Extension: We also add these operators for vector types.
    @@ -7868,7 +7794,7 @@ class BuiltinOperatorOverloadBuilder {
                VecEnd = CandidateTypes[0].vector_end();
              Vec != VecEnd; ++Vec) {
           QualType VecTy = *Vec;
    -      S.AddBuiltinCandidate(VecTy, &VecTy, Args, CandidateSet);
    +      S.AddBuiltinCandidate(&VecTy, Args, CandidateSet);
         }
       }
     
    @@ -7883,7 +7809,7 @@ class BuiltinOperatorOverloadBuilder {
                PtrEnd = CandidateTypes[0].pointer_end();
              Ptr != PtrEnd; ++Ptr) {
           QualType ParamTy = *Ptr;
    -      S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, CandidateSet);
    +      S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet);
         }
       }
     
    @@ -7899,7 +7825,7 @@ class BuiltinOperatorOverloadBuilder {
         for (unsigned Int = FirstPromotedIntegralType;
              Int < LastPromotedIntegralType; ++Int) {
           QualType IntTy = getArithmeticType(Int);
    -      S.AddBuiltinCandidate(IntTy, &IntTy, Args, CandidateSet);
    +      S.AddBuiltinCandidate(&IntTy, Args, CandidateSet);
         }
     
         // Extension: We also add this operator for vector types.
    @@ -7908,7 +7834,7 @@ class BuiltinOperatorOverloadBuilder {
                VecEnd = CandidateTypes[0].vector_end();
              Vec != VecEnd; ++Vec) {
           QualType VecTy = *Vec;
    -      S.AddBuiltinCandidate(VecTy, &VecTy, Args, CandidateSet);
    +      S.AddBuiltinCandidate(&VecTy, Args, CandidateSet);
         }
       }
     
    @@ -7933,15 +7859,14 @@ class BuiltinOperatorOverloadBuilder {
               continue;
     
             QualType ParamTypes[2] = { *MemPtr, *MemPtr };
    -        S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet);
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
           }
     
           if (CandidateTypes[ArgIdx].hasNullPtrType()) {
             CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy);
             if (AddedTypes.insert(NullPtrTy).second) {
               QualType ParamTypes[2] = { NullPtrTy, NullPtrTy };
    -          S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args,
    -                                CandidateSet);
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
             }
           }
         }
    @@ -8017,7 +7942,7 @@ class BuiltinOperatorOverloadBuilder {
               continue;
     
             QualType ParamTypes[2] = { *Ptr, *Ptr };
    -        S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet);
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
           }
           for (BuiltinCandidateTypeSet::iterator
                     Enum = CandidateTypes[ArgIdx].enumeration_begin(),
    @@ -8033,7 +7958,7 @@ class BuiltinOperatorOverloadBuilder {
               continue;
     
             QualType ParamTypes[2] = { *Enum, *Enum };
    -        S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet);
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
           }
         }
       }
    @@ -8076,7 +8001,7 @@ class BuiltinOperatorOverloadBuilder {
             if (Arg == 0 || Op == OO_Plus) {
               // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
               // T* operator+(ptrdiff_t, T*);
    -          S.AddBuiltinCandidate(*Ptr, AsymmetricParamTypes, Args, CandidateSet);
    +          S.AddBuiltinCandidate(AsymmetricParamTypes, Args, CandidateSet);
             }
             if (Op == OO_Minus) {
               // ptrdiff_t operator-(T, T);
    @@ -8084,8 +8009,7 @@ class BuiltinOperatorOverloadBuilder {
                 continue;
     
               QualType ParamTypes[2] = { *Ptr, *Ptr };
    -          S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes,
    -                                Args, CandidateSet);
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
             }
           }
         }
    @@ -8120,7 +8044,7 @@ class BuiltinOperatorOverloadBuilder {
       //   where LR is the result of the usual arithmetic conversions
       //   between types L and R.
       // Our candidates ignore the first parameter.
    -  void addGenericBinaryArithmeticOverloads(bool isComparison) {
    +  void addGenericBinaryArithmeticOverloads() {
         if (!HasArithmeticOrEnumeralCandidateType)
           return;
     
    @@ -8130,10 +8054,7 @@ class BuiltinOperatorOverloadBuilder {
                Right < LastPromotedArithmeticType; ++Right) {
             QualType LandR[2] = { getArithmeticType(Left),
                                   getArithmeticType(Right) };
    -        QualType Result =
    -          isComparison ? S.Context.BoolTy
    -                       : getUsualArithmeticConversions(Left, Right);
    -        S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet);
    +        S.AddBuiltinCandidate(LandR, Args, CandidateSet);
           }
         }
     
    @@ -8148,15 +8069,7 @@ class BuiltinOperatorOverloadBuilder {
                  Vec2End = CandidateTypes[1].vector_end();
                Vec2 != Vec2End; ++Vec2) {
             QualType LandR[2] = { *Vec1, *Vec2 };
    -        QualType Result = S.Context.BoolTy;
    -        if (!isComparison) {
    -          if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType())
    -            Result = *Vec1;
    -          else
    -            Result = *Vec2;
    -        }
    -
    -        S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet);
    +        S.AddBuiltinCandidate(LandR, Args, CandidateSet);
           }
         }
       }
    @@ -8185,10 +8098,7 @@ class BuiltinOperatorOverloadBuilder {
                Right < LastPromotedIntegralType; ++Right) {
             QualType LandR[2] = { getArithmeticType(Left),
                                   getArithmeticType(Right) };
    -        QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater)
    -            ? LandR[0]
    -            : getUsualArithmeticConversions(Left, Right);
    -        S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet);
    +        S.AddBuiltinCandidate(LandR, Args, CandidateSet);
           }
         }
       }
    @@ -8262,7 +8172,7 @@ class BuiltinOperatorOverloadBuilder {
             S.Context.getLValueReferenceType(*Ptr),
             isEqualOp ? *Ptr : S.Context.getPointerDiffType(),
           };
    -      S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +      S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                 /*IsAssigmentOperator=*/ isEqualOp);
     
           bool NeedVolatile = !(*Ptr).isVolatileQualified() &&
    @@ -8271,7 +8181,7 @@ class BuiltinOperatorOverloadBuilder {
             // volatile version
             ParamTypes[0] =
               S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
    -        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                   /*IsAssigmentOperator=*/isEqualOp);
           }
     
    @@ -8280,7 +8190,7 @@ class BuiltinOperatorOverloadBuilder {
             // restrict version
             ParamTypes[0]
               = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr));
    -        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                   /*IsAssigmentOperator=*/isEqualOp);
     
             if (NeedVolatile) {
    @@ -8290,7 +8200,7 @@ class BuiltinOperatorOverloadBuilder {
                     S.Context.getCVRQualifiedType(*Ptr,
                                                   (Qualifiers::Volatile |
                                                    Qualifiers::Restrict)));
    -          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                     /*IsAssigmentOperator=*/isEqualOp);
             }
           }
    @@ -8311,7 +8221,7 @@ class BuiltinOperatorOverloadBuilder {
             };
     
             // non-volatile version
    -        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                   /*IsAssigmentOperator=*/true);
     
             bool NeedVolatile = !(*Ptr).isVolatileQualified() &&
    @@ -8320,7 +8230,7 @@ class BuiltinOperatorOverloadBuilder {
               // volatile version
               ParamTypes[0] =
                 S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
    -          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                     /*IsAssigmentOperator=*/true);
             }
     
    @@ -8329,7 +8239,7 @@ class BuiltinOperatorOverloadBuilder {
               // restrict version
               ParamTypes[0]
                 = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr));
    -          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                     /*IsAssigmentOperator=*/true);
     
               if (NeedVolatile) {
    @@ -8339,7 +8249,7 @@ class BuiltinOperatorOverloadBuilder {
                       S.Context.getCVRQualifiedType(*Ptr,
                                                     (Qualifiers::Volatile |
                                                      Qualifiers::Restrict)));
    -            S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +            S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                       /*IsAssigmentOperator=*/true);
               }
             }
    @@ -8372,7 +8282,7 @@ class BuiltinOperatorOverloadBuilder {
             // Add this built-in operator as a candidate (VQ is empty).
             ParamTypes[0] =
               S.Context.getLValueReferenceType(getArithmeticType(Left));
    -        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                   /*IsAssigmentOperator=*/isEqualOp);
     
             // Add this built-in operator as a candidate (VQ is 'volatile').
    @@ -8380,7 +8290,7 @@ class BuiltinOperatorOverloadBuilder {
               ParamTypes[0] =
                 S.Context.getVolatileType(getArithmeticType(Left));
               ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
    -          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                     /*IsAssigmentOperator=*/isEqualOp);
             }
           }
    @@ -8399,14 +8309,14 @@ class BuiltinOperatorOverloadBuilder {
             ParamTypes[1] = *Vec2;
             // Add this built-in operator as a candidate (VQ is empty).
             ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1);
    -        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                   /*IsAssigmentOperator=*/isEqualOp);
     
             // Add this built-in operator as a candidate (VQ is 'volatile').
             if (VisibleTypeConversionsQuals.hasVolatile()) {
               ParamTypes[0] = S.Context.getVolatileType(*Vec1);
               ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
    -          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                                     /*IsAssigmentOperator=*/isEqualOp);
             }
           }
    @@ -8438,13 +8348,13 @@ class BuiltinOperatorOverloadBuilder {
             // Add this built-in operator as a candidate (VQ is empty).
             ParamTypes[0] =
               S.Context.getLValueReferenceType(getArithmeticType(Left));
    -        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
             if (VisibleTypeConversionsQuals.hasVolatile()) {
               // Add this built-in operator as a candidate (VQ is 'volatile').
               ParamTypes[0] = getArithmeticType(Left);
               ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]);
               ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
    -          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
             }
           }
         }
    @@ -8459,13 +8369,13 @@ class BuiltinOperatorOverloadBuilder {
       //        bool        operator||(bool, bool);
       void addExclaimOverload() {
         QualType ParamTy = S.Context.BoolTy;
    -    S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, CandidateSet,
    +    S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet,
                               /*IsAssignmentOperator=*/false,
                               /*NumContextualBoolArguments=*/1);
       }
       void addAmpAmpOrPipePipeOverload() {
         QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy };
    -    S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet,
    +    S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
                               /*IsAssignmentOperator=*/false,
                               /*NumContextualBoolArguments=*/2);
       }
    @@ -8490,10 +8400,8 @@ class BuiltinOperatorOverloadBuilder {
           if (!PointeeType->isObjectType())
             continue;
     
    -      QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
    -
           // T& operator[](T*, ptrdiff_t)
    -      S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet);
    +      S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
         }
     
         for (BuiltinCandidateTypeSet::iterator
    @@ -8505,10 +8413,8 @@ class BuiltinOperatorOverloadBuilder {
           if (!PointeeType->isObjectType())
             continue;
     
    -      QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
    -
           // T& operator[](ptrdiff_t, T*)
    -      S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet);
    +      S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
         }
       }
     
    @@ -8558,8 +8464,7 @@ class BuiltinOperatorOverloadBuilder {
                 T.isRestrictQualified())
               continue;
             T = Q1.apply(S.Context, T);
    -        QualType ResultTy = S.Context.getLValueReferenceType(T);
    -        S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet);
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
           }
         }
       }
    @@ -8587,7 +8492,7 @@ class BuiltinOperatorOverloadBuilder {
               continue;
     
             QualType ParamTypes[2] = { *Ptr, *Ptr };
    -        S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, CandidateSet);
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
           }
     
           for (BuiltinCandidateTypeSet::iterator
    @@ -8598,7 +8503,7 @@ class BuiltinOperatorOverloadBuilder {
               continue;
     
             QualType ParamTypes[2] = { *MemPtr, *MemPtr };
    -        S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, CandidateSet);
    +        S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
           }
     
           if (S.getLangOpts().CPlusPlus11) {
    @@ -8613,7 +8518,7 @@ class BuiltinOperatorOverloadBuilder {
                 continue;
     
               QualType ParamTypes[2] = { *Enum, *Enum };
    -          S.AddBuiltinCandidate(*Enum, ParamTypes, Args, CandidateSet);
    +          S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
             }
           }
         }
    @@ -8707,7 +8612,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
           OpBuilder.addUnaryPlusOrMinusArithmeticOverloads();
         } else {
           OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op);
    -      OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
    +      OpBuilder.addGenericBinaryArithmeticOverloads();
         }
         break;
     
    @@ -8715,11 +8620,11 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
         if (Args.size() == 1)
           OpBuilder.addUnaryStarPointerOverloads();
         else
    -      OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
    +      OpBuilder.addGenericBinaryArithmeticOverloads();
         break;
     
       case OO_Slash:
    -    OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
    +    OpBuilder.addGenericBinaryArithmeticOverloads();
         break;
     
       case OO_PlusPlus:
    @@ -8738,7 +8643,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
       case OO_LessEqual:
       case OO_GreaterEqual:
         OpBuilder.addRelationalPointerOrEnumeralOverloads();
    -    OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true);
    +    OpBuilder.addGenericBinaryArithmeticOverloads();
         break;
     
       case OO_Percent:
    @@ -8805,7 +8710,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
     
       case OO_Conditional:
         OpBuilder.addConditionalOperatorOverloads();
    -    OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
    +    OpBuilder.addGenericBinaryArithmeticOverloads();
         break;
       }
     }
    @@ -10237,13 +10142,13 @@ static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
       std::string TypeStr("operator");
       TypeStr += Opc;
       TypeStr += "(";
    -  TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
    +  TypeStr += Cand->BuiltinParamTypes[0].getAsString();
       if (Cand->Conversions.size() == 1) {
         TypeStr += ")";
         S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
       } else {
         TypeStr += ", ";
    -    TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
    +    TypeStr += Cand->BuiltinParamTypes[1].getAsString();
         TypeStr += ")";
         S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
       }
    @@ -10480,7 +10385,7 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
       } else {
         // Builtin operator.
         assert(ConvCount <= 3);
    -    ParamTypes = Cand->BuiltinTypes.ParamTypes;
    +    ParamTypes = Cand->BuiltinParamTypes;
       }
     
       // Fill in the rest of the conversions.
    @@ -12086,9 +11991,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
           // We matched a built-in operator. Convert the arguments, then
           // break out so that we will build the appropriate built-in
           // operator node.
    -      ExprResult InputRes =
    -        PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0],
    -                                  Best->Conversions[0], AA_Passing);
    +      ExprResult InputRes = PerformImplicitConversion(
    +          Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing);
           if (InputRes.isInvalid())
             return ExprError();
           Input = InputRes.get();
    @@ -12332,15 +12236,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
             // break out so that we will build the appropriate built-in
             // operator node.
             ExprResult ArgsRes0 =
    -          PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
    -                                    Best->Conversions[0], AA_Passing);
    +            PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0],
    +                                      Best->Conversions[0], AA_Passing);
             if (ArgsRes0.isInvalid())
               return ExprError();
             Args[0] = ArgsRes0.get();
     
             ExprResult ArgsRes1 =
    -          PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
    -                                    Best->Conversions[1], AA_Passing);
    +            PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1],
    +                                      Best->Conversions[1], AA_Passing);
             if (ArgsRes1.isInvalid())
               return ExprError();
             Args[1] = ArgsRes1.get();
    @@ -12543,15 +12447,15 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
             // break out so that we will build the appropriate built-in
             // operator node.
             ExprResult ArgsRes0 =
    -          PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
    -                                    Best->Conversions[0], AA_Passing);
    +            PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0],
    +                                      Best->Conversions[0], AA_Passing);
             if (ArgsRes0.isInvalid())
               return ExprError();
             Args[0] = ArgsRes0.get();
     
             ExprResult ArgsRes1 =
    -          PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
    -                                    Best->Conversions[1], AA_Passing);
    +            PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1],
    +                                      Best->Conversions[1], AA_Passing);
             if (ArgsRes1.isInvalid())
               return ExprError();
             Args[1] = ArgsRes1.get();
    diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
    index dcb2c11c73c7..151b89ab8d2a 100644
    --- a/lib/Sema/SemaStmt.cpp
    +++ b/lib/Sema/SemaStmt.cpp
    @@ -3956,8 +3956,9 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
       DeclContext *DC = CapturedDecl::castToDeclContext(CD);
       IdentifierInfo *ParamName = &Context.Idents.get("__context");
       QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
    -  ImplicitParamDecl *Param
    -    = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
    +  auto *Param =
    +      ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType,
    +                                ImplicitParamDecl::CapturedContext);
       DC->addDecl(Param);
     
       CD->setContextParam(0, Param);
    @@ -3992,15 +3993,17 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
                  "null type has been found already for '__context' parameter");
           IdentifierInfo *ParamName = &Context.Idents.get("__context");
           QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
    -      ImplicitParamDecl *Param
    -        = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
    +      auto *Param =
    +          ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType,
    +                                    ImplicitParamDecl::CapturedContext);
           DC->addDecl(Param);
           CD->setContextParam(ParamNum, Param);
           ContextIsFound = true;
         } else {
           IdentifierInfo *ParamName = &Context.Idents.get(I->first);
    -      ImplicitParamDecl *Param
    -        = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second);
    +      auto *Param =
    +          ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second,
    +                                    ImplicitParamDecl::CapturedContext);
           DC->addDecl(Param);
           CD->setParam(ParamNum, Param);
         }
    @@ -4010,8 +4013,9 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
         // Add __context implicitly if it is not specified.
         IdentifierInfo *ParamName = &Context.Idents.get("__context");
         QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD));
    -    ImplicitParamDecl *Param =
    -        ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType);
    +    auto *Param =
    +        ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType,
    +                                  ImplicitParamDecl::CapturedContext);
         DC->addDecl(Param);
         CD->setContextParam(ParamNum, Param);
       }
    diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
    index 8cd7efbb1dba..1eea151a4ec8 100644
    --- a/lib/Sema/SemaTemplate.cpp
    +++ b/lib/Sema/SemaTemplate.cpp
    @@ -4020,6 +4020,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
           }
         }
         // fallthrough
    +    LLVM_FALLTHROUGH;
       }
       default: {
         // We have a template type parameter but the template argument
    @@ -7594,6 +7595,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
             return false;
           }
           // Fall through
    +      LLVM_FALLTHROUGH;
     
         case TSK_ExplicitInstantiationDeclaration:
         case TSK_ExplicitInstantiationDefinition:
    @@ -7620,6 +7622,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
     
           return true;
         }
    +    llvm_unreachable("The switch over PrevTSK must be exhaustive.");
     
       case TSK_ExplicitInstantiationDeclaration:
         switch (PrevTSK) {
    @@ -8955,7 +8958,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
       //   A member function [...] of a class template can be explicitly
       //  instantiated from the member definition associated with its class
       //  template.
    -  UnresolvedSet<8> Matches;
    +  UnresolvedSet<8> TemplateMatches;
    +  FunctionDecl *NonTemplateMatch = nullptr;
       AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
       TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
       for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
    @@ -8966,11 +8970,13 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
             QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(),
                                                     /*AdjustExceptionSpec*/true);
             if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
    -          Matches.clear();
    -
    -          Matches.addDecl(Method, P.getAccess());
    -          if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
    -            break;
    +          if (Method->getPrimaryTemplate()) {
    +            TemplateMatches.addDecl(Method, P.getAccess());
    +          } else {
    +            // FIXME: Can this assert ever happen?  Needs a test.
    +            assert(!NonTemplateMatch && "Multiple NonTemplateMatches");
    +            NonTemplateMatch = Method;
    +          }
             }
           }
         }
    @@ -9009,22 +9015,25 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
           continue;
         }
     
    -    Matches.addDecl(Specialization, P.getAccess());
    +    TemplateMatches.addDecl(Specialization, P.getAccess());
       }
     
    -  // Find the most specialized function template specialization.
    -  UnresolvedSetIterator Result = getMostSpecialized(
    -      Matches.begin(), Matches.end(), FailedCandidates,
    -      D.getIdentifierLoc(),
    -      PDiag(diag::err_explicit_instantiation_not_known) << Name,
    -      PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
    -      PDiag(diag::note_explicit_instantiation_candidate));
    +  FunctionDecl *Specialization = NonTemplateMatch;
    +  if (!Specialization) {
    +    // Find the most specialized function template specialization.
    +    UnresolvedSetIterator Result = getMostSpecialized(
    +        TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates,
    +        D.getIdentifierLoc(),
    +        PDiag(diag::err_explicit_instantiation_not_known) << Name,
    +        PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
    +        PDiag(diag::note_explicit_instantiation_candidate));
     
    -  if (Result == Matches.end())
    -    return true;
    +    if (Result == TemplateMatches.end())
    +      return true;
     
    -  // Ignore access control bits, we don't need them for redeclaration checking.
    -  FunctionDecl *Specialization = cast(*Result);
    +    // Ignore access control bits, we don't need them for redeclaration checking.
    +    Specialization = cast(*Result);
    +  }
     
       // C++11 [except.spec]p4
       // In an explicit instantiation an exception-specification may be specified,
    @@ -9379,6 +9388,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
       }
       // Fall through to create a dependent typename type, from which we can recover
       // better.
    +  LLVM_FALLTHROUGH;
     
       case LookupResult::NotFoundInCurrentInstantiation:
         // Okay, it's a member of an unknown instantiation.
    diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
    index 75b69ae04f56..983b1ea795dd 100644
    --- a/lib/Sema/SemaTemplateDeduction.cpp
    +++ b/lib/Sema/SemaTemplateDeduction.cpp
    @@ -56,8 +56,12 @@ namespace clang {
         TDF_TopLevelParameterTypeList = 0x10,
         /// \brief Within template argument deduction from overload resolution per
         /// C++ [over.over] allow matching function types that are compatible in
    -    /// terms of noreturn and default calling convention adjustments.
    -    TDF_InOverloadResolution = 0x20
    +    /// terms of noreturn and default calling convention adjustments, or
    +    /// similarly matching a declared template specialization against a
    +    /// possible template, per C++ [temp.deduct.decl]. In either case, permit
    +    /// deduction where the parameter is a function type that can be converted
    +    /// to the argument type.
    +    TDF_AllowCompatibleFunctionType = 0x20,
       };
     }
     
    @@ -1306,9 +1310,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
         // If the parameter type is not dependent, there is nothing to deduce.
         if (!Param->isDependentType()) {
           if (!(TDF & TDF_SkipNonDependent)) {
    -        bool NonDeduced = (TDF & TDF_InOverloadResolution)?
    -                          !S.isSameOrCompatibleFunctionType(CanParam, CanArg) :
    -                          Param != Arg;
    +        bool NonDeduced =
    +            (TDF & TDF_AllowCompatibleFunctionType)
    +                ? !S.isSameOrCompatibleFunctionType(CanParam, CanArg)
    +                : Param != Arg;
             if (NonDeduced) {
               return Sema::TDK_NonDeducedMismatch;
             }
    @@ -1318,10 +1323,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
       } else if (!Param->isDependentType()) {
         CanQualType ParamUnqualType = CanParam.getUnqualifiedType(),
                     ArgUnqualType = CanArg.getUnqualifiedType();
    -    bool Success = (TDF & TDF_InOverloadResolution)?
    -                   S.isSameOrCompatibleFunctionType(ParamUnqualType,
    -                                                    ArgUnqualType) :
    -                   ParamUnqualType == ArgUnqualType;
    +    bool Success =
    +        (TDF & TDF_AllowCompatibleFunctionType)
    +            ? S.isSameOrCompatibleFunctionType(ParamUnqualType, ArgUnqualType)
    +            : ParamUnqualType == ArgUnqualType;
         if (Success)
           return Sema::TDK_Success;
       }
    @@ -1524,17 +1529,56 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
             return Sema::TDK_NonDeducedMismatch;
     
           // Check return types.
    -      if (Sema::TemplateDeductionResult Result =
    -              DeduceTemplateArgumentsByTypeMatch(
    -                  S, TemplateParams, FunctionProtoParam->getReturnType(),
    -                  FunctionProtoArg->getReturnType(), Info, Deduced, 0))
    +      if (auto Result = DeduceTemplateArgumentsByTypeMatch(
    +              S, TemplateParams, FunctionProtoParam->getReturnType(),
    +              FunctionProtoArg->getReturnType(), Info, Deduced, 0))
             return Result;
     
    -      return DeduceTemplateArguments(
    -          S, TemplateParams, FunctionProtoParam->param_type_begin(),
    -          FunctionProtoParam->getNumParams(),
    -          FunctionProtoArg->param_type_begin(),
    -          FunctionProtoArg->getNumParams(), Info, Deduced, SubTDF);
    +      // Check parameter types.
    +      if (auto Result = DeduceTemplateArguments(
    +              S, TemplateParams, FunctionProtoParam->param_type_begin(),
    +              FunctionProtoParam->getNumParams(),
    +              FunctionProtoArg->param_type_begin(),
    +              FunctionProtoArg->getNumParams(), Info, Deduced, SubTDF))
    +        return Result;
    +
    +      if (TDF & TDF_AllowCompatibleFunctionType)
    +        return Sema::TDK_Success;
    +
    +      // FIXME: Per core-2016/10/1019 (no corresponding core issue yet), permit
    +      // deducing through the noexcept-specifier if it's part of the canonical
    +      // type. libstdc++ relies on this.
    +      Expr *NoexceptExpr = FunctionProtoParam->getNoexceptExpr();
    +      if (NonTypeTemplateParmDecl *NTTP =
    +          NoexceptExpr ? getDeducedParameterFromExpr(Info, NoexceptExpr)
    +                       : nullptr) {
    +        assert(NTTP->getDepth() == Info.getDeducedDepth() &&
    +               "saw non-type template parameter with wrong depth");
    +
    +        llvm::APSInt Noexcept(1);
    +        switch (FunctionProtoArg->canThrow(S.Context)) {
    +        case CT_Cannot:
    +          Noexcept = 1;
    +          LLVM_FALLTHROUGH;
    +
    +        case CT_Can:
    +          // We give E in noexcept(E) the "deduced from array bound" treatment.
    +          // FIXME: Should we?
    +          return DeduceNonTypeTemplateArgument(
    +              S, TemplateParams, NTTP, Noexcept, S.Context.BoolTy,
    +              /*ArrayBound*/true, Info, Deduced);
    +
    +        case CT_Dependent:
    +          if (Expr *ArgNoexceptExpr = FunctionProtoArg->getNoexceptExpr())
    +            return DeduceNonTypeTemplateArgument(
    +                S, TemplateParams, NTTP, ArgNoexceptExpr, Info, Deduced);
    +          // Can't deduce anything from throw(T...).
    +          break;
    +        }
    +      }
    +      // FIXME: Detect non-deduced exception specification mismatches?
    +
    +      return Sema::TDK_Success;
         }
     
         case Type::InjectedClassName: {
    @@ -1544,7 +1588,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
             ->getInjectedSpecializationType();
           assert(isa(Param) &&
                  "injected class name is not a template specialization type");
    -      // fall through
    +      LLVM_FALLTHROUGH;
         }
     
         //     template-name (where template-name refers to a class template)
    @@ -2820,6 +2864,17 @@ Sema::SubstituteExplicitTemplateArguments(
       if (FunctionType) {
         auto EPI = Proto->getExtProtoInfo();
         EPI.ExtParameterInfos = ExtParamInfos.getPointerOrNull(ParamTypes.size());
    +
    +    // In C++1z onwards, exception specifications are part of the function type,
    +    // so substitution into the type must also substitute into the exception
    +    // specification.
    +    SmallVector ExceptionStorage;
    +    if (getLangOpts().CPlusPlus1z &&
    +        SubstExceptionSpec(
    +            Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage,
    +            MultiLevelTemplateArgumentList(*ExplicitArgumentList)))
    +      return TDK_SubstitutionFailure;
    +
         *FunctionType = BuildFunctionType(ResultType, ParamTypes,
                                           Function->getLocation(),
                                           Function->getDeclName(),
    @@ -3714,13 +3769,6 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
         = FunctionTemplate->getTemplateParameters();
       QualType FunctionType = Function->getType();
     
    -  // When taking the address of a function, we require convertibility of
    -  // the resulting function type. Otherwise, we allow arbitrary mismatches
    -  // of calling convention, noreturn, and noexcept.
    -  if (!IsAddressOfFunction)
    -    ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType,
    -                                          /*AdjustExceptionSpec*/true);
    -
       // Substitute any explicit template arguments.
       LocalInstantiationScope InstScope(*this);
       SmallVector Deduced;
    @@ -3737,6 +3785,13 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
         NumExplicitlySpecified = Deduced.size();
       }
     
    +  // When taking the address of a function, we require convertibility of
    +  // the resulting function type. Otherwise, we allow arbitrary mismatches
    +  // of calling convention and noreturn.
    +  if (!IsAddressOfFunction)
    +    ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType,
    +                                          /*AdjustExceptionSpec*/false);
    +
       // Unevaluated SFINAE context.
       EnterExpressionEvaluationContext Unevaluated(
           *this, Sema::ExpressionEvaluationContext::Unevaluated);
    @@ -3756,9 +3811,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
       }
     
       if (!ArgFunctionType.isNull()) {
    -    unsigned TDF = TDF_TopLevelParameterTypeList;
    -    if (IsAddressOfFunction)
    -      TDF |= TDF_InOverloadResolution;
    +    unsigned TDF =
    +        TDF_TopLevelParameterTypeList | TDF_AllowCompatibleFunctionType;
         // Deduce template arguments from the function type.
         if (TemplateDeductionResult Result
               = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
    @@ -3789,7 +3843,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
           !ResolveExceptionSpec(Info.getLocation(), SpecializationFPT))
         return TDK_MiscellaneousDeductionFailure;
     
    -  // Adjust the exception specification of the argument again to match the
    +  // Adjust the exception specification of the argument to match the
       // substituted and resolved type we just formed. (Calling convention and
       // noreturn can't be dependent, so we don't actually need this for them
       // right now.)
    @@ -5127,6 +5181,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
         for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I)
           MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced,
                                      Depth, Used);
    +    if (auto *E = Proto->getNoexceptExpr())
    +      MarkUsedTemplateParameters(Ctx, E, OnlyDeduced, Depth, Used);
         break;
       }
     
    diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
    index a654ca800b05..fe92dd8ac653 100644
    --- a/lib/Sema/SemaTemplateInstantiate.cpp
    +++ b/lib/Sema/SemaTemplateInstantiate.cpp
    @@ -1692,20 +1692,26 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
       return TLB.getTypeSourceInfo(Context, Result);
     }
     
    +bool Sema::SubstExceptionSpec(SourceLocation Loc,
    +                              FunctionProtoType::ExceptionSpecInfo &ESI,
    +                              SmallVectorImpl &ExceptionStorage,
    +                              const MultiLevelTemplateArgumentList &Args) {
    +  assert(ESI.Type != EST_Uninstantiated);
    +
    +  bool Changed = false;
    +  TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName());
    +  return Instantiator.TransformExceptionSpec(Loc, ESI, ExceptionStorage,
    +                                             Changed);
    +}
    +
     void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
                                   const MultiLevelTemplateArgumentList &Args) {
       FunctionProtoType::ExceptionSpecInfo ESI =
           Proto->getExtProtoInfo().ExceptionSpec;
    -  assert(ESI.Type != EST_Uninstantiated);
    -
    -  TemplateInstantiator Instantiator(*this, Args, New->getLocation(),
    -                                    New->getDeclName());
     
       SmallVector ExceptionStorage;
    -  bool Changed = false;
    -  if (Instantiator.TransformExceptionSpec(
    -          New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), ESI,
    -          ExceptionStorage, Changed))
    +  if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getLocEnd(),
    +                         ESI, ExceptionStorage, Args))
         // On error, recover by dropping the exception specification.
         ESI.Type = EST_None;
     
    @@ -2350,6 +2356,25 @@ namespace {
       };
     }
     
    +bool Sema::usesPartialOrExplicitSpecialization(
    +    SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec) {
    +  if (ClassTemplateSpec->getTemplateSpecializationKind() ==
    +      TSK_ExplicitSpecialization)
    +    return true;
    +
    +  SmallVector PartialSpecs;
    +  ClassTemplateSpec->getSpecializedTemplate()
    +                   ->getPartialSpecializations(PartialSpecs);
    +  for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
    +    TemplateDeductionInfo Info(Loc);
    +    if (!DeduceTemplateArguments(PartialSpecs[I],
    +                                 ClassTemplateSpec->getTemplateArgs(), Info))
    +      return true;
    +  }
    +
    +  return false;
    +}
    +
     /// Get the instantiation pattern to use to instantiate the definition of a
     /// given ClassTemplateSpecializationDecl (either the pattern of the primary
     /// template or of a partial specialization).
    diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
    index e7523ce2836d..148ce24293a0 100644
    --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
    +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
    @@ -4807,7 +4807,7 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx,
     DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
                               const MultiLevelTemplateArgumentList &TemplateArgs) {
       if (NamedDecl *D = dyn_cast(DC)) {
    -    Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs);
    +    Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs, true);
         return cast_or_null(ID);
       } else return DC;
     }
    @@ -4839,7 +4839,8 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
     /// (X::::KnownValue). \p FindInstantiatedDecl performs
     /// this mapping from within the instantiation of X.
     NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
    -                          const MultiLevelTemplateArgumentList &TemplateArgs) {
    +                          const MultiLevelTemplateArgumentList &TemplateArgs,
    +                          bool FindingInstantiatedContext) {
       DeclContext *ParentDC = D->getDeclContext();
       // FIXME: Parmeters of pointer to functions (y below) that are themselves 
       // parameters (p below) can have their ParentDC set to the translation-unit
    @@ -5000,7 +5001,22 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
               QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args);
               if (T.isNull())
                 return nullptr;
    -          DC = T->getAsCXXRecordDecl();
    +          auto *SubstRecord = T->getAsCXXRecordDecl();
    +          assert(SubstRecord && "class template id not a class type?");
    +          // Check that this template-id names the primary template and not a
    +          // partial or explicit specialization. (In the latter cases, it's
    +          // meaningless to attempt to find an instantiation of D within the
    +          // specialization.)
    +          // FIXME: The standard doesn't say what should happen here.
    +          if (FindingInstantiatedContext &&
    +              usesPartialOrExplicitSpecialization(
    +                  Loc, cast(SubstRecord))) {
    +            Diag(Loc, diag::err_specialization_not_primary_template)
    +              << T << (SubstRecord->getTemplateSpecializationKind() ==
    +                           TSK_ExplicitSpecialization);
    +            return nullptr;
    +          }
    +          DC = SubstRecord;
               continue;
             }
           }
    diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
    index c189112e3455..8c8402e75e37 100644
    --- a/lib/Sema/SemaType.cpp
    +++ b/lib/Sema/SemaType.cpp
    @@ -3367,7 +3367,7 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator,
         if (auto objcClass = type->getAs()) {
           if (objcClass->getInterface()->getIdentifier() == S.getNSErrorIdent()) {
             if (numNormalPointers == 2 && numTypeSpecifierPointers < 2)
    -          return PointerDeclaratorKind::NSErrorPointerPointer;;
    +          return PointerDeclaratorKind::NSErrorPointerPointer;
           }
     
           break;
    diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
    index e16a9b3ee3b5..94a8f609f57c 100644
    --- a/lib/Serialization/ASTReader.cpp
    +++ b/lib/Serialization/ASTReader.cpp
    @@ -4918,6 +4918,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
             }
     
             CurrentModule->setASTFile(F.File);
    +        CurrentModule->PresumedModuleMapFile = F.ModuleMapPath;
           }
     
           CurrentModule->Kind = ModuleKind;
    @@ -5211,6 +5212,8 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
       HSOpts.ModuleCachePath = ReadString(Record, Idx);
       HSOpts.ModuleUserBuildPath = ReadString(Record, Idx);
       HSOpts.DisableModuleHash = Record[Idx++];
    +  HSOpts.ImplicitModuleMaps = Record[Idx++];
    +  HSOpts.ModuleMapFileHomeIsCwd = Record[Idx++];
       HSOpts.UseBuiltinIncludes = Record[Idx++];
       HSOpts.UseStandardSystemIncludes = Record[Idx++];
       HSOpts.UseStandardCXXIncludes = Record[Idx++];
    @@ -9750,13 +9753,13 @@ void ASTReader::diagnoseOdrViolations() {
           if (Diagnosed == true)
             continue;
     
    -      Diag(FirstRecord->getLocation(),
    -           diag::err_module_odr_violation_different_definitions)
    -          << FirstRecord << FirstModule.empty() << FirstModule;
    -
    -      Diag(SecondRecord->getLocation(),
    -           diag::note_module_odr_violation_different_definitions)
    -          << SecondModule;
    +      Diag(FirstDecl->getLocation(),
    +           diag::err_module_odr_violation_mismatch_decl_unknown)
    +          << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType
    +          << FirstDecl->getSourceRange();
    +      Diag(SecondDecl->getLocation(),
    +           diag::note_module_odr_violation_mismatch_decl_unknown)
    +          << SecondModule << FirstDiffType << SecondDecl->getSourceRange();
           Diagnosed = true;
         }
     
    diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
    index f3ee9078298e..9c467055fe55 100644
    --- a/lib/Serialization/ASTReaderDecl.cpp
    +++ b/lib/Serialization/ASTReaderDecl.cpp
    @@ -216,6 +216,30 @@ namespace clang {
               TypedefNameForLinkage(nullptr), HasPendingBody(false),
               IsDeclMarkedUsed(false) {}
     
    +    template  static
    +    void AddLazySpecializations(T *D,
    +                                SmallVectorImpl& IDs) {
    +      if (IDs.empty())
    +        return;
    +
    +      // FIXME: We should avoid this pattern of getting the ASTContext.
    +      ASTContext &C = D->getASTContext();
    +
    +      auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations;
    +
    +      if (auto &Old = LazySpecializations) {
    +        IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
    +        std::sort(IDs.begin(), IDs.end());
    +        IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
    +      }
    +
    +      auto *Result = new (C) serialization::DeclID[1 + IDs.size()];
    +      *Result = IDs.size();
    +      std::copy(IDs.begin(), IDs.end(), Result + 1);
    +
    +      LazySpecializations = Result;
    +    }
    +
         template 
         static Decl *getMostRecentDeclImpl(Redeclarable *D);
         static Decl *getMostRecentDeclImpl(...);
    @@ -244,7 +268,7 @@ namespace clang {
         void ReadFunctionDefinition(FunctionDecl *FD);
         void Visit(Decl *D);
     
    -    void UpdateDecl(Decl *D);
    +    void UpdateDecl(Decl *D, llvm::SmallVectorImpl&);
     
         static void setNextObjCCategory(ObjCCategoryDecl *Cat,
                                         ObjCCategoryDecl *Next) {
    @@ -1229,6 +1253,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
         VD->NonParmVarDeclBits.IsConstexpr = Record.readInt();
         VD->NonParmVarDeclBits.IsInitCapture = Record.readInt();
         VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt();
    +    VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt();
       }
       Linkage VarLinkage = Linkage(Record.readInt());
       VD->setCachedLinkage(VarLinkage);
    @@ -1951,21 +1976,6 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
       return Redecl;
     }
     
    -static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,
    -                             SmallVectorImpl &IDs) {
    -  assert(!IDs.empty() && "no IDs to add to list");
    -  if (Old) {
    -    IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
    -    std::sort(IDs.begin(), IDs.end());
    -    IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
    -  }
    -
    -  auto *Result = new (Context) DeclID[1 + IDs.size()];
    -  *Result = IDs.size();
    -  std::copy(IDs.begin(), IDs.end(), Result + 1);
    -  return Result;
    -}
    -
     void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
       RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
     
    @@ -1974,12 +1984,7 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
         // the specializations.
         SmallVector SpecIDs;
         ReadDeclIDList(SpecIDs);
    -
    -    if (!SpecIDs.empty()) {
    -      auto *CommonPtr = D->getCommonPtr();
    -      CommonPtr->LazySpecializations = newDeclIDList(
    -          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
    -    }
    +    ASTDeclReader::AddLazySpecializations(D, SpecIDs);
       }
     
       if (D->getTemplatedDecl()->TemplateOrInstantiation) {
    @@ -2006,12 +2011,7 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
         // the specializations.
         SmallVector SpecIDs;
         ReadDeclIDList(SpecIDs);
    -
    -    if (!SpecIDs.empty()) {
    -      auto *CommonPtr = D->getCommonPtr();
    -      CommonPtr->LazySpecializations = newDeclIDList(
    -          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
    -    }
    +    ASTDeclReader::AddLazySpecializations(D, SpecIDs);
       }
     }
     
    @@ -2117,12 +2117,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
         // This FunctionTemplateDecl owns a CommonPtr; read it.
         SmallVector SpecIDs;
         ReadDeclIDList(SpecIDs);
    -
    -    if (!SpecIDs.empty()) {
    -      auto *CommonPtr = D->getCommonPtr();
    -      CommonPtr->LazySpecializations = newDeclIDList(
    -          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
    -    }
    +    ASTDeclReader::AddLazySpecializations(D, SpecIDs);
       }
     }
     
    @@ -3666,6 +3661,9 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
       Decl *D = Record.D;
       ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
       DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
    +
    +  llvm::SmallVector PendingLazySpecializationIDs;
    +
       if (UpdI != DeclUpdateOffsets.end()) {
         auto UpdateOffsets = std::move(UpdI->second);
         DeclUpdateOffsets.erase(UpdI);
    @@ -3690,7 +3688,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
     
           ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID,
                                SourceLocation());
    -      Reader.UpdateDecl(D);
    +      Reader.UpdateDecl(D, PendingLazySpecializationIDs);
     
           // We might have made this declaration interesting. If so, remember that
           // we need to hand it off to the consumer.
    @@ -3702,6 +3700,17 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
           }
         }
       }
    +  // Add the lazy specializations to the template.
    +  assert((PendingLazySpecializationIDs.empty() || isa(D) ||
    +          isa(D) || isa(D)) &&
    +         "Must not have pending specializations");
    +  if (auto *CTD = dyn_cast(D))
    +    ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs);
    +  else if (auto *FTD = dyn_cast(D))
    +    ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs);
    +  else if (auto *VTD = dyn_cast(D))
    +    ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs);
    +  PendingLazySpecializationIDs.clear();
     
       // Load the pending visible updates for this decl context, if it has any.
       auto I = PendingVisibleUpdates.find(ID);
    @@ -3898,7 +3907,8 @@ static void forAllLaterRedecls(DeclT *D, Fn F) {
       }
     }
     
    -void ASTDeclReader::UpdateDecl(Decl *D) {
    +void ASTDeclReader::UpdateDecl(Decl *D,
    +   llvm::SmallVectorImpl &PendingLazySpecializationIDs) {
       while (Record.getIdx() < Record.size()) {
         switch ((DeclUpdateKind)Record.readInt()) {
         case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
    @@ -3914,8 +3924,8 @@ void ASTDeclReader::UpdateDecl(Decl *D) {
         }
     
         case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
    -      // It will be added to the template's specializations set when loaded.
    -      (void)Record.readDecl();
    +      // It will be added to the template's lazy specialization set.
    +      PendingLazySpecializationIDs.push_back(ReadDeclID());
           break;
     
         case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
    diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
    index 044a26433a93..dcacabec1225 100644
    --- a/lib/Serialization/ASTWriter.cpp
    +++ b/lib/Serialization/ASTWriter.cpp
    @@ -1601,6 +1601,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
       AddString(HSOpts.ModuleCachePath, Record);
       AddString(HSOpts.ModuleUserBuildPath, Record);
       Record.push_back(HSOpts.DisableModuleHash);
    +  Record.push_back(HSOpts.ImplicitModuleMaps);
    +  Record.push_back(HSOpts.ModuleMapFileHomeIsCwd);
       Record.push_back(HSOpts.UseBuiltinIncludes);
       Record.push_back(HSOpts.UseStandardSystemIncludes);
       Record.push_back(HSOpts.UseStandardCXXIncludes);
    diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
    index 8fa64aa1b9d3..2d648cb103cb 100644
    --- a/lib/Serialization/ASTWriterDecl.cpp
    +++ b/lib/Serialization/ASTWriterDecl.cpp
    @@ -915,6 +915,10 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
         Record.push_back(D->isConstexpr());
         Record.push_back(D->isInitCapture());
         Record.push_back(D->isPreviousDeclInSameBlockScope());
    +    if (const auto *IPD = dyn_cast(D))
    +      Record.push_back(static_cast(IPD->getParameterKind()));
    +    else
    +      Record.push_back(0);
       }
       Record.push_back(D->getLinkageInternal());
     
    @@ -1989,6 +1993,7 @@ void ASTWriter::WriteDeclAbbrevs() {
       Abv->Add(BitCodeAbbrevOp(0));                         // isConstexpr
       Abv->Add(BitCodeAbbrevOp(0));                         // isInitCapture
       Abv->Add(BitCodeAbbrevOp(0));                         // isPrevDeclInSameScope
    +  Abv->Add(BitCodeAbbrevOp(0));                         // ImplicitParamKind
       Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
       Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // IsInitICE (local)
       Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum)
    diff --git a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
    index 41999d252763..fa9a317683ba 100644
    --- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
    +++ b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
    @@ -326,7 +326,7 @@ NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
     
       // Retrieve the associated statement.
       const Stmt *S = TrackedNullab->getNullabilitySource();
    -  if (!S) {
    +  if (!S || S->getLocStart().isInvalid()) {
         S = PathDiagnosticLocation::getStmt(N);
       }
     
    diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
    index 2c3169c0f8dd..d8fca00681b4 100644
    --- a/lib/StaticAnalyzer/Core/BugReporter.cpp
    +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
    @@ -1671,9 +1671,15 @@ static bool GenerateAlternateExtensivePathDiagnostic(
             // Add an edge to the start of the function.
             const StackFrameContext *CalleeLC = CE->getCalleeContext();
             const Decl *D = CalleeLC->getDecl();
    -        addEdgeToPath(PD.getActivePath(), PrevLoc,
    -                      PathDiagnosticLocation::createBegin(D, SM),
    -                      CalleeLC);
    +        // Add the edge only when the callee has body. We jump to the beginning
    +        // of the *declaration*, however we expect it to be followed by the
    +        // body. This isn't the case for autosynthesized property accessors in
    +        // Objective-C. No need for a similar extra check for CallExit points
    +        // because the exit edge comes from a statement (i.e. return),
    +        // not from declaration.
    +        if (D->hasBody())
    +          addEdgeToPath(PD.getActivePath(), PrevLoc,
    +                        PathDiagnosticLocation::createBegin(D, SM), CalleeLC);
     
             // Did we visit an entire call?
             bool VisitedEntireCall = PD.isWithinCall();
    diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
    index 7c5ee3b25944..6aa6da560e60 100644
    --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
    +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
    @@ -694,7 +694,30 @@ PathDiagnosticLocation::create(const ProgramPoint& P,
       return PathDiagnosticLocation(S, SMng, P.getLocationContext());
     }
     
    +static const LocationContext *
    +findTopAutosynthesizedParentContext(const LocationContext *LC) {
    +  assert(LC->getAnalysisDeclContext()->isBodyAutosynthesized());
    +  const LocationContext *ParentLC = LC->getParent();
    +  assert(ParentLC && "We don't start analysis from autosynthesized code");
    +  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
    +    LC = ParentLC;
    +    ParentLC = LC->getParent();
    +    assert(ParentLC && "We don't start analysis from autosynthesized code");
    +  }
    +  return LC;
    +}
    +
     const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
    +  // We cannot place diagnostics on autosynthesized code.
    +  // Put them onto the call site through which we jumped into autosynthesized
    +  // code for the first time.
    +  const LocationContext *LC = N->getLocationContext();
    +  if (LC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
    +    // It must be a stack frame because we only autosynthesize functions.
    +    return cast(findTopAutosynthesizedParentContext(LC))
    +        ->getCallSite();
    +  }
    +  // Otherwise, see if the node's program point directly points to a statement.
       ProgramPoint P = N->getLocation();
       if (Optional SP = P.getAs())
         return SP->getStmt();
    @@ -912,6 +935,17 @@ void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
     
       callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
       callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
    +
    +  // Autosynthesized property accessors are special because we'd never
    +  // pop back up to non-autosynthesized code until we leave them.
    +  // This is not generally true for autosynthesized callees, which may call
    +  // non-autosynthesized callbacks.
    +  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
    +  // defaults to false.
    +  if (const ObjCMethodDecl *MD = dyn_cast(Callee))
    +    IsCalleeAnAutosynthesizedPropertyAccessor = (
    +        MD->isPropertyAccessor() &&
    +        CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
     }
     
     static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
    @@ -986,7 +1020,11 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
     
     std::shared_ptr
     PathDiagnosticCallPiece::getCallEnterEvent() const {
    -  if (!Callee)
    +  // We do not produce call enters and call exits for autosynthesized property
    +  // accessors. We do generally produce them for other functions coming from
    +  // the body farm because they may call callbacks that bring us back into
    +  // visible code.
    +  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
         return nullptr;
     
       SmallString<256> buf;
    @@ -1020,7 +1058,11 @@ PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
     
     std::shared_ptr
     PathDiagnosticCallPiece::getCallExitEvent() const {
    -  if (NoExit)
    +  // We do not produce call enters and call exits for autosynthesized property
    +  // accessors. We do generally produce them for other functions coming from
    +  // the body farm because they may call callbacks that bring us back into
    +  // visible code.
    +  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
         return nullptr;
     
       SmallString<256> buf;
    diff --git a/test/Analysis/nullability-notes.m b/test/Analysis/nullability-notes.m
    new file mode 100644
    index 000000000000..c93aa02c4200
    --- /dev/null
    +++ b/test/Analysis/nullability-notes.m
    @@ -0,0 +1,204 @@
    +// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=text -verify %s
    +// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=plist -analyzer-config path-diagnostics-alternate=true -o %t.plist %s
    +// RUN: FileCheck --input-file=%t.plist %s
    +
    +#include "Inputs/system-header-simulator-for-nullability.h"
    +
    +void takesNonnull(NSObject *_Nonnull y);
    +
    +@interface ClassWithProperties: NSObject
    +@property(copy, nullable) NSObject *x; // plist check ensures no control flow piece from here to 'self.x'.
    +-(void) method;
    +@end;
    +@implementation ClassWithProperties
    +-(void) method {
    +  // no-crash
    +  NSObject *x = self.x; // expected-note{{Nullability 'nullable' is inferred}}
    +  takesNonnull(x); // expected-warning{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
    +                   // expected-note@-1{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
    +}
    +@end
    +
    +// CHECK:  diagnostics
    +// CHECK-NEXT:  
    +// CHECK-NEXT:   
    +// CHECK-NEXT:    path
    +// CHECK-NEXT:    
    +// CHECK-NEXT:     
    +// CHECK-NEXT:      kindcontrol
    +// CHECK-NEXT:      edges
    +// CHECK-NEXT:       
    +// CHECK-NEXT:        
    +// CHECK-NEXT:         start
    +// CHECK-NEXT:          
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col3
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col10
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:          
    +// CHECK-NEXT:         end
    +// CHECK-NEXT:          
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col22
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col22
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:          
    +// CHECK-NEXT:        
    +// CHECK-NEXT:       
    +// CHECK-NEXT:     
    +// CHECK-NEXT:     
    +// CHECK-NEXT:      kindevent
    +// CHECK-NEXT:      location
    +// CHECK-NEXT:      
    +// CHECK-NEXT:       line16
    +// CHECK-NEXT:       col22
    +// CHECK-NEXT:       file0
    +// CHECK-NEXT:      
    +// CHECK-NEXT:      ranges
    +// CHECK-NEXT:      
    +// CHECK-NEXT:        
    +// CHECK-NEXT:         
    +// CHECK-NEXT:          line16
    +// CHECK-NEXT:          col22
    +// CHECK-NEXT:          file0
    +// CHECK-NEXT:         
    +// CHECK-NEXT:         
    +// CHECK-NEXT:          line16
    +// CHECK-NEXT:          col22
    +// CHECK-NEXT:          file0
    +// CHECK-NEXT:         
    +// CHECK-NEXT:        
    +// CHECK-NEXT:      
    +// CHECK-NEXT:      depth1
    +// CHECK-NEXT:      extended_message
    +// CHECK-NEXT:      Nullability 'nullable' is inferred
    +// CHECK-NEXT:      message
    +// CHECK-NEXT:      Nullability 'nullable' is inferred
    +// CHECK-NEXT:     
    +// CHECK-NEXT:     
    +// CHECK-NEXT:      kindcontrol
    +// CHECK-NEXT:      edges
    +// CHECK-NEXT:       
    +// CHECK-NEXT:        
    +// CHECK-NEXT:         start
    +// CHECK-NEXT:          
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col22
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col22
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:          
    +// CHECK-NEXT:         end
    +// CHECK-NEXT:          
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col3
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col10
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:          
    +// CHECK-NEXT:        
    +// CHECK-NEXT:       
    +// CHECK-NEXT:     
    +// CHECK-NEXT:     
    +// CHECK-NEXT:      kindcontrol
    +// CHECK-NEXT:      edges
    +// CHECK-NEXT:       
    +// CHECK-NEXT:        
    +// CHECK-NEXT:         start
    +// CHECK-NEXT:          
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col3
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line16
    +// CHECK-NEXT:            col10
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:          
    +// CHECK-NEXT:         end
    +// CHECK-NEXT:          
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line17
    +// CHECK-NEXT:            col3
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:           
    +// CHECK-NEXT:            line17
    +// CHECK-NEXT:            col14
    +// CHECK-NEXT:            file0
    +// CHECK-NEXT:           
    +// CHECK-NEXT:          
    +// CHECK-NEXT:        
    +// CHECK-NEXT:       
    +// CHECK-NEXT:     
    +// CHECK-NEXT:     
    +// CHECK-NEXT:      kindevent
    +// CHECK-NEXT:      location
    +// CHECK-NEXT:      
    +// CHECK-NEXT:       line17
    +// CHECK-NEXT:       col3
    +// CHECK-NEXT:       file0
    +// CHECK-NEXT:      
    +// CHECK-NEXT:      ranges
    +// CHECK-NEXT:      
    +// CHECK-NEXT:        
    +// CHECK-NEXT:         
    +// CHECK-NEXT:          line17
    +// CHECK-NEXT:          col16
    +// CHECK-NEXT:          file0
    +// CHECK-NEXT:         
    +// CHECK-NEXT:         
    +// CHECK-NEXT:          line17
    +// CHECK-NEXT:          col16
    +// CHECK-NEXT:          file0
    +// CHECK-NEXT:         
    +// CHECK-NEXT:        
    +// CHECK-NEXT:      
    +// CHECK-NEXT:      depth0
    +// CHECK-NEXT:      extended_message
    +// CHECK-NEXT:      Nullable pointer is passed to a callee that requires a non-null 1st parameter
    +// CHECK-NEXT:      message
    +// CHECK-NEXT:      Nullable pointer is passed to a callee that requires a non-null 1st parameter
    +// CHECK-NEXT:     
    +// CHECK-NEXT:    
    +// CHECK-NEXT:    descriptionNullable pointer is passed to a callee that requires a non-null 1st parameter
    +// CHECK-NEXT:    categoryMemory error
    +// CHECK-NEXT:    typeNullability
    +// CHECK-NEXT:    check_namenullability.NullPassedToNonnull
    +// CHECK-NEXT:    
    +// CHECK-NEXT:    issue_hash_content_of_line_in_contextb6bc8126de8e6eb3375483a656fe858d
    +// CHECK-NEXT:   issue_context_kindObjective-C method
    +// CHECK-NEXT:   issue_contextmethod
    +// CHECK-NEXT:   issue_hash_function_offset3
    +// CHECK-NEXT:   location
    +// CHECK-NEXT:   
    +// CHECK-NEXT:    line17
    +// CHECK-NEXT:    col3
    +// CHECK-NEXT:    file0
    +// CHECK-NEXT:   
    +// CHECK-NEXT:   
    +// CHECK-NEXT:  
    diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
    index 12237a39ab54..6e150ce5a554 100644
    --- a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
    +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
    @@ -4,3 +4,31 @@ void f0() { // expected-note {{previous definition is here}}
     }
     
     inline void f0(); // expected-error {{inline declaration of 'f0' follows non-inline definition}}
    +
    +void func_01() {} // expected-note{{previous definition is here}}
    +struct C01 {
    +  friend void func_01() {} // expected-error{{redefinition of 'func_01'}}
    +};
    +
    +void func_02() {} // expected-note{{previous definition is here}}
    +struct C02 {
    +  friend inline void func_02(); // expected-error{{inline declaration of 'func_02' follows non-inline definition}}
    +};
    +
    +void func_03() {} // expected-note{{previous definition is here}}
    +struct C03 {
    +  friend inline void func_03() {} // expected-error{{inline declaration of 'func_03' follows non-inline definition}}
    +};
    +
    +void func_04() {} // expected-note{{previous definition is here}}
    +inline void func_04() {} // expected-error{{inline declaration of 'func_04' follows non-inline definition}}
    +
    +void func_06() {} // expected-note{{previous definition is here}}
    +template struct C06 {
    +  friend inline void func_06() {} // expected-error{{inline declaration of 'func_06' follows non-inline definition}}
    +};
    +
    +void func_07() {} // expected-note{{previous definition is here}}
    +template struct C07 {
    +  friend inline void func_07(); // expected-error{{inline declaration of 'func_07' follows non-inline definition}}
    +};
    diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
    index a5ac85cb6f3a..6014268a1860 100644
    --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
    +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
    @@ -73,3 +73,36 @@ void Test ()
     }
     
     } // namespace
    +
    +namespace pr12724 {
    +
    +void func_01(bool param = true);
    +class C01 {
    +public:
    +  friend void func_01(bool param);
    +};
    +
    +void func_02(bool param = true);
    +template
    +class C02 {
    +public:
    +  friend void func_02(bool param);
    +};
    +C02 c02;
    +
    +void func_03(bool param);
    +template
    +class C03 {
    +public:
    +  friend void func_03(bool param);
    +};
    +void func_03(bool param = true);
    +C03 c03;
    +
    +void main() {
    +  func_01();
    +  func_02();
    +  func_03();
    +}
    +
    +} // namespace pr12724
    diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp
    index 56ff1237480f..64ba3be2a618 100644
    --- a/test/CXX/drs/dr13xx.cpp
    +++ b/test/CXX/drs/dr13xx.cpp
    @@ -192,7 +192,7 @@ namespace dr1330 { // dr1330: 4 c++11
       static_assert(!noexcept(B().g()), "");
     #endif
     
    -  template int f() throw(typename T::error) { return 0; } // expected-error 1-4{{prior to '::'}} expected-note 0-1{{instantiation of}}
    +  template int f() throw(typename T::error) { return 0; } // expected-error 1-4{{prior to '::'}} expected-note 0-1{{prior to '::'}} expected-note 0-1{{requested here}}
     #if __cplusplus > 201402L
         // expected-error@-2 0-1{{C++1z}} expected-note@-2 0-1{{noexcept}}
     #endif
    @@ -203,7 +203,16 @@ namespace dr1330 { // dr1330: 4 c++11
       decltype(f()) f2; // expected-note {{instantiation of}}
       bool f3 = noexcept(f()); // expected-note {{instantiation of}}
     #endif
    -  template int f(); // expected-note {{instantiation of}}
    +  // In C++1z onwards, substituting explicit template arguments into the
    +  // function type substitutes into the exception specification (because it's
    +  // part of the type). In earlier languages, we don't notice there's a problem
    +  // until we've already started to instantiate.
    +  template int f();
    +#if __cplusplus >= 201703L
    +  // expected-error@-2 {{does not refer to a function template}}
    +#else
    +  // expected-note@-4 {{instantiation of}}
    +#endif
     
       template struct C {
         C() throw(typename T::type); // expected-error 1-2{{prior to '::'}}
    diff --git a/test/CXX/temp/temp.decls/temp.mem/p5.cpp b/test/CXX/temp/temp.decls/temp.mem/p5.cpp
    index 1e061fa33d3a..a41ea6b5e109 100644
    --- a/test/CXX/temp/temp.decls/temp.mem/p5.cpp
    +++ b/test/CXX/temp/temp.decls/temp.mem/p5.cpp
    @@ -77,3 +77,16 @@ void test_X0(X0 x0, const X0 &x0c) {
       x0.operator float *();
       x0c.operator const char*();
     }
    +
    +namespace PR14211 {
    +template  struct X {
    +  void foo(U){}
    +  template  void foo(T){}
    +
    +  template  void bar(T){}
    +  void bar(U){}
    +};
    +
    +template void X::foo(int);
    +template void X::bar(int);
    +}
    diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp
    index e7b665a34137..357ea664037d 100644
    --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp
    +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp
    @@ -46,10 +46,11 @@ namespace noexcept_conversion {
       template  int h(T *, T *); // expected-note {{deduced conflicting types for parameter 'T' ('void () noexcept' vs. 'void ()')}}
       int x = h(g1, g2); // expected-error {{no matching function}}
     
    -  // FIXME: It seems like a defect that B is not deducible here.
    -  template int i(void () noexcept(B)); // expected-note 2{{couldn't infer template argument 'B'}}
    -  int i1 = i(g1); // expected-error {{no matching function}}
    -  int i2 = i(g2); // expected-error {{no matching function}}
    +  // We consider it a defect that deduction does not support the following.
    +  // FIXME: Check that the defect is resolved as we expect.
    +  template int i(void () noexcept(B));
    +  int i1 = i(g1);
    +  int i2 = i(g2);
     }
     #else
     // expected-no-diagnostics
    diff --git a/test/CodeGen/arm-long-calls.c b/test/CodeGen/arm-long-calls.c
    index fdd7babe9fe6..cff2d6607113 100644
    --- a/test/CodeGen/arm-long-calls.c
    +++ b/test/CodeGen/arm-long-calls.c
    @@ -1,7 +1,7 @@
     // RUN: %clang_cc1 -triple thumbv7-apple-ios5  -target-feature +long-calls -emit-llvm -o - %s | FileCheck -check-prefix=LONGCALL %s
     // RUN: %clang_cc1 -triple thumbv7-apple-ios5 -emit-llvm -o - %s | FileCheck -check-prefix=NOLONGCALL %s
     
    -// LONGCALL: attributes #0 = { {{.*}} "target-features"="+long-calls"
    -// NOLONGCALL-NOT: attributes #0 = { {{.*}} "target-features"="+long-calls"
    +// LONGCALL: attributes #0 = { {{.*}} "target-features"="+long-calls,+thumb-mode"
    +// NOLONGCALL-NOT: attributes #0 = { {{.*}} "target-features"="+long-calls,+thumb-mode"
     
     int foo1(int a) { return a; }
    diff --git a/test/CodeGen/arm-no-movt.c b/test/CodeGen/arm-no-movt.c
    index 0773941fb384..f61f2248643e 100644
    --- a/test/CodeGen/arm-no-movt.c
    +++ b/test/CodeGen/arm-no-movt.c
    @@ -1,7 +1,7 @@
     // RUN: %clang_cc1 -triple thumbv7-apple-ios5  -target-feature +no-movt -emit-llvm -o - %s | FileCheck -check-prefix=NO-MOVT %s
     // RUN: %clang_cc1 -triple thumbv7-apple-ios5 -emit-llvm -o - %s | FileCheck -check-prefix=MOVT %s
     
    -// NO-MOVT: attributes #0 = { {{.*}} "target-features"="+no-movt"
    -// MOVT-NOT: attributes #0 = { {{.*}} "target-features"="+no-movt"
    +// NO-MOVT: attributes #0 = { {{.*}} "target-features"="+no-movt,+thumb-mode"
    +// MOVT-NOT: attributes #0 = { {{.*}} "target-features"="+no-movt,+thumb-mode"
     
     int foo1(int a) { return a; }
    diff --git a/test/CodeGen/arm-target-attr.c b/test/CodeGen/arm-target-attr.c
    new file mode 100644
    index 000000000000..42fe8d15aaf4
    --- /dev/null
    +++ b/test/CodeGen/arm-target-attr.c
    @@ -0,0 +1,19 @@
    +// RUN: %clang_cc1 -triple thumb-apple-darwin -emit-llvm -o - %s | FileCheck --check-prefix CHECKPOS %s
    +// RUN: %clang_cc1 -triple thumb-apple-darwin -emit-llvm -o - %s | FileCheck --check-prefix CHECKNEG %s
    +// RUN: %clang_cc1 -triple arm-apple-darwin -emit-llvm -o - %s | FileCheck --check-prefix CHECKPOS %s
    +// RUN: %clang_cc1 -triple arm-apple-darwin -emit-llvm -o - %s | FileCheck --check-prefix CHECKNEG %s
    +
    +__attribute__((target("arm"))) void test_target_arm() {
    +  // CHECKPOS: define void @test_target_arm() [[ARM_ATTRS:#[0-9]+]]
    +  // CHECKNEG: define void @test_target_arm() [[ARM_ATTRS:#[0-9]+]]
    +}
    +
    +__attribute__((target("thumb"))) void test_target_thumb() {
    +  // CHECKPOS: define void @test_target_thumb() [[THUMB_ATTRS:#[0-9]+]]
    +  // CHECKNEG: define void @test_target_thumb() [[THUMB_ATTRS:#[0-9]+]]
    +}
    +
    +// CHECKPOS: attributes [[ARM_ATTRS]] = { {{.*}} "target-features"="{{.*}}-thumb-mode{{.*}}"
    +// CHECKPOS: attributes [[THUMB_ATTRS]] = { {{.*}} "target-features"="{{.*}}+thumb-mode{{.*}}"
    +// CHECKNEG-NOT: attributes [[ARM_ATTRS]] = { {{.*}} "target-features"="{{.*}}+thumb-mode{{.*}}"
    +// CHECKNEG-NOT: attributes [[THUMB_ATTRS]] = { {{.*}} "target-features"="{{.*}}-thumb-mode{{.*}}"
    diff --git a/test/CodeGen/arm-target-features.c b/test/CodeGen/arm-target-features.c
    index 7437fb0e4ed2..e5591a28ad1a 100644
    --- a/test/CodeGen/arm-target-features.c
    +++ b/test/CodeGen/arm-target-features.c
    @@ -1,65 +1,63 @@
     // REQUIRES: arm-registered-target
     
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a8 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3
    -// CHECK-VFP3: "target-features"="+dsp,+neon,+vfp3"
    -
    -
    -// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-a9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-FP16
    -// CHECK-VFP3-FP16: "target-features"="+dsp,+fp16,+neon,+vfp3"
    +// CHECK-VFP3: "target-features"="+dsp,+neon,+thumb-mode
     
     
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4
    -// CHECK-VFP4: "target-features"="+dsp,+neon,+vfp4"
    +// CHECK-VFP4: "target-features"="+dsp,+neon,+thumb-mode,+vfp4"
     
     
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-a12 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
    -// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -target-cpu cortex-a15 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
    -// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -target-cpu cortex-a17 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
     // RUN: %clang_cc1 -triple thumbv7s-linux-gnueabi -target-cpu swift -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu krait -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV
    -// CHECK-VFP4-DIV: "target-features"="+dsp,+hwdiv,+hwdiv-arm,+neon,+vfp4"
    +// CHECK-VFP4-DIV: "target-features"="+dsp,+hwdiv,+hwdiv-arm,+neon,+thumb-mode,+vfp4"
     
    +// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -target-cpu cortex-a15 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV-ARM
    +// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -target-cpu cortex-a17 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-DIV-ARM
    +// CHECK-VFP4-DIV-ARM: "target-features"="+dsp,+hwdiv,+hwdiv-arm,+neon,+vfp4,-thumb-mode"
     
     // RUN: %clang_cc1 -triple thumbv7s-apple-ios7.0 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
     // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a32 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
     // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a35 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
    -// RUN: %clang_cc1 -triple armv8-linux-gnueabi -target-cpu cortex-a53 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
     // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a57 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
     // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a72 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
     // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a73 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
     // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
     // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m2 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
     // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
    -// CHECK-BASIC-V8: "target-features"="+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon"
    +// CHECK-BASIC-V8: "target-features"="+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,+thumb-mode"
     
    +// RUN: %clang_cc1 -triple armv8-linux-gnueabi -target-cpu cortex-a53 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8-ARM
    +// CHECK-BASIC-V8-ARM: "target-features"="+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,-thumb-mode"
     
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-DIV
    -// CHECK-VFP3-D16-DIV: "target-features"="+d16,+dsp,+hwdiv,+hwdiv-arm,+vfp3"
    +// CHECK-VFP3-D16-DIV: "target-features"="+d16,+dsp,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp3"
     
     
     // RUN: %clang_cc1 -triple armv7-linux-gnueabi -target-cpu cortex-r4f -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-THUMB-DIV
    -// CHECK-VFP3-D16-THUMB-DIV: "target-features"="+d16,+dsp,+hwdiv,+vfp3"
    +// CHECK-VFP3-D16-THUMB-DIV: "target-features"="+d16,+dsp,+hwdiv,+vfp3,-thumb-mode"
     
     
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-FP16-DIV
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r8 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-FP16-DIV
    -// CHECK-VFP3-D16-FP16-DIV: "target-features"="+d16,+dsp,+fp16,+hwdiv,+hwdiv-arm,+vfp3"
    +// CHECK-VFP3-D16-FP16-DIV: "target-features"="+d16,+dsp,+fp16,+hwdiv,+hwdiv-arm,+thumb-mode,+vfp3"
     
     
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4-D16-SP-THUMB-DIV
    -// CHECK-VFP4-D16-SP-THUMB-DIV: "target-features"="+d16,+dsp,+fp-only-sp,+hwdiv,+vfp4"
    +// CHECK-VFP4-D16-SP-THUMB-DIV: "target-features"="+d16,+dsp,+fp-only-sp,+hwdiv,+thumb-mode,+vfp4"
     
     
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP5-D16-THUMB-DIV
    -// CHECK-VFP5-D16-THUMB-DIV: "target-features"="+d16,+dsp,+fp-armv8,+hwdiv"
    +// CHECK-VFP5-D16-THUMB-DIV: "target-features"="+d16,+dsp,+fp-armv8,+hwdiv,+thumb-mode"
     
     
     // RUN: %clang_cc1 -triple armv7-linux-gnueabi -target-cpu cortex-r4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV
    -// CHECK-THUMB-DIV: "target-features"="+dsp,+hwdiv"
    +// CHECK-THUMB-DIV: "target-features"="+dsp,+hwdiv,-thumb-mode"
     
     // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV-M3
    -// CHECK-THUMB-DIV-M3: "target-features"="+hwdiv"
    +// CHECK-THUMB-DIV-M3: "target-features"="+hwdiv,+thumb-mode"
     
     
     void foo() {}
    diff --git a/test/CodeGen/arm-thumb-mode-target-feature.c b/test/CodeGen/arm-thumb-mode-target-feature.c
    new file mode 100644
    index 000000000000..5c41d0b16fda
    --- /dev/null
    +++ b/test/CodeGen/arm-thumb-mode-target-feature.c
    @@ -0,0 +1,33 @@
    +// REQUIRES: arm-registered-target
    +
    +// RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -emit-llvm -o - %s | FileCheck --check-prefix THUMB %s
    +// RUN: %clang_cc1 -triple thumbv7eb-linux-gnueabihf -emit-llvm -o - %s | FileCheck --check-prefix THUMB %s
    +// RUN: %clang -target armv7-linux-gnueabihf -mthumb -S -emit-llvm -o - %s | FileCheck --check-prefix THUMB-CLANG %s
    +// RUN: %clang_cc1 -triple armv7-linux-gnueabihf -emit-llvm -o - %s | FileCheck --check-prefix ARM %s
    +// RUN: %clang_cc1 -triple armv7eb-linux-gnueabihf -emit-llvm -o - %s | FileCheck --check-prefix ARM %s
    +
    +void t1() {}
    +
    + __attribute__((target("no-thumb-mode")))
    +void t2() {}
    +
    + __attribute__((target("thumb-mode")))
    +void t3() {}
    +
    +// THUMB: void @t1() [[ThumbAttr:#[0-7]]]
    +// THUMB: void @t2() [[NoThumbAttr:#[0-7]]]
    +// THUMB: void @t3() [[ThumbAttr:#[0-7]]]
    +// THUMB: attributes [[ThumbAttr]] = { {{.*}} "target-features"="+thumb-mode"
    +// THUMB: attributes [[NoThumbAttr]] = { {{.*}} "target-features"="-thumb-mode"
    +//
    +// THUMB-CLANG: void @t1() [[ThumbAttr:#[0-7]]]
    +// THUMB-CLANG: void @t2() [[NoThumbAttr:#[0-7]]]
    +// THUMB-CLANG: void @t3() [[ThumbAttr:#[0-7]]]
    +// THUMB-CLANG: attributes [[ThumbAttr]] = { {{.*}} "target-features"="{{.*}}+thumb-mode
    +// THUMB-CLANG: attributes [[NoThumbAttr]] = { {{.*}} "target-features"="{{.*}}-thumb-mode
    +
    +// ARM: void @t1() [[NoThumbAtr:#[0-7]]]
    +// ARM: void @t2() [[NoThumbAttr:#[0-7]]]
    +// ARM: void @t3() [[ThumbAttr:#[0-7]]]
    +// ARM: attributes [[NoThumbAttr]] = { {{.*}} "target-features"="-thumb-mode"
    +// ARM: attributes [[ThumbAttr]] = { {{.*}} "target-features"="+thumb-mode"
    diff --git a/test/CodeGen/captured-statements.c b/test/CodeGen/captured-statements.c
    index 607ec8e55f48..68ff2517be1e 100644
    --- a/test/CodeGen/captured-statements.c
    +++ b/test/CodeGen/captured-statements.c
    @@ -1,4 +1,4 @@
    -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o %t
    +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o %t -debug-info-kind=limited
     // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-GLOBALS
     // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1
     // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2
    @@ -98,3 +98,8 @@ void dont_capture_global() {
     // CHECK-GLOBALS:   load i32, i32* @global
     // CHECK-GLOBALS:   load i32, i32* @
     // CHECK-GLOBALS:   load i32, i32* @e
    +
    +// CHECK-GLOBALS-NOT: DIFlagObjectPointer
    +// CHECK-1-NOT: DIFlagObjectPointer
    +// CHECK-2-NOT: DIFlagObjectPointer
    +// CHECK-3-NOT: DIFlagObjectPointer
    diff --git a/test/CodeGen/mips-madd4.c b/test/CodeGen/mips-madd4.c
    new file mode 100644
    index 000000000000..bc7bb593f95d
    --- /dev/null
    +++ b/test/CodeGen/mips-madd4.c
    @@ -0,0 +1,87 @@
    +// REQUIRES: mips-registered-target
    +// RUN: %clang --target=mips64-unknown-linux -S -mmadd4    %s -o -| FileCheck %s -check-prefix=MADD4
    +// RUN: %clang --target=mips64-unknown-linux -S -mno-madd4 %s -o -| FileCheck %s -check-prefix=NOMADD4
    +// RUN: %clang --target=mips64-unknown-linux -S -mmadd4    -fno-honor-nans %s -o -| FileCheck %s -check-prefix=MADD4-NONAN
    +// RUN: %clang --target=mips64-unknown-linux -S -mno-madd4 -fno-honor-nans %s -o -| FileCheck %s -check-prefix=NOMADD4-NONAN
    + 
    +float madd_s (float f, float g, float h)
    +{
    +  return (f * g) + h;
    +}
    +// MADD4:   madd.s
    +// NOMADD4: mul.s
    +// NOMADD4: add.s
    +
    +float msub_s (float f, float g, float h)
    +{
    +  return (f * g) - h;
    +}
    +// MADD4:   msub.s
    +// NOMADD4: mul.s
    +// NOMADD4: sub.s
    +
    +double madd_d (double f, double g, double h)
    +{
    +  return (f * g) + h;
    +}
    +// MADD4:   madd.d
    +// NOMADD4: mul.d
    +// NOMADD4: add.d
    +
    +double msub_d (double f, double g, double h)
    +{
    +  return (f * g) - h;
    +}
    +// MADD4:   msub.d
    +// NOMADD4: mul.d
    +// NOMADD4: sub.d
    +
    +
    +float nmadd_s (float f, float g, float h)
    +{
    +  // FIXME: Zero has been explicitly placed to force generation of a positive
    +  // zero in IR until pattern used to match this instruction is changed to
    +  // comply with negative zero as well.
    +  return 0-((f * g) + h);
    +}
    +// MADD4-NONAN:   nmadd.s
    +// NOMADD4-NONAN: mul.s
    +// NOMADD4-NONAN: add.s
    +// NOMADD4-NONAN: sub.s
    +
    +float nmsub_s (float f, float g, float h)
    +{
    +  // FIXME: Zero has been explicitly placed to force generation of a positive
    +  // zero in IR until pattern used to match this instruction is changed to
    +  // comply with negative zero as well.
    +  return 0-((f * g) - h);
    +}
    +// MADD4-NONAN:   nmsub.s
    +// NOMADD4-NONAN: mul.s
    +// NOMADD4-NONAN: sub.s
    +// NOMADD4-NONAN: sub.s
    +
    +double nmadd_d (double f, double g, double h)
    +{
    +  // FIXME: Zero has been explicitly placed to force generation of a positive
    +  // zero in IR until pattern used to match this instruction is changed to
    +  // comply with negative zero as well.
    +  return 0-((f * g) + h);
    +}
    +// MADD4-NONAN:   nmadd.d
    +// NOMADD4-NONAN: mul.d
    +// NOMADD4-NONAN: add.d
    +// NOMADD4-NONAN: sub.d
    +
    +double nmsub_d (double f, double g, double h)
    +{
    +  // FIXME: Zero has been explicitly placed to force generation of a positive
    +  // zero in IR until pattern used to match this instruction is changed to
    +  // comply with negative zero as well.
    +  return 0-((f * g) - h);
    +}
    +// MADD4-NONAN:   nmsub.d
    +// NOMADD4-NONAN: mul.d
    +// NOMADD4-NONAN: sub.d
    +// NOMADD4-NONAN: sub.d
    +
    diff --git a/test/CodeGen/neon-aapcs-align.c b/test/CodeGen/neon-aapcs-align.c
    new file mode 100644
    index 000000000000..4b7e5ff4d387
    --- /dev/null
    +++ b/test/CodeGen/neon-aapcs-align.c
    @@ -0,0 +1,17 @@
    +// RUN: %clang_cc1 -triple armv7a-none-eabi -target-feature +neon -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=AAPCS
    +// RUN: %clang_cc1 -triple armv7a-none-gnueabi -target-feature +neon -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=AAPCS
    +// RUN: %clang_cc1 -triple armv7a-none-freebsd -target-feature +neon -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=AAPCS
    +
    +// RUN: %clang_cc1 -triple armv7a-apple-ios -target-feature +neon -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=DEFAULT
    +// RUN: %clang_cc1 -triple armv7a-none-android -target-feature +neon -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=DEFAULT
    +// RUN: %clang_cc1 -triple armv7a-none-androideabi -target-feature +neon -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=DEFAULT
    +
    +#include 
    +// Neon types have 64-bit alignment
    +int32x4_t gl_b;
    +void t3(int32x4_t *src) {
    +// CHECK: @t3
    +  gl_b = *src;
    +// AAPCS: store <4 x i32> {{%.*}}, <4 x i32>* @gl_b, align 8
    +// DEFAULT: store <4 x i32> {{%.*}}, <4 x i32>* @gl_b, align 16
    +}
    diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp
    index 4b95503ad7b3..95e73e548399 100644
    --- a/test/CodeGenCXX/captured-statements.cpp
    +++ b/test/CodeGenCXX/captured-statements.cpp
    @@ -1,4 +1,4 @@
    -// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm %s -o %t
    +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm %s -o %t -debug-info-kind=limited
     // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1
     // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2
     // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3
    @@ -194,3 +194,18 @@ inline int test_captured_linkage() {
     void call_test_captured_linkage() {
       test_captured_linkage();
     }
    +
    +// CHECK-1-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
    +// CHECK-1-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
    +// CHECK-2-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
    +// CHECK-2-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
    +// CHECK-3-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
    +// CHECK-3-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
    +// CHECK-4-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
    +// CHECK-4-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
    +// CHECK-5-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
    +// CHECK-5-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
    +// CHECK-6-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
    +// CHECK-6-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
    +// CHECK-7-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
    +// CHECK-7-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
    diff --git a/test/CodeGenCXX/clang-sections-tentative.c b/test/CodeGenCXX/clang-sections-tentative.c
    new file mode 100644
    index 000000000000..e663079b9aa4
    --- /dev/null
    +++ b/test/CodeGenCXX/clang-sections-tentative.c
    @@ -0,0 +1,41 @@
    +// RUN: %clang_cc1 -x c -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
    +
    +// Test that section attributes are attached to C tentative definitions as per
    +// '#pragma clang section' directives.
    +
    +#pragma clang section bss = ".bss.1"
    +int x; // bss.1
    +
    +#pragma clang section bss = ""
    +int x; // stays in .bss.1
    +int y; // not assigned a section attribute
    +int z; // not assigned a section attribute
    +
    +#pragma clang section bss = ".bss.2"
    +int x; // stays in .bss.1
    +int y; // .bss.2
    +
    +// Test the same for `const` declarations.
    +#pragma clang section rodata = ".rodata.1"
    +const int cx; // rodata.1
    +
    +#pragma clang section rodata = ""
    +const int cx; // stays in .rodata.1
    +const int cy; // not assigned a section attribute
    +const int cz; // not assigned a rodata section attribute
    +
    +#pragma clang section rodata = ".rodata.2"
    +const int cx; // stays in .rodata.1
    +const int cy; // .rodata.2
    +
    +// CHECK: @x = global i32 0, align 4 #0
    +// CHECK: @y = global i32 0, align 4 #1
    +// CHECK: @z = common global i32 0, align 4
    +// CHECK: @cx = constant i32 0, align 4 #2
    +// CHECK: @cy = constant i32 0, align 4 #3
    +// CHECK: @cz = constant i32 0, align 4 #1
    +
    +// CHECK: attributes #0 = { "bss-section"=".bss.1" }
    +// CHECK: attributes #1 = { "bss-section"=".bss.2" }
    +// CHECK: attributes #2 = { "bss-section"=".bss.2" "rodata-section"=".rodata.1" }
    +// CHECK: attributes #3 = { "bss-section"=".bss.2" "rodata-section"=".rodata.2" }
    diff --git a/test/CodeGenCXX/clang-sections.cpp b/test/CodeGenCXX/clang-sections.cpp
    new file mode 100644
    index 000000000000..4fe42eaf7789
    --- /dev/null
    +++ b/test/CodeGenCXX/clang-sections.cpp
    @@ -0,0 +1,78 @@
    +// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
    +// Test that global variables, statics and functions are attached section-attributes
    +// as per '#pragma clang section' directives.
    +
    +extern "C" {
    +// test with names for each section
    +#pragma clang section bss="my_bss.1" data="my_data.1" rodata="my_rodata.1"
    +#pragma clang section text="my_text.1"
    +int a;      // my_bss.1
    +int b = 1;  // my_data.1
    +int c[4];   // my_bss.1
    +short d[5] = {0}; // my_bss.1
    +short e[6] = {0, 0, 1}; // my_data.1
    +extern const int f;
    +const int f = 2;  // my_rodata.1
    +int foo(void) {   // my_text.1
    +  return b;
    +}
    +static int g[2]; // my_bss.1
    +#pragma clang section bss=""
    +int h; // default - .bss
    +#pragma clang section data=""  bss="my_bss.2" text="my_text.2"
    +int i = 0; // my_bss.2
    +extern const int j;
    +const int j = 4; // default - .rodata
    +int k; // my_bss.2
    +extern int zoo(int *x, int *y);
    +int goo(void) {  // my_text.2
    +  static int lstat_h;  // my_bss.2
    +  return zoo(g, &lstat_h);
    +}
    +#pragma clang section rodata="my_rodata.2" data="my_data.2"
    +int l = 5; // my_data.2
    +extern const int m;
    +const int m = 6; // my_rodata.2
    +#pragma clang section rodata="" data="" bss="" text=""
    +int n; // default
    +int o = 6; // default
    +extern const int p;
    +const int p = 7; // default
    +int hoo(void) {
    +  return b;
    +}
    +}
    +//CHECK: @a = global i32 0, align 4 #0
    +//CHECK: @b = global i32 1, align 4 #0
    +//CHECK: @c = global [4 x i32] zeroinitializer, align 4 #0
    +//CHECK: @d = global [5 x i16] zeroinitializer, align 2 #0
    +//CHECK: @e = global [6 x i16] [i16 0, i16 0, i16 1, i16 0, i16 0, i16 0], align 2 #0
    +//CHECK: @f = constant i32 2, align 4 #0
    +
    +//CHECK: @h = global i32 0, align 4 #1
    +//CHECK: @i = global i32 0, align 4 #2
    +//CHECK: @j = constant i32 4, align 4 #2
    +//CHECK: @k = global i32 0, align 4 #2
    +//CHECK: @_ZZ3gooE7lstat_h = internal global i32 0, align 4 #2
    +//CHECK: @_ZL1g = internal global [2 x i32] zeroinitializer, align 4 #0
    +
    +//CHECK: @l = global i32 5, align 4 #3
    +//CHECK: @m = constant i32 6, align 4 #3
    +
    +//CHECK: @n = global i32 0, align 4
    +//CHECK: @o = global i32 6, align 4
    +//CHECK: @p = constant i32 7, align 4
    +
    +//CHECK: define i32 @foo() #4 {
    +//CHECK: define i32 @goo() #5 {
    +//CHECK: declare i32 @zoo(i32*, i32*) #6
    +//CHECK: define i32 @hoo() #7 {
    +
    +//CHECK: attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
    +//CHECK: attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
    +//CHECK: attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" }
    +//CHECK: attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "rodata-section"="my_rodata.2" }
    +//CHECK: attributes #4 = { {{.*"implicit-section-name"="my_text.1".*}} }
    +//CHECK: attributes #5 = { {{.*"implicit-section-name"="my_text.2".*}} }
    +//CHECK-NOT: attributes #6 = { {{.*"implicit-section-name".*}} }
    +//CHECK-NOT: attributes #7 = { {{.*"implicit-section-name".*}} }
    diff --git a/test/CodeGenObjC/exceptions-asm-attribute.m b/test/CodeGenObjC/exceptions-asm-attribute.m
    index 5719198f7962..93e89b8e0a8a 100644
    --- a/test/CodeGenObjC/exceptions-asm-attribute.m
    +++ b/test/CodeGenObjC/exceptions-asm-attribute.m
    @@ -1,4 +1,4 @@
    -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -o %t %s
    +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -Wno-objc-root-class -fexceptions -fobjc-exceptions -o %t %s
     // RUN: FileCheck -check-prefix=CHECK-X86_64 < %t %s
     // RUN: FileCheck -check-prefix=CHECK-EHTYPE < %t %s
     // rdar://16462586
    @@ -15,11 +15,11 @@
     // CHECK-X86_64: @"OBJC_EHTYPE_$_MySecretNamespace.EH1" = weak global {{.*}}, align 8
     // CHECK-X86_64: @"OBJC_EHTYPE_$_MySecretNamespace.EH2" = external global
     // CHECK-X86_64: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" = global {{.*}}, section "__DATA,__objc_const", align 8
    -// CHECK-X86_64: @"OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
    +// CHECK-X86_64: @"OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip", align 8
     // CHECK-X86_64: define internal void @"\01-[A im0]"
     // CHECK-X86_64: define internal void @"\01-[A(Cat) im1]"
     
    -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-exceptions -fvisibility hidden -emit-llvm -o %t %s
    +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -fobjc-exceptions -fvisibility hidden -emit-llvm -o %t %s
     // RUN: FileCheck -check-prefix=CHECK-X86_64-HIDDEN < %t %s
     
     // CHECK-X86_64-HIDDEN: @"OBJC_CLASS_$_MySecretNamespace.A" = hidden global {{.*}}, section "__DATA, __objc_data", align 8
    @@ -30,7 +30,7 @@
     // CHECK-X86_64-HIDDEN: define internal void @"\01-[A im0]"
     // CHECK-X86_64-HIDDEN: define internal void @"\01-[A(Cat) im1]"
     
    -// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -fobjc-exceptions -emit-llvm -o %t %s
    +// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -Wno-objc-root-class -fobjc-exceptions -emit-llvm -o %t %s
     // RUN: FileCheck -check-prefix=CHECK-ARMV6 < %t %s
     
     // CHECK-ARMV6: @"OBJC_CLASS_$_MySecretNamespace.A" = global {{.*}}, section "__DATA, __objc_data", align 4
    @@ -39,7 +39,7 @@
     // CHECK-ARMV6: @"OBJC_EHTYPE_$_MySecretNamespace.EH1" = weak global {{.*}}, align 4
     // CHECK-ARMV6: @"OBJC_EHTYPE_$_MySecretNamespace.EH2" = external global
     // CHECK-ARMV6: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" = global {{.*}}, section "__DATA,__objc_const", align 4
    -// CHECK-ARMV6: @"OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA, __objc_classlist, regular, no_dead_strip", align 4
    +// CHECK-ARMV6: @"OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip", align 4
     // CHECK-ARMV6: define internal void @"\01-[A im0]"
     // CHECK-ARMV6: define internal void @"\01-[A(Cat) im1]"
     
    diff --git a/test/CodeGenObjC/image-info.m b/test/CodeGenObjC/image-info.m
    index 43fb125a4cc6..37156ed039e4 100644
    --- a/test/CodeGenObjC/image-info.m
    +++ b/test/CodeGenObjC/image-info.m
    @@ -7,11 +7,11 @@
     // CHECK-FRAGILE:      !llvm.module.flags = !{{{.*}}}
     // CHECK-FRAGILE:      !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 1}
     // CHECK-FRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0}
    -// CHECK-FRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__OBJC, __image_info,regular"}
    +// CHECK-FRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__OBJC,__image_info,regular"}
     // CHECK-FRAGILE-NEXT: !{{[0-9]+}} = !{i32 4, !"Objective-C Garbage Collection", i32 0}
     
     // CHECK-NONFRAGILE:      !llvm.module.flags = !{{{.*}}}
     // CHECK-NONFRAGILE:      !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 2}
     // CHECK-NONFRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0}
    -// CHECK-NONFRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__DATA, __objc_imageinfo, regular, no_dead_strip"}
    +// CHECK-NONFRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"}
     // CHECK-NONFRAGILE-NEXT: !{{[0-9]+}} = !{i32 4, !"Objective-C Garbage Collection", i32 0}
    diff --git a/test/CodeGenObjC/metadata-symbols-64.m b/test/CodeGenObjC/metadata-symbols-64.m
    index 5139cd8fdedf..b94f1b63843e 100644
    --- a/test/CodeGenObjC/metadata-symbols-64.m
    +++ b/test/CodeGenObjC/metadata-symbols-64.m
    @@ -12,7 +12,7 @@
     // CHECK: @"\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_P" = private global {{.*}} section "__DATA, __objc_const", align 8
     // CHECK: @"\01l_OBJC_$_PROTOCOL_CLASS_METHODS_P" = private global {{.*}} section "__DATA, __objc_const", align 8
     // CHECK: @"\01l_OBJC_PROTOCOL_$_P" = weak hidden global {{.*}}, align 8
    -// CHECK: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global {{.*}} section "__DATA, __objc_protolist, coalesced, no_dead_strip", align 8
    +// CHECK: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global {{.*}} section "__DATA,__objc_protolist,coalesced,no_dead_strip", align 8
     // CHECK: @"\01l_OBJC_CLASS_PROTOCOLS_$_A" = private global {{.*}} section "__DATA, __objc_const", align 8
     // CHECK: @"\01l_OBJC_METACLASS_RO_$_A" = private global {{.*}} section "__DATA, __objc_const", align 8
     // CHECK: @"\01l_OBJC_$_INSTANCE_METHODS_A" = private global {{.*}} section "__DATA, __objc_const", align 8
    @@ -23,14 +23,14 @@
     // CHECK: @"\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = private global {{.*}} section "__DATA, __objc_const", align 8
     // CHECK: @"\01l_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = private global {{.*}} section "__DATA, __objc_const", align 8
     // CHECK: @"\01l_OBJC_$_CATEGORY_A_$_Cat" = private global {{.*}} section "__DATA, __objc_const", align 8
    -// CHECK: @"OBJC_CLASSLIST_SUP_REFS_$_{{[0-9]*}}" = private global {{.*}} section "__DATA, __objc_superrefs, regular, no_dead_strip", align 8
    -// CHECK: @OBJC_SELECTOR_REFERENCES_ = private externally_initialized global {{.*}} section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
    -// CHECK: @"OBJC_CLASSLIST_SUP_REFS_$_{{[\.0-9]*}}" = private global {{.*}} section "__DATA, __objc_superrefs, regular, no_dead_strip", align 8
    +// CHECK: @"OBJC_CLASSLIST_SUP_REFS_$_{{[0-9]*}}" = private global {{.*}} section "__DATA,__objc_superrefs,regular,no_dead_strip", align 8
    +// CHECK: @OBJC_SELECTOR_REFERENCES_ = private externally_initialized global {{.*}} section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip"
    +// CHECK: @"OBJC_CLASSLIST_SUP_REFS_$_{{[\.0-9]*}}" = private global {{.*}} section "__DATA,__objc_superrefs,regular,no_dead_strip", align 8
     // CHECK: @"OBJC_CLASS_$_B" = external global
    -// CHECK: @"OBJC_CLASSLIST_REFERENCES_$_{{[0-9]*}}" = private global {{.*}} section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
    -// CHECK: @"\01l_objc_msgSend_fixup_alloc" = weak hidden global {{.*}} section "__DATA, __objc_msgrefs, coalesced", align 16
    -// CHECK: @"OBJC_LABEL_CLASS_$" = private global {{.*}} section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
    -// CHECK: @"OBJC_LABEL_CATEGORY_$" = private global {{.*}} section "__DATA, __objc_catlist, regular, no_dead_strip", align 8
    +// CHECK: @"OBJC_CLASSLIST_REFERENCES_$_{{[0-9]*}}" = private global {{.*}} section "__DATA,__objc_classrefs,regular,no_dead_strip", align 8
    +// CHECK: @"\01l_objc_msgSend_fixup_alloc" = weak hidden global {{.*}} section "__DATA,__objc_msgrefs,coalesced", align 16
    +// CHECK: @"OBJC_LABEL_CLASS_$" = private global {{.*}} section "__DATA,__objc_classlist,regular,no_dead_strip", align 8
    +// CHECK: @"OBJC_LABEL_CATEGORY_$" = private global {{.*}} section "__DATA,__objc_catlist,regular,no_dead_strip", align 8
     // CHECK: @objc_msgSend_fpret(
     // CHECK: @objc_msgSend_fixup(
     
    diff --git a/test/CodeGenObjC/metadata_symbols.m b/test/CodeGenObjC/metadata_symbols.m
    index 4c365a14f982..9aee55bb8e1a 100644
    --- a/test/CodeGenObjC/metadata_symbols.m
    +++ b/test/CodeGenObjC/metadata_symbols.m
    @@ -1,4 +1,4 @@
    -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -o %t %s
    +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -Wno-objc-root-class -fexceptions -fobjc-exceptions -o %t %s
     // RUN: FileCheck -check-prefix=CHECK-X86_64 < %t %s
     // RUN: FileCheck -check-prefix=CHECK-EHTYPE < %t %s
     
    @@ -14,11 +14,11 @@
     // CHECK-X86_64: @"OBJC_EHTYPE_$_EH1" = weak global {{.*}}, align 8
     // CHECK-X86_64: @"OBJC_EHTYPE_$_EH2" = external global
     // CHECK-X86_64: @"OBJC_EHTYPE_$_EH3" = global {{.*}}, section "__DATA,__objc_const", align 8
    -// CHECK-X86_64: @"OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
    +// CHECK-X86_64: @"OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip", align 8
     // CHECK-X86_64: define internal void @"\01-[A im0]"
     // CHECK-X86_64: define internal void @"\01-[A(Cat) im1]"
     
    -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-exceptions -fvisibility hidden -emit-llvm -o %t %s
    +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -fobjc-exceptions -fvisibility hidden -emit-llvm -o %t %s
     // RUN: FileCheck -check-prefix=CHECK-X86_64-HIDDEN < %t %s
     
     // CHECK-X86_64-HIDDEN: @"OBJC_CLASS_$_A" = hidden global {{.*}}, section "__DATA, __objc_data", align 8
    @@ -29,7 +29,7 @@
     // CHECK-X86_64-HIDDEN: define internal void @"\01-[A im0]"
     // CHECK-X86_64-HIDDEN: define internal void @"\01-[A(Cat) im1]"
     
    -// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -fobjc-exceptions -emit-llvm -o %t %s
    +// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -Wno-objc-root-class -fobjc-exceptions -emit-llvm -o %t %s
     // RUN: FileCheck -check-prefix=CHECK-ARMV6 < %t %s
     
     // CHECK-ARMV6: @"OBJC_CLASS_$_A" = global {{.*}}, section "__DATA, __objc_data", align 4
    @@ -38,7 +38,7 @@
     // CHECK-ARMV6: @"OBJC_EHTYPE_$_EH1" = weak global {{.*}}, align 4
     // CHECK-ARMV6: @"OBJC_EHTYPE_$_EH2" = external global
     // CHECK-ARMV6: @"OBJC_EHTYPE_$_EH3" = global {{.*}}, section "__DATA,__objc_const", align 4
    -// CHECK-ARMV6: @"OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA, __objc_classlist, regular, no_dead_strip", align 4
    +// CHECK-ARMV6: @"OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip", align 4
     // CHECK-ARMV6: define internal void @"\01-[A im0]"
     // CHECK-ARMV6: define internal void @"\01-[A(Cat) im1]"
     
    diff --git a/test/CodeGenObjC/non-lazy-classes.m b/test/CodeGenObjC/non-lazy-classes.m
    index 400d3e9fdf94..b04b020e20ee 100644
    --- a/test/CodeGenObjC/non-lazy-classes.m
    +++ b/test/CodeGenObjC/non-lazy-classes.m
    @@ -1,7 +1,7 @@
    -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | \
    +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -emit-llvm -o - %s | \
     // RUN: FileCheck %s
    -// CHECK: @"OBJC_LABEL_NONLAZY_CLASS_$" = private global [1 x {{.*}}] {{.*}}@"OBJC_CLASS_$_A"{{.*}}, section "__DATA, __objc_nlclslist, regular, no_dead_strip", align 8
    -// CHECK: @"OBJC_LABEL_NONLAZY_CATEGORY_$" = private global [1 x {{.*}}] {{.*}}@"\01l_OBJC_$_CATEGORY_A_$_Cat"{{.*}}, section "__DATA, __objc_nlcatlist, regular, no_dead_strip", align 8
    +// CHECK: @"OBJC_LABEL_NONLAZY_CLASS_$" = private global [1 x {{.*}}] {{.*}}@"OBJC_CLASS_$_A"{{.*}}, section "__DATA,__objc_nlclslist,regular,no_dead_strip", align 8
    +// CHECK: @"OBJC_LABEL_NONLAZY_CATEGORY_$" = private global [1 x {{.*}}] {{.*}}@"\01l_OBJC_$_CATEGORY_A_$_Cat"{{.*}}, section "__DATA,__objc_nlcatlist,regular,no_dead_strip", align 8
     
     @interface A @end
     @implementation A
    diff --git a/test/CodeGenObjC/sections.m b/test/CodeGenObjC/sections.m
    new file mode 100644
    index 000000000000..f98b7db073c6
    --- /dev/null
    +++ b/test/CodeGenObjC/sections.m
    @@ -0,0 +1,72 @@
    +// RUN: %clang_cc1 -triple x86_64-unknown-windows -fobjc-dispatch-method=mixed -fobjc-runtime=ios -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-COFF
    +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fobjc-dispatch-method=mixed -fobjc-runtime=ios -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-ELF
    +// RUN: %clang_cc1 -triple x86_64-apple-ios -fobjc-dispatch-method=mixed -fobjc-runtime=ios -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MACHO
    +
    +__attribute__((__objc_root_class__))
    +@interface NSObject
    ++ (void)load;
    ++ (id)class;
    +@end
    +
    +@protocol P
    +@end
    +
    +@interface I

    : NSObject ++ (void)load; +@end + +@implementation I ++ (void)load; { } +@end + +@implementation I(C) ++ (void)load; { + [super load]; +} +@end + +@interface J : NSObject +- (void)m; +@end + +_Bool f(J *j) { + [j m]; + return [I class] == @protocol(P); +} + +// CHECK-COFF: @"OBJC_CLASSLIST_SUP_REFS_$_" = {{.*}}, section ".objc_superrefs$B" +// CHECK-COFF: @OBJC_SELECTOR_REFERENCES_ = {{.*}}, section ".objc_selrefs$B" +// CHECK-COFF: @"OBJC_CLASSLIST_REFERENCES_$_" = {{.*}}, section ".objc_classrefs$B" +// CHECK-COFF: @"\01l_objc_msgSend_fixup_class" = {{.*}}, section ".objc_msgrefs$B" +// CHECK-COFF: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section ".objc_protolist$B" +// CHECK-COFF: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section ".objc_protorefs$B" +// CHECK-COFF: @"OBJC_LABEL_CLASS_$" = {{.*}}, section ".objc_classlist$B" +// CHECK-COFF: @"OBJC_LABEL_NONLAZY_CLASS_$" = {{.*}}, section ".objc_nlclslist$B" +// CHECK-COFF: @"OBJC_LABEL_CATEGORY_$" = {{.*}}, section ".objc_catlist$B" +// CHECK-COFF: @"OBJC_LABEL_NONLAZY_CATEGORY_$" = {{.*}}, section ".objc_nlcatlist$B" +// CHECK-COFF: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !".objc_imageinfo$B"} + +// CHECK-ELF: @"OBJC_CLASSLIST_SUP_REFS_$_" = {{.*}}, section "objc_superrefs" +// CHECK-ELF: @OBJC_SELECTOR_REFERENCES_ = {{.*}}, section "objc_selrefs" +// CHECK-ELF: @"OBJC_CLASSLIST_REFERENCES_$_" = {{.*}}, section "objc_classrefs" +// CHECK-ELF: @"\01l_objc_msgSend_fixup_class" = {{.*}}, section "objc_msgrefs" +// CHECK-ELF: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section "objc_protolist" +// CHECK-ELF: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section "objc_protorefs" +// CHECK-ELF: @"OBJC_LABEL_CLASS_$" = {{.*}}, section "objc_classlist" +// CHECK-ELF: @"OBJC_LABEL_NONLAZY_CLASS_$" = {{.*}}, section "objc_nlclslist" +// CHECK-ELF: @"OBJC_LABEL_CATEGORY_$" = {{.*}}, section "objc_catlist" +// CHECK-ELF: @"OBJC_LABEL_NONLAZY_CATEGORY_$" = {{.*}}, section "objc_nlcatlist" +// CHECK-ELF: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"objc_imageinfo"} + +// CHECK-MACHO: @"OBJC_CLASSLIST_SUP_REFS_$_" = {{.*}}, section "__DATA,__objc_superrefs,regular,no_dead_strip" +// CHECK-MACHO: @OBJC_SELECTOR_REFERENCES_ = {{.*}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip" +// CHECK-MACHO: @"OBJC_CLASSLIST_REFERENCES_$_" = {{.*}}, section "__DATA,__objc_classrefs,regular,no_dead_strip" +// CHECK-MACHO: @"\01l_objc_msgSend_fixup_class" = {{.*}}, section "__DATA,__objc_msgrefs,coalesced" +// CHECK-MACHO: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section "__DATA,__objc_protolist,coalesced,no_dead_strip" +// CHECK-MACHO: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section "__DATA,__objc_protorefs,coalesced,no_dead_strip" +// CHECK-MACHO: @"OBJC_LABEL_CLASS_$" = {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip" +// CHECK-MACHO: @"OBJC_LABEL_NONLAZY_CLASS_$" = {{.*}}, section "__DATA,__objc_nlclslist,regular,no_dead_strip" +// CHECK-MACHO: @"OBJC_LABEL_CATEGORY_$" = {{.*}}, section "__DATA,__objc_catlist,regular,no_dead_strip" +// CHECK-MACHO: @"OBJC_LABEL_NONLAZY_CATEGORY_$" = {{.*}}, section "__DATA,__objc_nlcatlist,regular,no_dead_strip" +// CHECK-MACHO: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} + diff --git a/test/Driver/baremetal.cpp b/test/Driver/baremetal.cpp index aed90ac12c1e..ec78b9136371 100644 --- a/test/Driver/baremetal.cpp +++ b/test/Driver/baremetal.cpp @@ -5,13 +5,13 @@ // RUN: --sysroot=%S/Inputs/baremetal_arm \ // RUN: | FileCheck --check-prefix=CHECK-V6M-C %s // CHECK-V6M-C: "[[PREFIX_DIR:.*]]{{[/\\]+}}{{[^/^\\]+}}{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "thumbv6m-none--eabi" -// CHECK-V6M-C-SAME: "-resource-dir" "[[PREFIX_DIR]]{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}[[VERSION:[^"]*]]" +// CHECK-V6M-C-SAME: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-V6M-C-SAME: "-isysroot" "[[SYSROOT:[^"]*]]" // CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECk-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include" // CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp" // CHECK-V6M-C-NEXT: "{{[^"]*}}ld.lld" "{{.*}}.o" "-Bstatic" -// CHECK-V6M-C-SAME: "-L[[PREFIX_DIR]]{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}[[VERSION]]{{[/\\]+}}lib{{[/\\]+}}baremetal" +// CHECK-V6M-C-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for" // CHECK-V6M-C-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a" // CHECK-V6M-C-SAME: "-o" "{{.*}}.o" diff --git a/test/Driver/cl-link.c b/test/Driver/cl-link.c index 4cc170c1cbb8..142725fed8eb 100644 --- a/test/Driver/cl-link.c +++ b/test/Driver/cl-link.c @@ -56,4 +56,4 @@ // NONEXISTENT: nonexistent // RUN: %clang_cl /Tc%s -fuse-ld=lld -### 2>&1 | FileCheck --check-prefix=USE_LLD %s -// USE_LLD: lld-link.exe +// USE_LLD: lld-link diff --git a/test/Driver/fsanitize-coverage.c b/test/Driver/fsanitize-coverage.c index 0516b6db524c..b8a9fa60aa88 100644 --- a/test/Driver/fsanitize-coverage.c +++ b/test/Driver/fsanitize-coverage.c @@ -5,6 +5,7 @@ // CHECK-SANITIZE-COVERAGE-0: -fsanitize=address // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC // RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC // RUN: %clang -target x86_64-linux-gnu -fsanitize=leak -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 786f517f5371..f14459df6391 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -271,6 +271,12 @@ // RUN: %clang -target thumbeb-linux -fsanitize=address,leak -fno-sanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANA-SANL-NO-SANA-THUMBEB // CHECK-SANA-SANL-NO-SANA-THUMBEB: "-fsanitize=leak" +// RUN: %clang -target mips-unknown-linux -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-MIPS +// CHECK-SANL-MIPS: unsupported option '-fsanitize=leak' for target 'mips-unknown-linux' + +// RUN: %clang -target powerpc-unknown-linux -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-PPC +// CHECK-SANL-PPC: unsupported option '-fsanitize=leak' for target 'powerpc-unknown-linux' + // RUN: %clang -target x86_64-linux-gnu -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN // CHECK-MSAN: "-fno-assume-sane-operator-new" // RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN diff --git a/test/FixIt/fixit-format-darwin.m b/test/FixIt/fixit-format-darwin.m new file mode 100644 index 000000000000..bfc71291a5c3 --- /dev/null +++ b/test/FixIt/fixit-format-darwin.m @@ -0,0 +1,59 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -Wformat -fixit %t +// RUN: grep -v CHECK %t | FileCheck %s + +/* This is a test of code modifications created by darwin format fix-its hints + that are provided as part of warning */ + +int printf(const char * restrict, ...); + +#if __LP64__ +typedef long NSInteger; +typedef unsigned long NSUInteger; +#else +typedef int NSInteger; +typedef unsigned int NSUInteger; +#endif +NSInteger getNSInteger(); +NSUInteger getNSUInteger(); + +#define Log1(...) \ +do { \ + printf(__VA_ARGS__); \ +} while (0) + +#define Log2(...) \ +do { \ + printf(__VA_ARGS__); \ + printf(__VA_ARGS__); \ +} while (0) \ + +#define Log3(X, Y, Z) \ +do { \ + printf(X, Y); \ + printf(X, Z); \ +} while (0) \ + +void test() { + printf("test 1: %s", getNSInteger()); + // CHECK: printf("test 1: %ld", (long)getNSInteger()); + printf("test 2: %s %s", getNSInteger(), getNSInteger()); + // CHECK: printf("test 2: %ld %ld", (long)getNSInteger(), (long)getNSInteger()); + + Log1("test 3: %s", getNSInteger()); + // CHECK: Log1("test 3: %ld", (long)getNSInteger()); + Log1("test 4: %s %s", getNSInteger(), getNSInteger()); + // CHECK: Log1("test 4: %ld %ld", (long)getNSInteger(), (long)getNSInteger()); + + Log2("test 5: %s", getNSInteger()); + // CHECK: Log2("test 5: %ld", (long)getNSInteger()); + Log2("test 6: %s %s", getNSInteger(), getNSInteger()); + // CHECK: Log2("test 6: %ld %ld", (long)getNSInteger(), (long)getNSInteger()); + + // Artificial test to check that X (in Log3(X, Y, Z)) + // is modified only according to the diagnostics + // for the first printf and the modification caused + // by the second printf is dropped. + Log3("test 7: %s", getNSInteger(), getNSUInteger()); + // CHECK: Log3("test 7: %ld", (long)getNSInteger(), (unsigned long)getNSUInteger()); +} diff --git a/test/FixIt/fixit.c b/test/FixIt/fixit.c index 6443fe53c2a1..a46558c7fb0b 100644 --- a/test/FixIt/fixit.c +++ b/test/FixIt/fixit.c @@ -1,9 +1,8 @@ // RUN: %clang_cc1 -pedantic -Wunused-label -verify -x c %s // RUN: cp %s %t // RUN: not %clang_cc1 -pedantic -Wunused-label -fixit -x c %t -// RUN: grep -v CHECK %t > %t2 // RUN: %clang_cc1 -pedantic -Wunused-label -Werror -x c %t -// RUN: FileCheck -input-file=%t2 %t +// RUN: grep -v CHECK %t | FileCheck %t /* This is a test of the various code modification hints that are provided as part of warning or extension diagnostics. All of the diff --git a/test/Headers/ms-cppoperkey.cpp b/test/Headers/ms-cppoperkey.cpp new file mode 100644 index 000000000000..ca56ee17bcb1 --- /dev/null +++ b/test/Headers/ms-cppoperkey.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 \ +// RUN: -fms-compatibility -x c++-cpp-output \ +// RUN: -ffreestanding -fsyntax-only -Werror \ +// RUN: %s -verify +// expected-no-diagnostics +# 1 "t.cpp" +# 1 "query.h" 1 3 +// MS header uses operator keyword as field name. +// Compile without syntax errors. +struct tagRESTRICTION + { + union _URes + { + int or; // Note use of cpp operator token + } res; + }; diff --git a/test/Headers/ms-cppoperkey1.cpp b/test/Headers/ms-cppoperkey1.cpp new file mode 100644 index 000000000000..c03efc9dacde --- /dev/null +++ b/test/Headers/ms-cppoperkey1.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 \ +// RUN: -fms-compatibility -x c++-cpp-output \ +// RUN: -ffreestanding -fsyntax-only -Werror \ +// RUN: %s -verify + + +# 1 "t.cpp" +# 1 "query.h" 1 3 4 +// MS header uses operator keyword as field name. +// Compile without syntax errors. +struct tagRESTRICTION + { + union _URes + { + int or; // Note use of cpp operator token + } res; + }; + ; + +int aa ( int x) +{ + // In system header code, treat operator keyword as identifier. + if ( // expected-note{{to match this '('}} + x>1 or x<0) return 1; // expected-error{{expected ')'}} + else return 0; +} + diff --git a/test/Headers/ms-cppoperkey2.cpp b/test/Headers/ms-cppoperkey2.cpp new file mode 100644 index 000000000000..2afed36b7446 --- /dev/null +++ b/test/Headers/ms-cppoperkey2.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-pc-win32 -fms-compatibility \ +// RUN: -ffreestanding -fsyntax-only -Werror %s -verify +// RUN: %clang_cc1 \ +// RUN: -ffreestanding -fsyntax-only -Werror %s -verify +// expected-no-diagnostics +int bb ( int x) +{ + // In user code, treat operator keyword as operator keyword. + if ( x>1 or x<0) return 1; + else return 0; +} diff --git a/test/Index/pipe-size.cl b/test/Index/pipe-size.cl new file mode 100644 index 000000000000..d07d7067da8c --- /dev/null +++ b/test/Index/pipe-size.cl @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple spir-unknown-unknown %s -o - | FileCheck %s --check-prefix=SPIR +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple spir64-unknown-unknown %s -o - | FileCheck %s --check-prefix=SPIR64 +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL2.0 -emit-llvm -triple amdgcn-amd-amdhsa-amdgizcl %s -o - | FileCheck %s --check-prefix=AMD +__kernel void testPipe( pipe int test ) +{ + int s = sizeof(test); + // X86: store %opencl.pipe_t* %test, %opencl.pipe_t** %test.addr, align 8 + // X86: store i32 8, i32* %s, align 4 + // SPIR: store %opencl.pipe_t addrspace(1)* %test, %opencl.pipe_t addrspace(1)** %test.addr, align 4 + // SPIR: store i32 4, i32* %s, align 4 + // SPIR64: store %opencl.pipe_t addrspace(1)* %test, %opencl.pipe_t addrspace(1)** %test.addr, align 8 + // SPIR64: store i32 8, i32* %s, align 4 + // AMD: store %opencl.pipe_t addrspace(1)* %test, %opencl.pipe_t addrspace(1)* addrspace(5)* %test.addr, align 4 + // AMD: store i32 8, i32 addrspace(5)* %s, align 4 +} diff --git a/test/Index/singe-file-parse.m b/test/Index/singe-file-parse.m new file mode 100644 index 000000000000..d13915b30c5f --- /dev/null +++ b/test/Index/singe-file-parse.m @@ -0,0 +1,11 @@ +// RUN: c-index-test -single-file-parse %s | FileCheck %s + +#include + +// CHECK-NOT: TypedefDecl=intptr_t + +// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=MyCls +@interface MyCls +// CHECK: [[@LINE+1]]:8: ObjCInstanceMethodDecl=some_meth +-(void)some_meth; +@end diff --git a/test/Modules/Inputs/crash-typo-correction-visibility/module.h b/test/Modules/Inputs/crash-typo-correction-visibility/module.h new file mode 100644 index 000000000000..6e73c3c729e3 --- /dev/null +++ b/test/Modules/Inputs/crash-typo-correction-visibility/module.h @@ -0,0 +1 @@ +struct member; diff --git a/test/Modules/Inputs/crash-typo-correction-visibility/module.modulemap b/test/Modules/Inputs/crash-typo-correction-visibility/module.modulemap new file mode 100644 index 000000000000..7310d6a2ef18 --- /dev/null +++ b/test/Modules/Inputs/crash-typo-correction-visibility/module.modulemap @@ -0,0 +1,3 @@ +module "module" { + header "module.h" +} diff --git a/test/Modules/crash-typo-correction-visibility.cpp b/test/Modules/crash-typo-correction-visibility.cpp new file mode 100644 index 000000000000..518293026a63 --- /dev/null +++ b/test/Modules/crash-typo-correction-visibility.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=module -o %T/module.pcm -emit-module %S/Inputs/crash-typo-correction-visibility/module.modulemap +// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-file=%T/module.pcm %s -verify + +struct S { + int member; // expected-note {{declared here}} +}; + +int f(...); + +int b = sizeof(f(member)); // expected-error {{undeclared identifier 'member'}} diff --git a/test/Modules/preprocess-build-diamond.m b/test/Modules/preprocess-build-diamond.m new file mode 100644 index 000000000000..b031a0a91460 --- /dev/null +++ b/test/Modules/preprocess-build-diamond.m @@ -0,0 +1,26 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs %s -E -o %t/diamond.mi -frewrite-imports +// RUN: FileCheck %s --input-file %t/diamond.mi +// RUN: %clang_cc1 -fmodules %t/diamond.mi -I. -verify + +// CHECK: {{^}}#pragma clang module build diamond_top +// CHECK: {{^}}module diamond_top { +// CHECK: {{^}}#pragma clang module contents + +// FIXME: @import does not work under -frewrite-includes / -frewrite-imports +// because we disable it when macro expansion is disabled. +#include "diamond_bottom.h" + +// expected-no-diagnostics +void test_diamond(int i, float f, double d, char c) { + top(&i); + left(&f); + right(&d); + bottom(&c); + top_left(&c); + left_and_right(&i); + struct left_and_right lr; + lr.left = 17; +} + diff --git a/test/Modules/preprocess-build.cpp b/test/Modules/preprocess-build.cpp new file mode 100644 index 000000000000..bf9f16162be2 --- /dev/null +++ b/test/Modules/preprocess-build.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c++1z %s -verify + +#pragma clang module build baz + module baz {} +#pragma clang module endbuild // baz + +#pragma clang module build foo + module foo { module bar {} } +#pragma clang module contents + #pragma clang module begin foo.bar + + // Can import baz here even though it was created in an outer build. + #pragma clang module import baz + + #pragma clang module build bar + module bar {} + #pragma clang module contents + #pragma clang module begin bar + extern int n; + #pragma clang module end + #pragma clang module endbuild // bar + + #pragma clang module import bar + + constexpr int *f() { return &n; } + + #pragma clang module end +#pragma clang module endbuild // foo + +#pragma clang module import bar +#pragma clang module import foo.bar +static_assert(f() == &n); + +#pragma clang module build // expected-error {{expected module name}} +#pragma clang module build unterminated // expected-error {{no matching '#pragma clang module endbuild'}} diff --git a/test/Modules/preprocess-module.cpp b/test/Modules/preprocess-module.cpp index 1e9458e667e1..000290fc971b 100644 --- a/test/Modules/preprocess-module.cpp +++ b/test/Modules/preprocess-module.cpp @@ -34,9 +34,29 @@ // RUN: rm %t/fwd.h %t/file.h %t/file2.h %t/module.modulemap // RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/copy.ii -emit-module -o %t/copy.pcm -// Finally, check that our module contains correct mapping information for the headers. +// Check that our module contains correct mapping information for the headers. // RUN: cp %S/Inputs/preprocess/fwd.h %S/Inputs/preprocess/file.h %S/Inputs/preprocess/file2.h %S/Inputs/preprocess/module.modulemap %t // RUN: %clang_cc1 -fmodules -fmodule-file=%t/copy.pcm %s -I%t -verify -fno-modules-error-recovery -DCOPY -DINCLUDE +// RUN: rm %t/fwd.h %t/file.h %t/file2.h %t/module.modulemap + +// Check that we can preprocess from a .pcm file and that we get the same result as preprocessing from the original sources. +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -I%S/Inputs/preprocess -x c++-module-map %S/Inputs/preprocess/module.modulemap -emit-module -o %t/file.pcm +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -I%S/Inputs/preprocess %t/file.pcm -E -frewrite-includes -o %t/file.rewrite.ii +// FIXME: This check fails on Windows targets, due to canonicalization of directory separators. +// FIXME: cmp %t/rewrite.ii %t/file.rewrite.ii +// FIXME: Instead, just check that the preprocessed output is functionally equivalent to the output when preprocessing from the original sources. +// RUN: FileCheck %s --input-file %t/file.rewrite.ii --check-prefix=CHECK --check-prefix=REWRITE +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/file.rewrite.ii -emit-module -o %t/file.rewrite.pcm +// RUN: %clang_cc1 -fmodules -fmodule-file=%t/file.rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DFILE_REWRITE +// RUN: %clang_cc1 -fmodules -fmodule-file=%t/file.rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DFILE_REWRITE -DINCLUDE -I%S/Inputs/preprocess +// +// Check that language / header search options are ignored when preprocessing from a .pcm file. +// RUN: %clang_cc1 %t/file.pcm -E -frewrite-includes -o %t/file.rewrite.ii.2 +// RUN: cmp %t/file.rewrite.ii %t/file.rewrite.ii.2 +// +// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -I%S/Inputs/preprocess %t/file.pcm -E -o %t/file.no-rewrite.ii +// RUN: %clang_cc1 %t/file.pcm -E -o %t/file.no-rewrite.ii.2 -Dstruct=error +// RUN: cmp %t/file.no-rewrite.ii %t/file.no-rewrite.ii.2 // == module map // CHECK: # 1 "{{.*}}module.modulemap" @@ -105,7 +125,9 @@ __FILE *a; // expected-error {{declaration of '__FILE' must be imported}} -#ifdef REWRITE +#if FILE_REWRITE +// expected-note@file.rewrite.ii:1 {{here}} +#elif REWRITE // expected-note@rewrite.ii:1 {{here}} #elif COPY // expected-note@copy.ii:1 {{here}} diff --git a/test/Modules/requires-coroutines.mm b/test/Modules/requires-coroutines.mm index d3519cd2bba7..8e25a3c57521 100644 --- a/test/Modules/requires-coroutines.mm +++ b/test/Modules/requires-coroutines.mm @@ -1,12 +1,13 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -fcoroutines-ts -DCOROUTINES - +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify -fcoroutines-ts -DCOROUTINES #ifdef COROUTINES @import DependsOnModule.Coroutines; -@import DependsOnModule.NotCoroutines; // expected-error {{module 'DependsOnModule.NotCoroutines' is incompatible with feature 'coroutines'}} +// expected-error@module.map:29 {{module 'DependsOnModule.NotCoroutines' is incompatible with feature 'coroutines'}} +@import DependsOnModule.NotCoroutines; // expected-note {{module imported here}} #else @import DependsOnModule.NotCoroutines; -@import DependsOnModule.Coroutines; // expected-error {{module 'DependsOnModule.Coroutines' requires feature 'coroutines'}} +// expected-error@module.map:25 {{module 'DependsOnModule.Coroutines' requires feature 'coroutines'}} +@import DependsOnModule.Coroutines; // expected-note {{module imported here}} #endif diff --git a/test/Modules/requires-gnuinlineasm.m b/test/Modules/requires-gnuinlineasm.m index 80b1b18d0742..e710b6bf8d4b 100644 --- a/test/Modules/requires-gnuinlineasm.m +++ b/test/Modules/requires-gnuinlineasm.m @@ -1,6 +1,7 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules \ // RUN: -fimplicit-module-maps -F %S/Inputs/GNUAsm %s \ +// RUN: -I %S/Inputs/GNUAsm \ // RUN: -fno-gnu-inline-asm -DNO_ASM_INLINE -verify // RUN: rm -rf %t // RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules \ @@ -8,7 +9,8 @@ // RUN: -DASM_INLINE -verify #ifdef NO_ASM_INLINE -@import NeedsGNUInlineAsm.Asm; // expected-error{{module 'NeedsGNUInlineAsm.Asm' requires feature 'gnuinlineasm'}} +// expected-error@NeedsGNUInlineAsm.framework/module.map:4 {{module 'NeedsGNUInlineAsm.Asm' requires feature 'gnuinlineasm'}} +@import NeedsGNUInlineAsm.Asm; // expected-note {{module imported here}} #endif #ifdef ASM_INLINE diff --git a/test/Modules/requires.m b/test/Modules/requires.m index 1a013727108b..d61de6bd48d0 100644 --- a/test/Modules/requires.m +++ b/test/Modules/requires.m @@ -1,12 +1,17 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -fmodule-feature custom_req1 +// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs %s -verify -fmodule-feature custom_req1 -@import DependsOnModule.CXX; // expected-error{{module 'DependsOnModule.CXX' requires feature 'cplusplus'}} +// expected-error@DependsOnModule.framework/module.map:7 {{module 'DependsOnModule.CXX' requires feature 'cplusplus'}} +@import DependsOnModule.CXX; // expected-note {{module imported here}} @import DependsOnModule.NotCXX; -@import DependsOnModule.NotObjC; // expected-error{{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}} +// expected-error@DependsOnModule.framework/module.map:15 {{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}} +@import DependsOnModule.NotObjC; // expected-note {{module imported here}} @import DependsOnModule.CustomReq1; // OK -@import DependsOnModule.CustomReq2; // expected-error{{module 'DependsOnModule.CustomReq2' requires feature 'custom_req2'}} +// expected-error@DependsOnModule.framework/module.map:22 {{module 'DependsOnModule.CustomReq2' requires feature 'custom_req2'}} +@import DependsOnModule.CustomReq2; // expected-note {{module imported here}} @import RequiresWithMissingHeader; // OK -@import RequiresWithMissingHeader.HeaderBefore; // expected-error{{module 'RequiresWithMissingHeader.HeaderBefore' requires feature 'missing'}} -@import RequiresWithMissingHeader.HeaderAfter; // expected-error{{module 'RequiresWithMissingHeader.HeaderAfter' requires feature 'missing'}} +// expected-error@module.map:* {{module 'RequiresWithMissingHeader.HeaderBefore' requires feature 'missing'}} +@import RequiresWithMissingHeader.HeaderBefore; // expected-note {{module imported here}} +// expected-error@module.map:* {{module 'RequiresWithMissingHeader.HeaderAfter' requires feature 'missing'}} +@import RequiresWithMissingHeader.HeaderAfter; // expected-note {{module imported here}} diff --git a/test/Modules/requires.mm b/test/Modules/requires.mm index cc64a500bd57..f90622ece842 100644 --- a/test/Modules/requires.mm +++ b/test/Modules/requires.mm @@ -1,6 +1,8 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify +// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify @import DependsOnModule.CXX; -@import DependsOnModule.NotCXX; // expected-error{{module 'DependsOnModule.NotCXX' is incompatible with feature 'cplusplus'}} -@import DependsOnModule.NotObjC; // expected-error{{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}} +// expected-error@module.map:11 {{module 'DependsOnModule.NotCXX' is incompatible with feature 'cplusplus'}} +@import DependsOnModule.NotCXX; // expected-note {{module imported here}} +// expected-error@module.map:15 {{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}} +@import DependsOnModule.NotObjC; // expected-note {{module imported here}} diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c index 36ef9b213658..0bd9e9784599 100644 --- a/test/Preprocessor/init.c +++ b/test/Preprocessor/init.c @@ -4664,6 +4664,16 @@ // RUN: | FileCheck -match-full-lines -check-prefix MIPS-MSA %s // MIPS-MSA:#define __mips_msa 1 // +// RUN: %clang_cc1 -target-feature +nomadd4 \ +// RUN: -E -dM -triple=mips-none-none < /dev/null \ +// RUN: | FileCheck -match-full-lines -check-prefix MIPS-NOMADD4 %s +// MIPS-NOMADD4:#define __mips_no_madd4 1 +// +// RUN: %clang_cc1 \ +// RUN: -E -dM -triple=mips-none-none < /dev/null \ +// RUN: | FileCheck -match-full-lines -check-prefix MIPS-MADD4 %s +// MIPS-MADD4-NOT:#define __mips_no_madd4 1 +// // RUN: %clang_cc1 -target-cpu mips32r3 -target-feature +nan2008 \ // RUN: -E -dM -triple=mips-none-none < /dev/null \ // RUN: | FileCheck -match-full-lines -check-prefix MIPS-NAN2008 %s @@ -8851,7 +8861,7 @@ // WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 1 +// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 @@ -8895,7 +8905,7 @@ // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 1 +// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2 diff --git a/test/Sema/2010-05-31-palignr.c b/test/Sema/2010-05-31-palignr.c index 12be29af95c0..d9bf8f68b7a5 100644 --- a/test/Sema/2010-05-31-palignr.c +++ b/test/Sema/2010-05-31-palignr.c @@ -1,13 +1,12 @@ -// RUN: not %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o /dev/null %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -ffreestanding -verify -fsyntax-only %s #include +#include extern int i; int main () { -#if defined( __SSSE3__ ) - typedef int16_t vSInt16 __attribute__ ((__vector_size__ (16))); short dtbl[] = {1,2,3,4,5,6,7,8}; @@ -15,8 +14,7 @@ int main () vSInt16 v0; v0 = *vdtbl; - v0 = _mm_alignr_epi8(v0, v0, i); // expected-error {{argument to '__builtin_ia32_palignr128' must be a constant integer}} + _mm_alignr_epi8(v0, v0, i); // expected-error {{argument to '__builtin_ia32_palignr128' must be a constant integer}} return 0; -#endif } diff --git a/test/Sema/ext_vector_ops.c b/test/Sema/ext_vector_ops.c new file mode 100644 index 000000000000..af4df07e14da --- /dev/null +++ b/test/Sema/ext_vector_ops.c @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Wvector-conversion -triple x86_64-apple-darwin10 + +typedef unsigned int v2u __attribute__ ((ext_vector_type(2))); +typedef int v2s __attribute__ ((ext_vector_type(2))); +typedef float v2f __attribute__ ((ext_vector_type(2))); + +void test1(v2u v2ua, v2s v2sa, v2f v2fa) { + // Bitwise binary operators + (void)(v2ua & v2ua); + (void)(v2fa & v2fa); // expected-error{{invalid operands to binary expression}} + + // Unary operators + (void)(~v2ua); + (void)(~v2fa); // expected-error{{invalid argument type 'v2f' (vector of 2 'float' values) to unary}} + + // Comparison operators + v2sa = (v2ua==v2sa); + + // Arrays + int array1[v2ua]; // expected-error{{size of array has non-integer type 'v2u' (vector of 2 'unsigned int' values}} + int array2[17]; + // FIXME: error message below needs type! + (void)(array2[v2ua]); // expected-error{{array subscript is not an integer}} + + v2u *v2u_ptr = 0; + v2s *v2s_ptr; +} diff --git a/test/Sema/pragma-clang-section.c b/test/Sema/pragma-clang-section.c new file mode 100644 index 000000000000..49463889d37b --- /dev/null +++ b/test/Sema/pragma-clang-section.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm-none-eabi +#pragma clang section bss="mybss.1" data="mydata.1" rodata="myrodata.1" text="mytext.1" +#pragma clang section bss="" data="" rodata="" text="" +#pragma clang section + +#pragma clang section dss="mybss.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}} +#pragma clang section deta="mydata.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}} +#pragma clang section rodeta="rodata.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}} +#pragma clang section taxt="text.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}} + +#pragma clang section section bss="mybss.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}} + +#pragma clang section bss "mybss.2" // expected-error {{expected '=' following '#pragma clang section bss'}} +#pragma clang section data "mydata.2" // expected-error {{expected '=' following '#pragma clang section data'}} +#pragma clang section rodata "myrodata.2" // expected-error {{expected '=' following '#pragma clang section rodata'}} +#pragma clang section bss="" data="" rodata="" text="" more //expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}} +int a; diff --git a/test/SemaCXX/PR27037.cpp b/test/SemaCXX/PR27037.cpp new file mode 100644 index 000000000000..422de0e6371a --- /dev/null +++ b/test/SemaCXX/PR27037.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { + void f(); +}; + +struct B : A {}; + +void m() { + const B b; + (b.*&B::f)(); // expected-error{{drops 'const' qualifier}} + ((&b)->*&B::f)(); // expected-error{{drops 'const' qualifier}} +} diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp index 17215fedf0ab..7a581fd519a9 100644 --- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -136,13 +136,13 @@ struct bad_decls { }; struct DefaultDelete { - DefaultDelete() = default; // expected-note {{previous declaration is here}} + DefaultDelete() = default; // expected-note {{previous definition is here}} DefaultDelete() = delete; // expected-error {{constructor cannot be redeclared}} - ~DefaultDelete() = default; // expected-note {{previous declaration is here}} + ~DefaultDelete() = default; // expected-note {{previous definition is here}} ~DefaultDelete() = delete; // expected-error {{destructor cannot be redeclared}} - DefaultDelete &operator=(const DefaultDelete &) = default; // expected-note {{previous declaration is here}} + DefaultDelete &operator=(const DefaultDelete &) = default; // expected-note {{previous definition is here}} DefaultDelete &operator=(const DefaultDelete &) = delete; // expected-error {{class member cannot be redeclared}} }; diff --git a/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp b/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp index b08d58abd2a9..dc3adca62fd3 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp @@ -1376,3 +1376,7 @@ XT xt{}; } + +void PR33318(int i) { + [&](auto) { static_assert(&i != nullptr, ""); }(0); // expected-warning 2{{always true}} expected-note {{instantiation}} +} diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index 5de228ad2857..159b7072e61e 100644 --- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -248,3 +248,35 @@ namespace variadic { }; Z z(1, a, b); } + +namespace tuple_tests { + // The converting n-ary constructor appears viable, deducing T as an empty + // pack (until we check its SFINAE constraints). + namespace libcxx_1 { + template struct tuple { + template struct X { static const bool value = false; }; + template::value> tuple(U &&...u); + }; + tuple a = {1, 2, 3}; + } + + // Don't get caught by surprise when X<...> doesn't even exist in the + // selected specialization! + namespace libcxx_2 { + template struct tuple { // expected-note {{candidate}} + template struct X { static const bool value = false; }; + template::value> tuple(U &&...u); + // expected-note@-1 {{substitution failure [with T = <>, U = ]: cannot reference member of primary template because deduced class template specialization 'tuple<>' is an explicit specialization}} + }; + template <> class tuple<> {}; + tuple a = {1, 2, 3}; // expected-error {{no viable constructor or deduction guide}} + } + + namespace libcxx_3 { + template struct scoped_lock { + scoped_lock(T...); + }; + template<> struct scoped_lock<> {}; + scoped_lock l = {}; + } +} diff --git a/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/test/SemaCXX/cxx1z-noexcept-function-type.cpp index a3f710970456..40dc3a22e530 100644 --- a/test/SemaCXX/cxx1z-noexcept-function-type.cpp +++ b/test/SemaCXX/cxx1z-noexcept-function-type.cpp @@ -16,7 +16,7 @@ template void redecl3() throw(B); // expected-error {{do typedef int I; template void redecl4(I) noexcept(B); -template void redecl4(I) noexcept(B); // expected-note {{failed template argument deduction}} +template void redecl4(I) noexcept(B); // expected-note {{could not match 'void (I) noexcept(false)' (aka 'void (int) noexcept(false)') against 'void (int) noexcept'}} void (*init_with_exact_type_a)(int) noexcept = redecl4; void (*init_with_mismatched_type_a)(int) = redecl4; diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp index 74eb5a6ee581..be86f18729dc 100644 --- a/test/SemaTemplate/deduction.cpp +++ b/test/SemaTemplate/deduction.cpp @@ -305,11 +305,11 @@ namespace nullptr_deduction { template struct X {}; template void f(X) { - static_assert(!v, ""); + static_assert(!v, ""); // expected-warning 2{{implicit conversion of nullptr constant to 'bool'}} } void g() { - f(X()); - f(X()); + f(X()); // expected-note {{instantiation of}} + f(X()); // expected-note {{instantiation of}} } template class X, typename T, typename U, int *P> diff --git a/test/SemaTemplate/dependent-template-recover.cpp b/test/SemaTemplate/dependent-template-recover.cpp index 3c01f6586b01..ac1623041719 100644 --- a/test/SemaTemplate/dependent-template-recover.cpp +++ b/test/SemaTemplate/dependent-template-recover.cpp @@ -17,6 +17,28 @@ struct X { } }; +struct MrsBadcrumble { + friend MrsBadcrumble operator<(void (*)(int), MrsBadcrumble); + friend void operator>(MrsBadcrumble, int); +} mb; + +template void f(T t) { + t.f(0); // expected-error {{missing 'template' keyword prior to dependent template name 'f'}} + t.T::f(0); // expected-error {{missing 'template' keyword prior to dependent template name 'f'}} + T::g(0); // expected-error {{missing 'template' keyword prior to dependent template name 'g'}} + + // Note: no diagnostic here, this is actually valid as a comparison between + // the decayed pointer to Y::g<> and mb! + T::g(0); +} + +struct Y { + template void f(int); + template static void g(int); // expected-warning 0-1{{extension}} +}; +void q() { void (*p)(int) = Y::g; } +template void f<0>(Y); // expected-note {{in instantiation of}} + namespace PR9401 { // From GCC PR c++/45558 template diff --git a/test/SemaTemplate/temp_arg_type.cpp b/test/SemaTemplate/temp_arg_type.cpp index daad61c14292..9069f63e0224 100644 --- a/test/SemaTemplate/temp_arg_type.cpp +++ b/test/SemaTemplate/temp_arg_type.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s template class A; // expected-note 2 {{template parameter is declared here}} expected-note{{template is declared here}} @@ -53,3 +54,56 @@ A1::type> ax; // FIXME: [temp.arg.type]p3. The check doesn't really belong here (it // belongs somewhere in the template instantiation section). + +#if __cplusplus >= 201703 +// As a defect resolution, we support deducing B in noexcept(B). +namespace deduce_noexcept { + template struct function; + template + struct function { + static constexpr bool Noexcept = N; + }; + static_assert(function::Noexcept); + static_assert(!function::Noexcept); + + void noexcept_function() noexcept; + void throwing_function(); + + template float &deduce_function(T(*)() noexcept(B)); // expected-note {{candidate}} + template int &deduce_function(T(*)() noexcept); // expected-note {{candidate}} + void test_function_deduction() { + // FIXME: This should probably unambiguously select the second overload. + int &r = deduce_function(noexcept_function); // expected-error {{ambiguous}} + float &s = deduce_function(throwing_function); + } + + namespace low_priority_deduction { + template struct A {}; + template void f(A, void(*)() noexcept(B)) { + using T = decltype(B); + using T = int; + } + void g() { f(A<0>(), g); } // ok, deduce B as an int + } + + // FIXME: It's not clear whether this should work. We're told to deduce with + // P being the function template type and A being the declared type, which + // would accept this, but considering the exception specification in such + // cases breaks new/delete matching. + template void dep() noexcept(Noexcept) {} // expected-note 3{{couldn't infer template argument 'Noexcept'}} + template void dep(); // expected-error {{does not refer to a function template}} + template void dep() noexcept(true); // expected-error {{does not refer to a function template}} + template void dep() noexcept(false); // expected-error {{does not refer to a function template}} + + // FIXME: It's also not clear whether this should be valid: do we substitute + // into the function type (including the exception specification) or not? + template typename T::type1 f() noexcept(T::a); + template typename T::type2 f() noexcept(T::b) {} + struct X { + static constexpr bool b = true; + using type1 = void; + using type2 = void; + }; + template void f(); +} +#endif diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 31ad828a2f10..d25ae117a68a 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1850,6 +1850,34 @@ int perform_test_reparse_source(int argc, const char **argv, int trials, return result; } +static int perform_single_file_parse(const char *filename) { + CXIndex Idx; + CXTranslationUnit TU; + enum CXErrorCode Err; + int result; + + Idx = clang_createIndex(/* excludeDeclsFromPCH */1, + /* displayDiagnostics=*/1); + + Err = clang_parseTranslationUnit2(Idx, filename, + /*command_line_args=*/NULL, + /*num_command_line_args=*/0, + /*unsaved_files=*/NULL, + /*num_unsaved_files=*/0, + CXTranslationUnit_SingleFileParse, &TU); + if (Err != CXError_Success) { + fprintf(stderr, "Unable to load translation unit!\n"); + describeLibclangFailure(Err); + clang_disposeIndex(Idx); + return 1; + } + + result = perform_test_load(Idx, TU, /*filter=*/"all", /*prefix=*/NULL, FilteredPrintingVisitor, /*PostVisit=*/NULL, + /*CommentSchemaFile=*/NULL); + clang_disposeIndex(Idx); + return result; +} + /******************************************************************************/ /* Logic for testing clang_getCursor(). */ /******************************************************************************/ @@ -4439,6 +4467,8 @@ int cindextest_main(int argc, const char **argv) { return perform_test_load_source(argc - 3, argv + 3, argv[2], I, postVisit); } + else if (argc >= 3 && strcmp(argv[1], "-single-file-parse") == 0) + return perform_single_file_parse(argv[2]); else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0) return perform_file_scan(argv[2], argv[3], argc >= 5 ? argv[4] : 0); diff --git a/tools/clang-check/ClangCheck.cpp b/tools/clang-check/ClangCheck.cpp index dac11ff07771..e190c0721afb 100644 --- a/tools/clang-check/ClangCheck.cpp +++ b/tools/clang-check/ClangCheck.cpp @@ -124,8 +124,7 @@ class FixItRewriter : public clang::FixItRewriter { /// \c FixItRewriter. class FixItAction : public clang::FixItAction { public: - bool BeginSourceFileAction(clang::CompilerInstance& CI, - StringRef Filename) override { + bool BeginSourceFileAction(clang::CompilerInstance& CI) override { FixItOpts.reset(new FixItOptions); Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), CI.getLangOpts(), FixItOpts.get())); diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp index 14bff19a1a0c..f8e2fe186b91 100644 --- a/tools/clang-format/ClangFormat.cpp +++ b/tools/clang-format/ClangFormat.cpp @@ -328,8 +328,7 @@ static bool format(StringRef FileName) { } // namespace format } // namespace clang -static void PrintVersion() { - raw_ostream &OS = outs(); +static void PrintVersion(raw_ostream &OS) { OS << clang::getClangToolFullVersion("clang-format") << '\n'; } diff --git a/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/tools/clang-offload-bundler/ClangOffloadBundler.cpp index 49cdd9546689..95d3fdf14d5e 100644 --- a/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -915,8 +915,7 @@ static bool UnbundleFiles() { return false; } -static void PrintVersion() { - raw_ostream &OS = outs(); +static void PrintVersion(raw_ostream &OS) { OS << clang::getClangToolFullVersion("clang-offload-bundler") << '\n'; } diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp index 33d957658cf0..37c14f4a26e1 100644 --- a/tools/driver/cc1as_main.cpp +++ b/tools/driver/cc1as_main.cpp @@ -88,12 +88,13 @@ struct AssemblerInvocation { unsigned NoInitialTextSection : 1; unsigned SaveTemporaryLabels : 1; unsigned GenDwarfForAssembly : 1; - unsigned CompressDebugSections : 1; unsigned RelaxELFRelocations : 1; unsigned DwarfVersion; std::string DwarfDebugFlags; std::string DwarfDebugProducer; std::string DebugCompilationDir; + llvm::DebugCompressionType CompressDebugSections = + llvm::DebugCompressionType::None; std::string MainFileName; /// @} @@ -201,7 +202,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels); // Any DebugInfoKind implies GenDwarfForAssembly. Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ); - Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); + // TODO: base this on -gz instead + if (Args.hasArg(OPT_compress_debug_sections)) + Opts.CompressDebugSections = llvm::DebugCompressionType::GNU; Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); @@ -314,8 +317,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, // Ensure MCAsmInfo initialization occurs before any use, otherwise sections // may be created with a combination of default and explicit settings. - if (Opts.CompressDebugSections) - MAI->setCompressDebugSections(DebugCompressionType::DCT_ZlibGnu); + MAI->setCompressDebugSections(Opts.CompressDebugSections); MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 2d92de19d99c..1ccf6cbd328e 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -3300,12 +3300,14 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename, options & CXTranslationUnit_CreatePreambleOnFirstParse; // FIXME: Add a flag for modules. TranslationUnitKind TUKind - = (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete; + = (options & (CXTranslationUnit_Incomplete | + CXTranslationUnit_SingleFileParse))? TU_Prefix : TU_Complete; bool CacheCodeCompletionResults = options & CXTranslationUnit_CacheCompletionResults; bool IncludeBriefCommentsInCodeCompletion = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion; bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies; + bool SingleFileParse = options & CXTranslationUnit_SingleFileParse; bool ForSerialization = options & CXTranslationUnit_ForSerialization; // Configure the diagnostics. @@ -3390,7 +3392,7 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename, /*CaptureDiagnostics=*/true, *RemappedFiles.get(), /*RemappedFilesKeepOriginalName=*/true, PrecompilePreambleAfterNParses, TUKind, CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion, - /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, + /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, SingleFileParse, /*UserFilesAreVolatile=*/true, ForSerialization, CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(), &ErrUnit)); diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index f20581453e0e..df9aa656b5d9 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -21,6 +21,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/Frontend/ASTUnit.h" using namespace clang; @@ -394,6 +395,27 @@ unsigned clang_isRestrictQualifiedType(CXType CT) { return T.isLocalRestrictQualified(); } +unsigned clang_getAddressSpace(CXType CT) { + QualType T = GetQualType(CT); + + // For non language-specific address space, use separate helper function. + if (T.getAddressSpace() >= LangAS::FirstTargetAddressSpace) { + return T.getQualifiers().getAddressSpaceAttributePrintValue(); + } + return T.getAddressSpace(); +} + +CXString clang_getTypedefName(CXType CT) { + QualType T = GetQualType(CT); + const TypedefType *TT = T->getAs(); + if (TT) { + TypedefNameDecl *TD = TT->getDecl(); + if (TD) + return cxstring::createDup(TD->getNameAsString().c_str()); + } + return cxstring::createEmpty(); +} + CXType clang_getPointeeType(CXType CT) { QualType T = GetQualType(CT); const Type *TP = T.getTypePtrOrNull(); diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index f3758469cb60..187d4749ebc1 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -147,6 +147,7 @@ clang_findReferencesInFile clang_findReferencesInFileWithBlock clang_formatDiagnostic clang_free +clang_getAddressSpace clang_getAllSkippedRanges clang_getArgType clang_getArrayElementType @@ -259,6 +260,7 @@ clang_getTypeDeclaration clang_getTypeKindSpelling clang_getTypeSpelling clang_getTypedefDeclUnderlyingType +clang_getTypedefName clang_hashCursor clang_indexLoc_getCXSourceLocation clang_indexLoc_getFileLocation diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp index d241f5ba2f86..ed184a8c1497 100644 --- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp +++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp @@ -75,6 +75,30 @@ class MockSema : public Parser::Sema { ExpectedMatchersTy ExpectedMatchers; }; +TEST(ParserTest, ParseBoolean) { + MockSema Sema; + Sema.parse("true"); + Sema.parse("false"); + EXPECT_EQ(2U, Sema.Values.size()); + EXPECT_EQ(true, Sema.Values[0].getBoolean()); + EXPECT_EQ(false, Sema.Values[1].getBoolean()); +} + +TEST(ParserTest, ParseDouble) { + MockSema Sema; + Sema.parse("1.0"); + Sema.parse("2.0f"); + Sema.parse("34.56e-78"); + Sema.parse("4.E+6"); + Sema.parse("1"); + EXPECT_EQ(5U, Sema.Values.size()); + EXPECT_EQ(1.0, Sema.Values[0].getDouble()); + EXPECT_EQ("1:1: Error parsing numeric literal: <2.0f>", Sema.Errors[1]); + EXPECT_EQ(34.56e-78, Sema.Values[2].getDouble()); + EXPECT_EQ(4e+6, Sema.Values[3].getDouble()); + EXPECT_FALSE(Sema.Values[4].isDouble()); +} + TEST(ParserTest, ParseUnsigned) { MockSema Sema; Sema.parse("0"); @@ -86,8 +110,8 @@ TEST(ParserTest, ParseUnsigned) { EXPECT_EQ(0U, Sema.Values[0].getUnsigned()); EXPECT_EQ(123U, Sema.Values[1].getUnsigned()); EXPECT_EQ(31U, Sema.Values[2].getUnsigned()); - EXPECT_EQ("1:1: Error parsing unsigned token: <12345678901>", Sema.Errors[3]); - EXPECT_EQ("1:1: Error parsing unsigned token: <1a1>", Sema.Errors[4]); + EXPECT_EQ("1:1: Error parsing numeric literal: <12345678901>", Sema.Errors[3]); + EXPECT_EQ("1:1: Error parsing numeric literal: <1a1>", Sema.Errors[4]); } TEST(ParserTest, ParseString) { diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp index 6bbbc2bd3563..aae229bd045a 100644 --- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -511,6 +511,49 @@ TEST_F(RegistryTest, ParenExpr) { EXPECT_FALSE(matches("int i = 1;", Value)); } +TEST_F(RegistryTest, EqualsMatcher) { + Matcher BooleanStmt = constructMatcher( + "cxxBoolLiteral", constructMatcher("equals", VariantValue(true))) + .getTypedMatcher(); + EXPECT_TRUE(matches("bool x = true;", BooleanStmt)); + EXPECT_FALSE(matches("bool x = false;", BooleanStmt)); + EXPECT_FALSE(matches("bool x = 0;", BooleanStmt)); + + BooleanStmt = constructMatcher( + "cxxBoolLiteral", constructMatcher("equals", VariantValue(0))) + .getTypedMatcher(); + EXPECT_TRUE(matches("bool x = false;", BooleanStmt)); + EXPECT_FALSE(matches("bool x = true;", BooleanStmt)); + EXPECT_FALSE(matches("bool x = 0;", BooleanStmt)); + + Matcher DoubleStmt = constructMatcher( + "floatLiteral", constructMatcher("equals", VariantValue(1.2))) + .getTypedMatcher(); + EXPECT_TRUE(matches("double x = 1.2;", DoubleStmt)); +#if 0 + // FIXME floatLiteral matching should work regardless of suffix. + EXPECT_TRUE(matches("double x = 1.2f;", DoubleStmt)); + EXPECT_TRUE(matches("double x = 1.2l;", DoubleStmt)); +#endif + EXPECT_TRUE(matches("double x = 12e-1;", DoubleStmt)); + EXPECT_FALSE(matches("double x = 1.23;", DoubleStmt)); + + Matcher IntegerStmt = constructMatcher( + "integerLiteral", constructMatcher("equals", VariantValue(42))) + .getTypedMatcher(); + EXPECT_TRUE(matches("int x = 42;", IntegerStmt)); + EXPECT_FALSE(matches("int x = 1;", IntegerStmt)); + + Matcher CharStmt = constructMatcher( + "characterLiteral", constructMatcher("equals", VariantValue('x'))) + .getTypedMatcher(); + EXPECT_TRUE(matches("int x = 'x';", CharStmt)); + EXPECT_TRUE(matches("int x = L'x';", CharStmt)); + EXPECT_TRUE(matches("int x = u'x';", CharStmt)); + EXPECT_TRUE(matches("int x = U'x';", CharStmt)); + EXPECT_FALSE(matches("int x = 120;", CharStmt)); +} + } // end anonymous namespace } // end namespace dynamic } // end namespace ast_matchers diff --git a/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp b/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp index 9df7b780d47f..7d3a07028a1b 100644 --- a/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp +++ b/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp @@ -75,12 +75,16 @@ TEST(VariantValueTest, Assignment) { EXPECT_TRUE(Value.isString()); EXPECT_EQ("A", Value.getString()); EXPECT_TRUE(Value.hasValue()); + EXPECT_FALSE(Value.isBoolean()); + EXPECT_FALSE(Value.isDouble()); EXPECT_FALSE(Value.isUnsigned()); EXPECT_FALSE(Value.isMatcher()); EXPECT_EQ("String", Value.getTypeAsString()); Value = VariantMatcher::SingleMatcher(recordDecl()); EXPECT_TRUE(Value.hasValue()); + EXPECT_FALSE(Value.isBoolean()); + EXPECT_FALSE(Value.isDouble()); EXPECT_FALSE(Value.isUnsigned()); EXPECT_FALSE(Value.isString()); EXPECT_TRUE(Value.isMatcher()); @@ -88,15 +92,36 @@ TEST(VariantValueTest, Assignment) { EXPECT_FALSE(Value.getMatcher().hasTypedMatcher()); EXPECT_EQ("Matcher", Value.getTypeAsString()); + Value = true; + EXPECT_TRUE(Value.isBoolean()); + EXPECT_EQ(true, Value.getBoolean()); + EXPECT_TRUE(Value.hasValue()); + EXPECT_FALSE(Value.isUnsigned()); + EXPECT_FALSE(Value.isMatcher()); + EXPECT_FALSE(Value.isString()); + + Value = 3.14; + EXPECT_TRUE(Value.isDouble()); + EXPECT_EQ(3.14, Value.getDouble()); + EXPECT_TRUE(Value.hasValue()); + EXPECT_FALSE(Value.isBoolean()); + EXPECT_FALSE(Value.isUnsigned()); + EXPECT_FALSE(Value.isMatcher()); + EXPECT_FALSE(Value.isString()); + Value = 17; EXPECT_TRUE(Value.isUnsigned()); EXPECT_EQ(17U, Value.getUnsigned()); + EXPECT_FALSE(Value.isBoolean()); + EXPECT_FALSE(Value.isDouble()); EXPECT_TRUE(Value.hasValue()); EXPECT_FALSE(Value.isMatcher()); EXPECT_FALSE(Value.isString()); Value = VariantValue(); EXPECT_FALSE(Value.hasValue()); + EXPECT_FALSE(Value.isBoolean()); + EXPECT_FALSE(Value.isDouble()); EXPECT_FALSE(Value.isUnsigned()); EXPECT_FALSE(Value.isString()); EXPECT_FALSE(Value.isMatcher()); diff --git a/unittests/Basic/SourceManagerTest.cpp b/unittests/Basic/SourceManagerTest.cpp index aa15e16b851f..8457d3b639f2 100644 --- a/unittests/Basic/SourceManagerTest.cpp +++ b/unittests/Basic/SourceManagerTest.cpp @@ -51,24 +51,6 @@ class SourceManagerTest : public ::testing::Test { IntrusiveRefCntPtr Target; }; -class VoidModuleLoader : public ModuleLoader { - ModuleLoadResult loadModule(SourceLocation ImportLoc, - ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) override { - return ModuleLoadResult(); - } - - void makeModuleVisible(Module *Mod, - Module::NameVisibilityKind Visibility, - SourceLocation ImportLoc) override { } - - GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override - { return nullptr; } - bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override - { return 0; } -}; - TEST_F(SourceManagerTest, isBeforeInTranslationUnit) { const char *source = "#define M(x) [x]\n" @@ -78,7 +60,7 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnit) { FileID mainFileID = SourceMgr.createFileID(std::move(Buf)); SourceMgr.setMainFileID(mainFileID); - VoidModuleLoader ModLoader; + TrivialModuleLoader ModLoader; MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared(), SourceMgr, Diags, LangOpts, &*Target); @@ -199,7 +181,7 @@ TEST_F(SourceManagerTest, getMacroArgExpandedLocation) { HeaderBuf->getBufferSize(), 0); SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf)); - VoidModuleLoader ModLoader; + TrivialModuleLoader ModLoader; MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared(), SourceMgr, Diags, LangOpts, &*Target); @@ -318,7 +300,7 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) { HeaderBuf->getBufferSize(), 0); SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf)); - VoidModuleLoader ModLoader; + TrivialModuleLoader ModLoader; MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared(), SourceMgr, Diags, LangOpts, &*Target); diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp index a44a6845587d..fdb5a08e7a21 100644 --- a/unittests/Format/FormatTestComments.cpp +++ b/unittests/Format/FormatTestComments.cpp @@ -1052,6 +1052,30 @@ TEST_F(FormatTestComments, KeepsTrailingPPCommentsAndSectionCommentsSeparate) { "}", getLLVMStyleWithColumns(80)); } +TEST_F(FormatTestComments, AlignsPPElseEndifComments) { + verifyFormat("#if A\n" + "#else // A\n" + "int iiii;\n" + "#endif // B", + getLLVMStyleWithColumns(20)); + verifyFormat("#if A\n" + "#else // A\n" + "int iiii; // CC\n" + "#endif // B", + getLLVMStyleWithColumns(20)); + EXPECT_EQ("#if A\n" + "#else // A1\n" + " // A2\n" + "int ii;\n" + "#endif // B", + format("#if A\n" + "#else // A1\n" + " // A2\n" + "int ii;\n" + "#endif // B", + getLLVMStyleWithColumns(20))); +} + TEST_F(FormatTestComments, CommentsInStaticInitializers) { EXPECT_EQ( "static SomeType type = {aaaaaaaaaaaaaaaaaaaa, /* comment */\n" @@ -2170,6 +2194,15 @@ TEST_F(FormatTestComments, AlignTrailingComments) { "// long", getLLVMStyleWithColumns(15))); + // Don't align newly broken trailing comments if that would put them over the + // column limit. + EXPECT_EQ("int i, j; // line 1\n" + "int k; // line longg\n" + " // long", + format("int i, j; // line 1\n" + "int k; // line longg long", + getLLVMStyleWithColumns(20))); + // Align comment line sections aligned with the next token with the next // token. EXPECT_EQ("class A {\n" diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 92a113111b6a..e84f470687ec 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -1226,6 +1226,12 @@ TEST_F(FormatTestJS, UnionIntersectionTypes) { verifyFormat("let x: Bar|Baz;"); verifyFormat("let x: Bar|Baz;"); verifyFormat("let x: (Foo|Bar)[];"); + verifyFormat("type X = {\n" + " a: Foo|Bar;\n" + "};"); + verifyFormat("export type X = {\n" + " a: Foo|Bar;\n" + "};"); } TEST_F(FormatTestJS, ClassDeclarations) { @@ -1869,5 +1875,44 @@ TEST_F(FormatTestJS, Exponentiation) { verifyFormat("squared **= 2;"); } +TEST_F(FormatTestJS, NestedLiterals) { + FormatStyle FourSpaces = getGoogleJSStyleWithColumns(15); + FourSpaces.IndentWidth = 4; + verifyFormat("var l = [\n" + " [\n" + " 1,\n" + " ],\n" + "];", FourSpaces); + verifyFormat("var l = [\n" + " {\n" + " 1: 1,\n" + " },\n" + "];", FourSpaces); + verifyFormat("someFunction(\n" + " p1,\n" + " [\n" + " 1,\n" + " ],\n" + ");", FourSpaces); + verifyFormat("someFunction(\n" + " p1,\n" + " {\n" + " 1: 1,\n" + " },\n" + ");", FourSpaces); + verifyFormat("var o = {\n" + " 1: 1,\n" + " 2: {\n" + " 3: 3,\n" + " },\n" + "};", FourSpaces); + verifyFormat("var o = {\n" + " 1: 1,\n" + " 2: [\n" + " 3,\n" + " ],\n" + "};", FourSpaces); +} + } // end namespace tooling } // end namespace clang diff --git a/unittests/Frontend/FrontendActionTest.cpp b/unittests/Frontend/FrontendActionTest.cpp index 68181c705ce8..ce0144538db7 100644 --- a/unittests/Frontend/FrontendActionTest.cpp +++ b/unittests/Frontend/FrontendActionTest.cpp @@ -37,12 +37,11 @@ class TestASTFrontendAction : public ASTFrontendAction { bool ActOnEndOfTranslationUnit; std::vector decl_names; - bool BeginSourceFileAction(CompilerInstance &ci, - StringRef filename) override { + bool BeginSourceFileAction(CompilerInstance &ci) override { if (EnableIncrementalProcessing) ci.getPreprocessor().enableIncrementalProcessing(); - return ASTFrontendAction::BeginSourceFileAction(ci, filename); + return ASTFrontendAction::BeginSourceFileAction(ci); } std::unique_ptr CreateASTConsumer(CompilerInstance &CI, diff --git a/unittests/Lex/LexerTest.cpp b/unittests/Lex/LexerTest.cpp index b5a6fd90d08f..e2507d3580d3 100644 --- a/unittests/Lex/LexerTest.cpp +++ b/unittests/Lex/LexerTest.cpp @@ -27,24 +27,6 @@ using namespace clang; namespace { -class VoidModuleLoader : public ModuleLoader { - ModuleLoadResult loadModule(SourceLocation ImportLoc, - ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) override { - return ModuleLoadResult(); - } - - void makeModuleVisible(Module *Mod, - Module::NameVisibilityKind Visibility, - SourceLocation ImportLoc) override { } - - GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override - { return nullptr; } - bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override - { return 0; } -}; - // The test fixture. class LexerTest : public ::testing::Test { protected: @@ -64,7 +46,7 @@ class LexerTest : public ::testing::Test { llvm::MemoryBuffer::getMemBuffer(Source); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); - VoidModuleLoader ModLoader; + TrivialModuleLoader ModLoader; MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared(), SourceMgr, Diags, LangOpts, Target.get()); diff --git a/unittests/Lex/PPCallbacksTest.cpp b/unittests/Lex/PPCallbacksTest.cpp index 0841791e0863..67b56a601c71 100644 --- a/unittests/Lex/PPCallbacksTest.cpp +++ b/unittests/Lex/PPCallbacksTest.cpp @@ -32,25 +32,6 @@ using namespace clang; namespace { -// Stub out module loading. -class VoidModuleLoader : public ModuleLoader { - ModuleLoadResult loadModule(SourceLocation ImportLoc, - ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) override { - return ModuleLoadResult(); - } - - void makeModuleVisible(Module *Mod, - Module::NameVisibilityKind Visibility, - SourceLocation ImportLoc) override { } - - GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override - { return nullptr; } - bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override - { return 0; } -}; - // Stub to collect data from InclusionDirective callbacks. class InclusionDirectiveCallbacks : public PPCallbacks { public: @@ -161,7 +142,7 @@ class PPCallbacksTest : public ::testing::Test { llvm::MemoryBuffer::getMemBuffer(SourceText); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); - VoidModuleLoader ModLoader; + TrivialModuleLoader ModLoader; MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared(), SourceMgr, @@ -199,7 +180,7 @@ class PPCallbacksTest : public ::testing::Test { llvm::MemoryBuffer::getMemBuffer(SourceText, "test.cl"); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf))); - VoidModuleLoader ModLoader; + TrivialModuleLoader ModLoader; MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared(), SourceMgr, Diags, OpenCLLangOpts, Target.get()); diff --git a/unittests/Lex/PPConditionalDirectiveRecordTest.cpp b/unittests/Lex/PPConditionalDirectiveRecordTest.cpp index b635604e0982..f7b6f717a1db 100644 --- a/unittests/Lex/PPConditionalDirectiveRecordTest.cpp +++ b/unittests/Lex/PPConditionalDirectiveRecordTest.cpp @@ -51,24 +51,6 @@ class PPConditionalDirectiveRecordTest : public ::testing::Test { IntrusiveRefCntPtr Target; }; -class VoidModuleLoader : public ModuleLoader { - ModuleLoadResult loadModule(SourceLocation ImportLoc, - ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) override { - return ModuleLoadResult(); - } - - void makeModuleVisible(Module *Mod, - Module::NameVisibilityKind Visibility, - SourceLocation ImportLoc) override { } - - GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override - { return nullptr; } - bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override - { return 0; } -}; - TEST_F(PPConditionalDirectiveRecordTest, PPRecAPI) { const char *source = "0 1\n" @@ -93,7 +75,7 @@ TEST_F(PPConditionalDirectiveRecordTest, PPRecAPI) { llvm::MemoryBuffer::getMemBuffer(source); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); - VoidModuleLoader ModLoader; + TrivialModuleLoader ModLoader; MemoryBufferCache PCMCache; HeaderSearch HeaderInfo(std::make_shared(), SourceMgr, Diags, LangOpts, Target.get()); diff --git a/unittests/Tooling/CommentHandlerTest.cpp b/unittests/Tooling/CommentHandlerTest.cpp index b42b28b9c948..9c3abdc4b15e 100644 --- a/unittests/Tooling/CommentHandlerTest.cpp +++ b/unittests/Tooling/CommentHandlerTest.cpp @@ -70,8 +70,7 @@ class CommentHandlerVisitor : public TestVisitor, CommentHandlerAction(CommentHandlerVisitor *Visitor) : TestAction(Visitor) { } - bool BeginSourceFileAction(CompilerInstance &CI, - StringRef FileName) override { + bool BeginSourceFileAction(CompilerInstance &CI) override { CommentHandlerVisitor *V = static_cast(this->Visitor); V->PP = &CI.getPreprocessor(); diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp index 68b5ed21059b..b179f033d357 100644 --- a/unittests/Tooling/ToolingTest.cpp +++ b/unittests/Tooling/ToolingTest.cpp @@ -203,7 +203,7 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) { struct VerifyEndCallback : public SourceFileCallbacks { VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {} - bool handleBeginSource(CompilerInstance &CI, StringRef Filename) override { + bool handleBeginSource(CompilerInstance &CI) override { ++BeginCalled; return true; } From 7edd24de96f22ad70fd3ca16a3c51723383cd58b Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 10 Jun 2017 13:44:32 +0000 Subject: [PATCH 13/22] Vendor import of compiler-rt trunk r305145: https://llvm.org/svn/llvm-project/compiler-rt/trunk@305145 --- CMakeLists.txt | 2 +- lib/asan/asan_allocator.cc | 4 +- lib/asan/asan_allocator.h | 2 - lib/asan/asan_interceptors.cc | 17 --- lib/asan/asan_malloc_linux.cc | 22 ++-- lib/lsan/lsan_common.cc | 3 - lib/lsan/lsan_common_linux.cc | 23 +--- lib/lsan/lsan_interceptors.cc | 24 ---- lib/msan/msan_allocator.cc | 96 +++++++++++++- lib/msan/msan_allocator.h | 97 -------------- lib/msan/msan_interceptors.cc | 2 - .../sanitizer_common_interceptors.inc | 5 +- lib/sanitizer_common/sanitizer_linux.cc | 10 ++ lib/sanitizer_common/sanitizer_platform.h | 9 -- .../symbolizer/scripts/build_symbolizer.sh | 3 +- lib/tsan/rtl/tsan_rtl_thread.cc | 1 + test/asan/TestCases/Darwin/atos-symbolizer.cc | 2 +- .../TestCases/Linux/asan_preload_test-3.cc | 33 +++++ .../TestCases/Posix/halt_on_error-torture.cc | 6 +- test/msan/Linux/strerror_r.cc | 18 +++ test/profile/Linux/instrprof-alloc.test | 4 +- .../Linux/instrprof-value-prof-warn.test | 2 +- .../TestCases/Linux/allocator_fork_no_hang.cc | 118 ------------------ .../sanitizer_coverage_inline8bit_counter.cc | 2 +- test/tsan/strerror_r.cc | 29 +++++ 25 files changed, 223 insertions(+), 311 deletions(-) create mode 100644 test/asan/TestCases/Linux/asan_preload_test-3.cc create mode 100644 test/msan/Linux/strerror_r.cc delete mode 100644 test/sanitizer_common/TestCases/Linux/allocator_fork_no_hang.cc create mode 100644 test/tsan/strerror_r.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index b522c340d669..51769088a992 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,7 +255,7 @@ if(EXISTS ${COMPILER_RT_LLD_PATH}/ AND LLVM_TOOL_LLD_BUILD) set(COMPILER_RT_HAS_LLD TRUE) else() set(COMPILER_RT_LLD_PATH ${LLVM_MAIN_SRC_DIR}/../lld) - if(EXISTS ${COMPILER_RT_LLD_PATH}/) + if(EXISTS ${COMPILER_RT_LLD_PATH}/ AND LLVM_TOOL_LLD_BUILD) set(COMPILER_RT_HAS_LLD TRUE) else() set(COMPILER_RT_HAS_LLD FALSE) diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc index db5a683e283d..7010b6023614 100644 --- a/lib/asan/asan_allocator.cc +++ b/lib/asan/asan_allocator.cc @@ -47,6 +47,8 @@ static u32 RZSize2Log(u32 rz_size) { return res; } +static AsanAllocator &get_allocator(); + // The memory chunk allocated from the underlying allocator looks like this: // L L L L L L H H U U U U U U R R // L -- left redzone words (0 or more bytes) @@ -717,7 +719,7 @@ struct Allocator { static Allocator instance(LINKER_INITIALIZED); -AsanAllocator &get_allocator() { +static AsanAllocator &get_allocator() { return instance.allocator; } diff --git a/lib/asan/asan_allocator.h b/lib/asan/asan_allocator.h index ce3e25dc5094..ad1aeb58a86b 100644 --- a/lib/asan/asan_allocator.h +++ b/lib/asan/asan_allocator.h @@ -213,7 +213,5 @@ void asan_mz_force_unlock(); void PrintInternalAllocatorStats(); void AsanSoftRssLimitExceededCallback(bool exceeded); -AsanAllocator &get_allocator(); - } // namespace __asan #endif // ASAN_ALLOCATOR_H diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index 4682fba3392c..264d5aee8ceb 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -22,7 +22,6 @@ #include "asan_stats.h" #include "asan_suppressions.h" #include "lsan/lsan_common.h" -#include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_libc.h" #if SANITIZER_POSIX @@ -705,25 +704,9 @@ INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, #endif // ASAN_INTERCEPT___CXA_ATEXIT #if ASAN_INTERCEPT_FORK -static void BeforeFork() { - if (SANITIZER_LINUX) { - get_allocator().ForceLock(); - StackDepotLockAll(); - } -} - -static void AfterFork() { - if (SANITIZER_LINUX) { - StackDepotUnlockAll(); - get_allocator().ForceUnlock(); - } -} - INTERCEPTOR(int, fork, void) { ENSURE_ASAN_INITED(); - BeforeFork(); int pid = REAL(fork)(); - AfterFork(); return pid; } #endif // ASAN_INTERCEPT_FORK diff --git a/lib/asan/asan_malloc_linux.cc b/lib/asan/asan_malloc_linux.cc index 8c99d3bc9257..fd40f47db1c4 100644 --- a/lib/asan/asan_malloc_linux.cc +++ b/lib/asan/asan_malloc_linux.cc @@ -60,36 +60,42 @@ INTERCEPTOR(void, cfree, void *ptr) { #endif // SANITIZER_INTERCEPT_CFREE INTERCEPTOR(void*, malloc, uptr size) { - if (UNLIKELY(!asan_inited)) + if (UNLIKELY(asan_init_is_running)) // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. return AllocateFromLocalPool(size); + ENSURE_ASAN_INITED(); GET_STACK_TRACE_MALLOC; return asan_malloc(size, &stack); } INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { - if (UNLIKELY(!asan_inited)) + if (UNLIKELY(asan_init_is_running)) // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. return AllocateFromLocalPool(nmemb * size); + ENSURE_ASAN_INITED(); GET_STACK_TRACE_MALLOC; return asan_calloc(nmemb, size, &stack); } INTERCEPTOR(void*, realloc, void *ptr, uptr size) { - GET_STACK_TRACE_MALLOC; if (UNLIKELY(IsInDlsymAllocPool(ptr))) { - uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; - uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); + const uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; + const uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); void *new_ptr; - if (UNLIKELY(!asan_inited)) { + if (UNLIKELY(asan_init_is_running)) { new_ptr = AllocateFromLocalPool(size); } else { - copy_size = size; - new_ptr = asan_malloc(copy_size, &stack); + ENSURE_ASAN_INITED(); + GET_STACK_TRACE_MALLOC; + new_ptr = asan_malloc(size, &stack); } internal_memcpy(new_ptr, ptr, copy_size); return new_ptr; } + if (UNLIKELY(asan_init_is_running)) + return AllocateFromLocalPool(size); + ENSURE_ASAN_INITED(); + GET_STACK_TRACE_MALLOC; return asan_realloc(ptr, size, &stack); } diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc index d4f670681fa5..a5ffc6835f5f 100644 --- a/lib/lsan/lsan_common.cc +++ b/lib/lsan/lsan_common.cc @@ -408,9 +408,6 @@ static void MarkInvalidPCCb(uptr chunk, void *arg) { // On Linux, handles dynamically allocated TLS blocks by treating all chunks // allocated from ld-linux.so as reachable. -// On Linux, treats all chunks allocated from ld-linux.so as reachable, which -// covers dynamically allocated TLS blocks, internal dynamic loader's loaded -// modules accounting etc. // Dynamic TLS blocks contain the TLS variables of dynamically loaded modules. // They are allocated with a __libc_memalign() call in allocate_and_init() // (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those diff --git a/lib/lsan/lsan_common_linux.cc b/lib/lsan/lsan_common_linux.cc index 2e4095b495fe..c903be42d1e7 100644 --- a/lib/lsan/lsan_common_linux.cc +++ b/lib/lsan/lsan_common_linux.cc @@ -23,10 +23,6 @@ #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_stackdepot.h" -#if SANITIZER_USE_GETAUXVAL -#include -#endif // SANITIZER_USE_GETAUXVAL - namespace __lsan { static const char kLinkerName[] = "ld"; @@ -34,12 +30,8 @@ static const char kLinkerName[] = "ld"; static char linker_placeholder[sizeof(LoadedModule)] ALIGNED(64); static LoadedModule *linker = nullptr; -static bool IsLinker(const LoadedModule& module) { -#if SANITIZER_USE_GETAUXVAL - return module.base_address() == getauxval(AT_BASE); -#else - return LibraryNameIs(module.full_name(), kLinkerName); -#endif // SANITIZER_USE_GETAUXVAL +static bool IsLinker(const char* full_name) { + return LibraryNameIs(full_name, kLinkerName); } __attribute__((tls_model("initial-exec"))) @@ -57,25 +49,22 @@ void InitializePlatformSpecificModules() { ListOfModules modules; modules.init(); for (LoadedModule &module : modules) { - if (!IsLinker(module)) - continue; + if (!IsLinker(module.full_name())) continue; if (linker == nullptr) { linker = reinterpret_cast(linker_placeholder); *linker = module; module = LoadedModule(); } else { VReport(1, "LeakSanitizer: Multiple modules match \"%s\". " - "TLS and other allocations originating from linker might be " - "falsely reported as leaks.\n", kLinkerName); + "TLS will not be handled correctly.\n", kLinkerName); linker->clear(); linker = nullptr; return; } } if (linker == nullptr) { - VReport(1, "LeakSanitizer: Dynamic linker not found. TLS and other " - "allocations originating from linker might be falsely reported " - "as leaks.\n"); + VReport(1, "LeakSanitizer: Dynamic linker not found. " + "TLS will not be handled correctly.\n"); } } diff --git a/lib/lsan/lsan_interceptors.cc b/lib/lsan/lsan_interceptors.cc index a0a59daa07ae..9e39a7d1944d 100644 --- a/lib/lsan/lsan_interceptors.cc +++ b/lib/lsan/lsan_interceptors.cc @@ -22,7 +22,6 @@ #include "sanitizer_common/sanitizer_platform_interceptors.h" #include "sanitizer_common/sanitizer_platform_limits_posix.h" #include "sanitizer_common/sanitizer_posix.h" -#include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" #include "lsan.h" #include "lsan_allocator.h" @@ -98,28 +97,6 @@ INTERCEPTOR(void*, valloc, uptr size) { } #endif -static void BeforeFork() { - if (SANITIZER_LINUX) { - LockAllocator(); - StackDepotLockAll(); - } -} - -static void AfterFork() { - if (SANITIZER_LINUX) { - StackDepotUnlockAll(); - UnlockAllocator(); - } -} - -INTERCEPTOR(int, fork, void) { - ENSURE_LSAN_INITED; - BeforeFork(); - int pid = REAL(fork)(); - AfterFork(); - return pid; -} - #if SANITIZER_INTERCEPT_MEMALIGN INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { ENSURE_LSAN_INITED; @@ -359,7 +336,6 @@ void InitializeInterceptors() { LSAN_MAYBE_INTERCEPT_MALLOPT; INTERCEPT_FUNCTION(pthread_create); INTERCEPT_FUNCTION(pthread_join); - INTERCEPT_FUNCTION(fork); if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { Report("LeakSanitizer: failed to create thread key.\n"); diff --git a/lib/msan/msan_allocator.cc b/lib/msan/msan_allocator.cc index f76b01de0924..1be573faa412 100644 --- a/lib/msan/msan_allocator.cc +++ b/lib/msan/msan_allocator.cc @@ -12,6 +12,8 @@ // MemorySanitizer allocator. //===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_allocator.h" +#include "sanitizer_common/sanitizer_allocator_interface.h" #include "msan.h" #include "msan_allocator.h" #include "msan_origin.h" @@ -20,12 +22,102 @@ namespace __msan { +struct Metadata { + uptr requested_size; +}; + +struct MsanMapUnmapCallback { + void OnMap(uptr p, uptr size) const {} + void OnUnmap(uptr p, uptr size) const { + __msan_unpoison((void *)p, size); + + // We are about to unmap a chunk of user memory. + // Mark the corresponding shadow memory as not needed. + uptr shadow_p = MEM_TO_SHADOW(p); + ReleaseMemoryPagesToOS(shadow_p, shadow_p + size); + if (__msan_get_track_origins()) { + uptr origin_p = MEM_TO_ORIGIN(p); + ReleaseMemoryPagesToOS(origin_p, origin_p + size); + } + } +}; + +#if defined(__mips64) + static const uptr kMaxAllowedMallocSize = 2UL << 30; + static const uptr kRegionSizeLog = 20; + static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; + typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; + + struct AP32 { + static const uptr kSpaceBeg = 0; + static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; + static const uptr kMetadataSize = sizeof(Metadata); + typedef __sanitizer::CompactSizeClassMap SizeClassMap; + static const uptr kRegionSizeLog = __msan::kRegionSizeLog; + typedef __msan::ByteMap ByteMap; + typedef MsanMapUnmapCallback MapUnmapCallback; + static const uptr kFlags = 0; + }; + typedef SizeClassAllocator32 PrimaryAllocator; +#elif defined(__x86_64__) +#if SANITIZER_LINUX && !defined(MSAN_LINUX_X86_64_OLD_MAPPING) + static const uptr kAllocatorSpace = 0x700000000000ULL; +#else + static const uptr kAllocatorSpace = 0x600000000000ULL; +#endif + static const uptr kMaxAllowedMallocSize = 8UL << 30; + + struct AP64 { // Allocator64 parameters. Deliberately using a short name. + static const uptr kSpaceBeg = kAllocatorSpace; + static const uptr kSpaceSize = 0x40000000000; // 4T. + static const uptr kMetadataSize = sizeof(Metadata); + typedef DefaultSizeClassMap SizeClassMap; + typedef MsanMapUnmapCallback MapUnmapCallback; + static const uptr kFlags = 0; + }; + + typedef SizeClassAllocator64 PrimaryAllocator; + +#elif defined(__powerpc64__) + static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G + + struct AP64 { // Allocator64 parameters. Deliberately using a short name. + static const uptr kSpaceBeg = 0x300000000000; + static const uptr kSpaceSize = 0x020000000000; // 2T. + static const uptr kMetadataSize = sizeof(Metadata); + typedef DefaultSizeClassMap SizeClassMap; + typedef MsanMapUnmapCallback MapUnmapCallback; + static const uptr kFlags = 0; + }; + + typedef SizeClassAllocator64 PrimaryAllocator; +#elif defined(__aarch64__) + static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G + static const uptr kRegionSizeLog = 20; + static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; + typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; + + struct AP32 { + static const uptr kSpaceBeg = 0; + static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; + static const uptr kMetadataSize = sizeof(Metadata); + typedef __sanitizer::CompactSizeClassMap SizeClassMap; + static const uptr kRegionSizeLog = __msan::kRegionSizeLog; + typedef __msan::ByteMap ByteMap; + typedef MsanMapUnmapCallback MapUnmapCallback; + static const uptr kFlags = 0; + }; + typedef SizeClassAllocator32 PrimaryAllocator; +#endif +typedef SizeClassAllocatorLocalCache AllocatorCache; +typedef LargeMmapAllocator SecondaryAllocator; +typedef CombinedAllocator Allocator; + static Allocator allocator; static AllocatorCache fallback_allocator_cache; static SpinMutex fallback_mutex; -Allocator &get_allocator() { return allocator; } - void MsanAllocatorInit() { allocator.Init( common_flags()->allocator_may_return_null, diff --git a/lib/msan/msan_allocator.h b/lib/msan/msan_allocator.h index abd4ea678523..407942e54c1a 100644 --- a/lib/msan/msan_allocator.h +++ b/lib/msan/msan_allocator.h @@ -15,106 +15,9 @@ #define MSAN_ALLOCATOR_H #include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_allocator.h" -#include "sanitizer_common/sanitizer_allocator_interface.h" namespace __msan { -struct Metadata { - uptr requested_size; -}; - -struct MsanMapUnmapCallback { - void OnMap(uptr p, uptr size) const {} - void OnUnmap(uptr p, uptr size) const { - __msan_unpoison((void *)p, size); - - // We are about to unmap a chunk of user memory. - // Mark the corresponding shadow memory as not needed. - uptr shadow_p = MEM_TO_SHADOW(p); - ReleaseMemoryPagesToOS(shadow_p, shadow_p + size); - if (__msan_get_track_origins()) { - uptr origin_p = MEM_TO_ORIGIN(p); - ReleaseMemoryPagesToOS(origin_p, origin_p + size); - } - } -}; - -#if defined(__mips64) - static const uptr kMaxAllowedMallocSize = 2UL << 30; - static const uptr kRegionSizeLog = 20; - static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; - typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; - - struct AP32 { - static const uptr kSpaceBeg = 0; - static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; - static const uptr kMetadataSize = sizeof(Metadata); - typedef __sanitizer::CompactSizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = __msan::kRegionSizeLog; - typedef __msan::ByteMap ByteMap; - typedef MsanMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - }; - typedef SizeClassAllocator32 PrimaryAllocator; -#elif defined(__x86_64__) -#if SANITIZER_LINUX && !defined(MSAN_LINUX_X86_64_OLD_MAPPING) - static const uptr kAllocatorSpace = 0x700000000000ULL; -#else - static const uptr kAllocatorSpace = 0x600000000000ULL; -#endif - static const uptr kMaxAllowedMallocSize = 8UL << 30; - - struct AP64 { // Allocator64 parameters. Deliberately using a short name. - static const uptr kSpaceBeg = kAllocatorSpace; - static const uptr kSpaceSize = 0x40000000000; // 4T. - static const uptr kMetadataSize = sizeof(Metadata); - typedef DefaultSizeClassMap SizeClassMap; - typedef MsanMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - }; - - typedef SizeClassAllocator64 PrimaryAllocator; - -#elif defined(__powerpc64__) - static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G - - struct AP64 { // Allocator64 parameters. Deliberately using a short name. - static const uptr kSpaceBeg = 0x300000000000; - static const uptr kSpaceSize = 0x020000000000; // 2T. - static const uptr kMetadataSize = sizeof(Metadata); - typedef DefaultSizeClassMap SizeClassMap; - typedef MsanMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - }; - - typedef SizeClassAllocator64 PrimaryAllocator; -#elif defined(__aarch64__) - static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G - static const uptr kRegionSizeLog = 20; - static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; - typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; - - struct AP32 { - static const uptr kSpaceBeg = 0; - static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; - static const uptr kMetadataSize = sizeof(Metadata); - typedef __sanitizer::CompactSizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = __msan::kRegionSizeLog; - typedef __msan::ByteMap ByteMap; - typedef MsanMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - }; - typedef SizeClassAllocator32 PrimaryAllocator; -#endif -typedef SizeClassAllocatorLocalCache AllocatorCache; -typedef LargeMmapAllocator SecondaryAllocator; -typedef CombinedAllocator Allocator; - - -Allocator &get_allocator(); - struct MsanThreadLocalMallocStorage { uptr quarantine_cache[16]; // Allocator cache contains atomic_uint64_t which must be 8-byte aligned. diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index fbc2ea4fec9d..0f50693441be 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -1201,7 +1201,6 @@ INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) { } static void BeforeFork() { - get_allocator().ForceLock(); StackDepotLockAll(); ChainedOriginDepotLockAll(); } @@ -1209,7 +1208,6 @@ static void BeforeFork() { static void AfterFork() { ChainedOriginDepotUnlockAll(); StackDepotUnlockAll(); - get_allocator().ForceUnlock(); } INTERCEPTOR(int, fork, void) { diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index c0c08a031e9b..6ca431d8ad82 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3395,7 +3395,10 @@ INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) { // its metadata. See // https://github.com/google/sanitizers/issues/321. char *res = REAL(strerror_r)(errnum, buf, buflen); - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + if (res == buf) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + else + COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); return res; } #endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE || diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index 7bc7682dd962..cec2f264cbc4 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -75,6 +75,16 @@ extern char **environ; // provided by crt1 #include #endif +#ifndef __GLIBC_PREREQ +#define __GLIBC_PREREQ(x, y) 0 +#endif + +#if SANITIZER_LINUX && __GLIBC_PREREQ(2, 16) +# define SANITIZER_USE_GETAUXVAL 1 +#else +# define SANITIZER_USE_GETAUXVAL 0 +#endif + #if SANITIZER_USE_GETAUXVAL #include #endif diff --git a/lib/sanitizer_common/sanitizer_platform.h b/lib/sanitizer_common/sanitizer_platform.h index 8fa3f7ab66fc..49732aa32323 100644 --- a/lib/sanitizer_common/sanitizer_platform.h +++ b/lib/sanitizer_common/sanitizer_platform.h @@ -269,14 +269,5 @@ # define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0 #endif -#ifndef __GLIBC_PREREQ -#define __GLIBC_PREREQ(x, y) 0 -#endif - -#if SANITIZER_LINUX && __GLIBC_PREREQ(2, 16) -# define SANITIZER_USE_GETAUXVAL 1 -#else -# define SANITIZER_USE_GETAUXVAL 0 -#endif #endif // SANITIZER_PLATFORM_H diff --git a/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh b/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh index 4a0fb03c4c70..c5865ecfee6c 100755 --- a/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh +++ b/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh @@ -129,7 +129,7 @@ if [[ ! -d ${LLVM_BUILD} ]]; then $LLVM_SRC fi cd ${LLVM_BUILD} -ninja LLVMSymbolize LLVMObject LLVMDebugInfoDWARF LLVMSupport LLVMDebugInfoPDB LLVMMC +ninja LLVMSymbolize LLVMObject LLVMBinaryFormat LLVMDebugInfoDWARF LLVMSupport LLVMDebugInfoPDB LLVMMC cd ${BUILD_DIR} rm -rf ${SYMBOLIZER_BUILD} @@ -148,6 +148,7 @@ $SCRIPT_DIR/ar_to_bc.sh $LIBCXX_BUILD/lib/libc++.a \ $LIBCXX_BUILD/lib/libc++abi.a \ $LLVM_BUILD/lib/libLLVMSymbolize.a \ $LLVM_BUILD/lib/libLLVMObject.a \ + $LLVM_BUILD/lib/libLLVMBinaryFormat.a \ $LLVM_BUILD/lib/libLLVMDebugInfoDWARF.a \ $LLVM_BUILD/lib/libLLVMSupport.a \ $LLVM_BUILD/lib/libLLVMDebugInfoPDB.a \ diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc index edb60980c76f..67eebf5d0c38 100644 --- a/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/lib/tsan/rtl/tsan_rtl_thread.cc @@ -345,6 +345,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, StatInc(thr, StatMopRange); if (*shadow_mem == kShadowRodata) { + DCHECK(!is_write); // Access to .rodata section, no races here. // Measurements show that it can be 10-20% of all memory accesses. StatInc(thr, StatMopRangeRodata); diff --git a/test/asan/TestCases/Darwin/atos-symbolizer.cc b/test/asan/TestCases/Darwin/atos-symbolizer.cc index 7b091c4d681c..e7d7e7a17fb7 100644 --- a/test/asan/TestCases/Darwin/atos-symbolizer.cc +++ b/test/asan/TestCases/Darwin/atos-symbolizer.cc @@ -4,7 +4,7 @@ // RUN: %env_asan_opts=verbosity=2 ASAN_SYMBOLIZER_PATH=$(which atos) not %run %t 2>&1 | FileCheck %s // Path returned by `which atos` is invalid on iOS. -// UNSUPPORTED: ios +// UNSUPPORTED: ios, i386-darwin #include #include diff --git a/test/asan/TestCases/Linux/asan_preload_test-3.cc b/test/asan/TestCases/Linux/asan_preload_test-3.cc new file mode 100644 index 000000000000..041669b56a45 --- /dev/null +++ b/test/asan/TestCases/Linux/asan_preload_test-3.cc @@ -0,0 +1,33 @@ +// Regression test for PR33206 +// +// RUN: %clang -DDYN=1 -DMALLOC=1 -fPIC -shared %s -o %t-dso1.so +// RUN: %clang -DDYN=1 -DMALLOC=1 -fPIC -shared %s -o %t-dso2.so %t-dso1.so +// RUN: %clang %s -o %t-1 %t-dso2.so +// RUN: env LD_PRELOAD=%shared_libasan %run %t-1 2>&1 | FileCheck %s +// RUN: %clang -DDYN=1 -DREALLOC=1 -fPIC -shared %s -o %t-dso3.so +// RUN: %clang -DDYN=1 -DREALLOC=1 -fPIC -shared %s -o %t-dso4.so %t-dso3.so +// RUN: %clang %s -o %t-2 %t-dso4.so +// RUN: env LD_PRELOAD=%shared_libasan %run %t-2 2>&1 | FileCheck %s +// REQUIRES: asan-dynamic-runtime + +#include +#include + +#ifdef DYN +__attribute__((constructor)) void foo() { + void *p; +#ifdef MALLOC + p = malloc(1 << 20); +#endif +#ifdef REALLOC + p = realloc (0, 1 << 20); +#endif + free(p); +} +#else +int main() { + // CHECK: Success + printf("Success\n"); + return 0; +} +#endif diff --git a/test/asan/TestCases/Posix/halt_on_error-torture.cc b/test/asan/TestCases/Posix/halt_on_error-torture.cc index 1b26173d713f..829568e2682b 100644 --- a/test/asan/TestCases/Posix/halt_on_error-torture.cc +++ b/test/asan/TestCases/Posix/halt_on_error-torture.cc @@ -10,12 +10,12 @@ // // Collisions are unlikely but still possible so we need the ||. // RUN: rm -f 10.txt -// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 10 20 >>10.txt 2>&1 || true +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false:exitcode=0 %run %t 10 20 2>&1 | cat > 10.txt // RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 10.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 10.txt // // Collisions are unlikely but still possible so we need the ||. // RUN: rm -f 20.txt -// RUN: %env_asan_opts=halt_on_error=false %run %t 10 20 >>20.txt 2>&1 || true +// RUN: %env_asan_opts=halt_on_error=false:exitcode=0 %run %t 10 20 2>&1 | cat > 20.txt // RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 20.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 20.txt #include @@ -38,7 +38,7 @@ void *run(void *arg) { unsigned seed = (unsigned)(size_t)arg; volatile char tmp[2]; - __asan_poison_memory_region(&tmp, sizeof(tmp)); + __asan_poison_memory_region(&tmp, sizeof(tmp)); for (size_t i = 0; i < niter; ++i) { random_delay(&seed); diff --git a/test/msan/Linux/strerror_r.cc b/test/msan/Linux/strerror_r.cc new file mode 100644 index 000000000000..aec653f9c025 --- /dev/null +++ b/test/msan/Linux/strerror_r.cc @@ -0,0 +1,18 @@ +// RUN: %clang_msan -O0 -g %s -o %t && %run %t + +#include +#include +#include + +int main() { + char buf[1000]; + char *res = strerror_r(EINVAL, buf, sizeof(buf)); + assert(res); + volatile int z = strlen(res); + + res = strerror_r(-1, buf, sizeof(buf)); + assert(res); + z = strlen(res); + + return 0; +} diff --git a/test/profile/Linux/instrprof-alloc.test b/test/profile/Linux/instrprof-alloc.test index 752b10892170..4db764704adb 100644 --- a/test/profile/Linux/instrprof-alloc.test +++ b/test/profile/Linux/instrprof-alloc.test @@ -1,6 +1,6 @@ -// RUN: %clang_profgen -Xclang -fprofile-instrument=llvm -fuse-ld=gold -Wl,-wrap,malloc -Wl,-wrap,calloc -o %t -O3 %S/../Inputs/instrprof-alloc.c +// RUN: %clang_pgogen -fuse-ld=gold -Wl,-wrap,malloc -Wl,-wrap,calloc -o %t -O3 %S/../Inputs/instrprof-alloc.c // RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t -// RUN: %clang_profgen -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=false -fuse-ld=gold -Wl,-wrap,malloc -Wl,-wrap,calloc -o %t.dyn -O3 %S/../Inputs/instrprof-alloc.c +// RUN: %clang_pgogen -mllvm -vp-static-alloc=false -fuse-ld=gold -Wl,-wrap,malloc -Wl,-wrap,calloc -o %t.dyn -O3 %S/../Inputs/instrprof-alloc.c // RUN: env LLVM_PROFILE_FILE=%t.profraw not %run %t.dyn diff --git a/test/profile/Linux/instrprof-value-prof-warn.test b/test/profile/Linux/instrprof-value-prof-warn.test index 26502cc900dc..6ca1603fb244 100644 --- a/test/profile/Linux/instrprof-value-prof-warn.test +++ b/test/profile/Linux/instrprof-value-prof-warn.test @@ -1,4 +1,4 @@ -RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=true -DSTRESS=1 -o %t.ir.warn %S/../Inputs/instrprof-value-prof-real.c +RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -DSTRESS=1 -o %t.ir.warn %S/../Inputs/instrprof-value-prof-real.c RUN: env LLVM_PROFILE_FILE=%t.ir.profraw LLVM_VP_MAX_NUM_VALS_PER_SITE=255 %run %t.ir.warn 2>&1 |FileCheck --check-prefix=WARNING %s # Test that enough static counters have been allocated RUN: env LLVM_PROFILE_FILE=%t.ir.profraw LLVM_VP_MAX_NUM_VALS_PER_SITE=150 %run %t.ir.warn 2>&1 |FileCheck --check-prefix=NOWARNING --allow-empty %s diff --git a/test/sanitizer_common/TestCases/Linux/allocator_fork_no_hang.cc b/test/sanitizer_common/TestCases/Linux/allocator_fork_no_hang.cc deleted file mode 100644 index d159d85ee2d6..000000000000 --- a/test/sanitizer_common/TestCases/Linux/allocator_fork_no_hang.cc +++ /dev/null @@ -1,118 +0,0 @@ -// https://github.com/google/sanitizers/issues/774 -// Test that sanitizer allocator is fork-safe. -// Run a number of threads that perform memory allocation/deallocation, then fork -// and verify that malloc/free do not deadlock in the child process. - -// RUN: %clangxx -std=c++11 -O0 %s -o %t -// RUN: ASAN_OPTIONS=detect_leaks=0 %run %t 2>&1 | FileCheck %s - -// Fun fact: if test output is redirected to a file (as opposed to -// being piped directly to FileCheck), we may lose some "done"s due to -// a kernel bug: -// https://lkml.org/lkml/2014/2/17/324 - -// UNSUPPORTED: tsan - -// Flaky on PPC64. -// UNSUPPORTED: powerpc64-target-arch -// UNSUPPORTED: powerpc64le-target-arch - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int done; - -void *worker(void *arg) { - while (true) { - void *p = malloc(4); - if (__atomic_load_n(&done, __ATOMIC_RELAXED)) - return 0; - } - return 0; -} - -// Run through malloc/free in the child process. -// This can deadlock on allocator cache refilling. -void child() { - for (int i = 0; i < 10000; ++i) { - void *p = malloc(4); - } - write(2, "done\n", 5); -} - -void test() { - const int kThreads = 10; - pthread_t t[kThreads]; - for (int i = 0; i < kThreads; ++i) - pthread_create(&t[i], NULL, worker, (void*)(long)i); - usleep(100000); - pid_t pid = fork(); - if (pid) { - // parent - __atomic_store_n(&done, 1, __ATOMIC_RELAXED); - pid_t p; - while ((p = wait(NULL)) == -1) { } - } else { - // child - child(); - } -} - -int main() { - const int kChildren = 30; - for (int i = 0; i < kChildren; ++i) { - pid_t pid = fork(); - if (pid) { - // parent - } else { - test(); - exit(0); - } - } - - for (int i = 0; i < kChildren; ++i) { - pid_t p; - while ((p = wait(NULL)) == -1) { } - } - - return 0; -} - -// Expect 30 (== kChildren) "done" messages. -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done -// CHECK: done diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc index b7246ebf2751..1a4ad1f066d9 100644 --- a/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc +++ b/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc @@ -1,7 +1,7 @@ // Tests -fsanitize-coverage=inline-8bit-counters // // REQUIRES: has_sancovcc,stable-runtime -// UNSUPPORTED: i386-darwin +// UNSUPPORTED: i386-darwin, x86_64-darwin, x86_64h-darwin // // RUN: %clangxx -O0 %s -fsanitize-coverage=inline-8bit-counters 2>&1 diff --git a/test/tsan/strerror_r.cc b/test/tsan/strerror_r.cc new file mode 100644 index 000000000000..06c92d3bb641 --- /dev/null +++ b/test/tsan/strerror_r.cc @@ -0,0 +1,29 @@ +// RUN: %clangxx_tsan -O1 -DTEST_ERROR=ERANGE %s -o %t && %run %t 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-SYS %s +// RUN: %clangxx_tsan -O1 -DTEST_ERROR=-1 %s -o %t && not %run %t 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-USER %s +// UNSUPPORTED: darwin + +#include +#include +#include +#include +#include + +char buffer[1000]; + +void *Thread(void *p) { + return strerror_r(TEST_ERROR, buffer, sizeof(buffer)); +} + +int main() { + pthread_t th[2]; + pthread_create(&th[0], 0, Thread, 0); + pthread_create(&th[1], 0, Thread, 0); + pthread_join(th[0], 0); + pthread_join(th[1], 0); + fprintf(stderr, "DONE\n"); +} + +// CHECK-USER: WARNING: ThreadSanitizer: data race +// CHECK-SYS-NOT: WARNING: ThreadSanitizer: data race + +// CHECK: DONE From f1d04915a666728c241bedb36bd99aafee3ea444 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 10 Jun 2017 13:44:58 +0000 Subject: [PATCH 14/22] Vendor import of lldb trunk r305145: https://llvm.org/svn/llvm-project/lldb/trunk@305145 --- include/lldb/Core/Address.h | 10 +- include/lldb/Core/Section.h | 3 +- include/lldb/Core/dwarf.h | 2 +- include/lldb/Target/SectionLoadList.h | 3 +- include/lldb/Utility/SafeMachO.h | 2 +- include/lldb/Utility/TaskPool.h | 3 +- include/lldb/Utility/VMRange.h | 5 - .../unwind/noreturn/TestNoreturnUnwind.py | 4 +- .../functionalities/unwind/noreturn/main.c | 2 - .../module-end/TestNoReturnModuleEnd.py | 53 ++++ .../unwind/noreturn/module-end/a.s | 35 +++ .../unwind/noreturn/module-end/test.core | Bin 0 -> 40960 bytes .../unwind/noreturn/module-end/test.out | Bin 0 -> 520 bytes source/Commands/CommandObjectRegister.cpp | 11 +- source/Core/Address.cpp | 12 +- source/Core/ArchSpec.cpp | 8 +- source/Core/CMakeLists.txt | 1 + source/Core/Section.cpp | 20 +- source/DataFormatters/TypeCategory.cpp | 21 +- source/Host/common/Host.cpp | 8 +- .../posix/ConnectionFileDescriptorPosix.cpp | 7 +- .../Host/posix/ProcessLauncherPosixFork.cpp | 5 +- source/Plugins/Language/ObjC/ObjCLanguage.cpp | 2 +- .../AppleObjCRuntime/AppleObjCRuntimeV1.cpp | 1 + source/Plugins/ObjectFile/ELF/CMakeLists.txt | 1 + source/Plugins/ObjectFile/ELF/ELFHeader.h | 2 +- .../Plugins/ObjectFile/PECOFF/CMakeLists.txt | 1 + .../ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 2 +- .../Process/Darwin/DarwinProcessLauncher.cpp | 38 ++- .../Process/FreeBSD/ProcessMonitor.cpp | 7 +- .../Process/Linux/NativeProcessLinux.cpp | 10 +- .../Process/Utility/RegisterContextLLDB.cpp | 12 +- .../Plugins/Process/elf-core/CMakeLists.txt | 1 + .../Process/elf-core/ProcessElfCore.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 4 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 5 +- source/Target/SectionLoadList.cpp | 15 +- source/Target/StackFrame.cpp | 3 +- source/Utility/CMakeLists.txt | 1 + source/Utility/Status.cpp | 18 +- source/Utility/TaskPool.cpp | 2 +- source/Utility/VMRange.cpp | 46 +-- tools/lldb-server/lldb-gdbserver.cpp | 11 +- unittests/CMakeLists.txt | 3 +- unittests/Core/ArchSpecTest.cpp | 2 +- unittests/Core/StructuredDataTest.cpp | 2 +- .../GDBRemoteCommunicationClientTest.cpp | 21 +- unittests/tools/CMakeLists.txt | 3 + unittests/tools/lldb-server/CMakeLists.txt | 13 + .../lldb-server/inferior/thread_inferior.cpp | 41 +++ .../tools/lldb-server/tests/CMakeLists.txt | 15 + .../lldb-server/tests/MessageObjects.cpp | 207 +++++++++++++ .../tools/lldb-server/tests/MessageObjects.h | 102 +++++++ .../tools/lldb-server/tests/TestClient.cpp | 287 ++++++++++++++++++ .../tools/lldb-server/tests/TestClient.h | 61 ++++ .../tests/ThreadIdsInJstopinfoTest.cpp | 58 ++++ 56 files changed, 1021 insertions(+), 193 deletions(-) create mode 100644 packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py create mode 100644 packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s create mode 100644 packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.core create mode 100755 packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out create mode 100644 unittests/tools/CMakeLists.txt create mode 100644 unittests/tools/lldb-server/CMakeLists.txt create mode 100644 unittests/tools/lldb-server/inferior/thread_inferior.cpp create mode 100644 unittests/tools/lldb-server/tests/CMakeLists.txt create mode 100644 unittests/tools/lldb-server/tests/MessageObjects.cpp create mode 100644 unittests/tools/lldb-server/tests/MessageObjects.h create mode 100644 unittests/tools/lldb-server/tests/TestClient.cpp create mode 100644 unittests/tools/lldb-server/tests/TestClient.h create mode 100644 unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h index a800570ec8b1..4c77458061d0 100644 --- a/include/lldb/Core/Address.h +++ b/include/lldb/Core/Address.h @@ -422,6 +422,10 @@ class Address { /// a section + offset. The Target's SectionLoadList object /// is used to resolve the address. /// + /// @param[in] allow_section_end + /// If true, treat an address pointing to the end of the module as + /// belonging to that module. + /// /// @return /// Returns \b true if the load address was resolved to be /// section/offset, \b false otherwise. It is often ok for an @@ -429,11 +433,13 @@ class Address { /// happens for JIT'ed code, or any load addresses on the stack /// or heap. //------------------------------------------------------------------ - bool SetLoadAddress(lldb::addr_t load_addr, Target *target); + bool SetLoadAddress(lldb::addr_t load_addr, Target *target, + bool allow_section_end = false); bool SetOpcodeLoadAddress( lldb::addr_t load_addr, Target *target, - lldb::AddressClass addr_class = lldb::eAddressClassInvalid); + lldb::AddressClass addr_class = lldb::eAddressClassInvalid, + bool allow_section_end = false); bool SetCallableLoadAddress(lldb::addr_t load_addr, Target *target); diff --git a/include/lldb/Core/Section.h b/include/lldb/Core/Section.h index a133298edaf3..0466693edbc4 100644 --- a/include/lldb/Core/Section.h +++ b/include/lldb/Core/Section.h @@ -143,7 +143,8 @@ class Section : public std::enable_shared_from_this

    , lldb::addr_t GetLoadBaseAddress(Target *target) const; - bool ResolveContainedAddress(lldb::addr_t offset, Address &so_addr) const; + bool ResolveContainedAddress(lldb::addr_t offset, Address &so_addr, + bool allow_section_end = false) const; lldb::offset_t GetFileOffset() const { return m_file_offset; } diff --git a/include/lldb/Core/dwarf.h b/include/lldb/Core/dwarf.h index 4a935d5151e9..651a2bc29475 100644 --- a/include/lldb/Core/dwarf.h +++ b/include/lldb/Core/dwarf.h @@ -13,7 +13,7 @@ #include // Get the DWARF constant definitions from llvm -#include "llvm/Support/Dwarf.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "lldb/Core/RangeMap.h" diff --git a/include/lldb/Target/SectionLoadList.h b/include/lldb/Target/SectionLoadList.h index c232dd91a8b3..beb345b71290 100644 --- a/include/lldb/Target/SectionLoadList.h +++ b/include/lldb/Target/SectionLoadList.h @@ -47,7 +47,8 @@ class SectionLoadList { lldb::addr_t GetSectionLoadAddress(const lldb::SectionSP §ion_sp) const; - bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr) const; + bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, + bool allow_section_end = false) const; bool SetSectionLoadAddress(const lldb::SectionSP §ion_sp, lldb::addr_t load_addr, diff --git a/include/lldb/Utility/SafeMachO.h b/include/lldb/Utility/SafeMachO.h index 5da03c15da94..791410a38b34 100644 --- a/include/lldb/Utility/SafeMachO.h +++ b/include/lldb/Utility/SafeMachO.h @@ -114,6 +114,6 @@ #undef CPU_SUBTYPE_MC980000_ALL #undef CPU_SUBTYPE_MC98601 -#include "llvm/Support/MachO.h" +#include "llvm/BinaryFormat/MachO.h" #endif // liblldb_SafeMachO_h_ diff --git a/include/lldb/Utility/TaskPool.h b/include/lldb/Utility/TaskPool.h index 87b8824f9226..f2deaee506b8 100644 --- a/include/lldb/Utility/TaskPool.h +++ b/include/lldb/Utility/TaskPool.h @@ -10,6 +10,7 @@ #ifndef utility_TaskPool_h_ #define utility_TaskPool_h_ +#include "llvm/ADT/STLExtras.h" #include // for bind, function #include #include @@ -86,6 +87,6 @@ template <> struct TaskPool::RunTaskImpl<> { // 'batch_size' numbers at a time to work on, so for very fast functions, batch // should be large enough to avoid too much cache line contention. void TaskMapOverInt(size_t begin, size_t end, - std::function const &func); + const llvm::function_ref &func); #endif // #ifndef utility_TaskPool_h_ diff --git a/include/lldb/Utility/VMRange.h b/include/lldb/Utility/VMRange.h index 98362f4d7608..f03a1b0c1f97 100644 --- a/include/lldb/Utility/VMRange.h +++ b/include/lldb/Utility/VMRange.h @@ -111,11 +111,6 @@ class VMRange { static bool ContainsRange(const VMRange::collection &coll, const VMRange &range); - // Returns a valid index into coll when a match is found, else UINT32_MAX - // is returned - static size_t FindRangeIndexThatContainsValue(const VMRange::collection &coll, - lldb::addr_t value); - protected: lldb::addr_t m_base_addr; lldb::addr_t m_byte_size; diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py index eafe62a0e08f..d54e62887ce1 100644 --- a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py +++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py @@ -17,8 +17,8 @@ class NoreturnUnwind(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfWindows # clang-cl does not support gcc style attributes. - @expectedFailureAndroid(bugnumber="llvm.org/pr31192") - @expectedFailureAll(bugnumber="llvm.org/pr31192", oslist=['linux'], compiler="gcc", archs=['arm']) + # clang does not preserve LR in noreturn functions, making unwinding impossible + @skipIf(compiler="clang", archs=['arm'], oslist=['linux']) def test(self): """Test that we can backtrace correctly with 'noreturn' functions on the stack""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c index 7190e38f5d8c..4f6525fbf52f 100644 --- a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c +++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c @@ -29,8 +29,6 @@ func_a (void) int main (int argc, char *argv[]) { - sleep (2); - func_a (); return 0; diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py new file mode 100644 index 000000000000..3aa6a230e8b6 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py @@ -0,0 +1,53 @@ +""" +Test that we properly display the backtrace when a noreturn function happens to +be at the end of the stack. +""" + +from __future__ import print_function + +import shutil +import struct + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestNoreturnModuleEnd(TestBase): + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + super(TestNoreturnModuleEnd, self).setUp() + self._initial_platform = lldb.DBG.GetSelectedPlatform() + + def tearDown(self): + lldb.DBG.SetSelectedPlatform(self._initial_platform) + super(TestNoreturnModuleEnd, self).tearDown() + + def test(self): + target = self.dbg.CreateTarget("test.out") + process = target.LoadCore("test.core") + self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + self.assertEqual(process.GetNumThreads(), 1) + + thread = process.GetSelectedThread() + self.assertTrue(thread.IsValid()) + + backtrace = [ + ["func2", 3], + ["func1", 8], + ["_start", 8], + ] + self.assertEqual(thread.GetNumFrames(), len(backtrace)) + for i in range(len(backtrace)): + frame = thread.GetFrameAtIndex(i) + self.assertTrue(frame.IsValid()) + symbol = frame.GetSymbol() + self.assertTrue(symbol.IsValid()) + self.assertEqual(symbol.GetName(), backtrace[i][0]) + function_start = symbol.GetStartAddress().GetLoadAddress(target) + self.assertEquals(function_start + backtrace[i][1], frame.GetPC()) + + self.dbg.DeleteTarget(target) diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s new file mode 100644 index 000000000000..119465c132a9 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s @@ -0,0 +1,35 @@ +# compile this with: +# as a.s -o a.o --32 && ld a.o -m elf_i386 +# generate core file with: +# ulimit -s 12 && ./a.out + +.text + +.globl func2 +.type func2, @function +func2: + pushl %ebp + movl %esp, %ebp + movl 0, %eax + popl %ebp + ret +.size func2, .-func2 + +.globl _start +.type _start, @function +_start: + pushl %ebp + movl %esp, %ebp + call func1 + popl %ebp + ret +.size _start, .-_start + +.globl func1 +.type func1, @function +func1: + pushl %ebp + movl %esp, %ebp + call func2 +.size func1, .-func1 + diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.core b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.core new file mode 100644 index 0000000000000000000000000000000000000000..6717d4ff6471103427e6d0902060cbdc56873f00 GIT binary patch literal 40960 zcmeHQ3y>SdnI5fn&2lW(f(@~OGfTz1VoS5yl^?88&hoByS6C}8df01hBaft6t+1q# zXGZ(*88CQlP?Sv!Ar&qmIqsFDt`b5H?!qNh#l{>M3hoTJu6!wy^Hn+A8bg)C1#^%C z-S_v*Nb<&k<8oC;QQh#V|L*>~=kKro>FIXO^xo+Y_SjOrVhwQf)nptg_!&U!!1;QbLyw0Lt}ptqBKCf zdcZyTR0lw9Q9qcEAT}IR5Xg0Jg&y_wvc-0x&5SQZeD4B5m~Y0PK}=yWuzlCQ>XnG! z{L_6^2jV|Q8W9V0of*I%4D?$zGycd>Tu0b%+!JC+Q^lN;l5%23Q8GDM98>bLn3Ix{ zJ|^aJ_&=Q#i&AR4l#w-YcuF5r3M^AAWp$a2zBpPcr1Y#(kaAf)3$0RNB3np{1x1zh zl3Eb+O1hMjoig$)Zy_Ve#vITDST^2iuc8m+u@nme`7DKH$TOt>yI(d|xcHsRUh5AA zLh%taeJ2grIl}HM$*OY{@T^Z21LPBH;R8+Z3+@x2s-dlQ#+rL;8C>8Da0WO7oB_@N zXW;*Zfjj5y|C_LLqWuc(iD>`-fN2%&|82r`*gG__a+Xc|8K8&+f%X-&2aA_~`DY|< zJp^f%b{U3rg7y|JZ7Q!zNyNHp#ABAE%agVJE!F?1a5)snR$4p8U`Gt`6@V3}i~{Wm z8@Cr^>s3@>21}1(vepV)kg*#H+Cx%4#poW}Gd8yOD)g2k-wIZHR=P1JJ1I>plinE8 zlyNaqv_2x<|G-Ss-m_@#7u!*O8PZhWD({$6e(jvJK>I_tkkE8V)rCYNscEK61zkcy zPD{FksE|fY9ykM>0nPwtfHS}u;0$mEI0Kvk&H!hCGr$?(3~&ZG1DpZQ0B3+Rz!~5S za0WO7oB_@NXMi)n8Q=_X1~>zp0nPwtfHS}u;0$mEI0Kvk&H!iNlgz-}_y6tY`~OGq zAvC@Jf0{moMxgiqoALhtMR)^#?)&XmLWf|z|4;AAKZzd;_aaT8_vbB)K-t1Jl4*lxJHd*w(gQvD?z4 zx{ptfe@A%!@<(5LVfXzPerd_w_kQk~YhM5IR zJzj4_)f4sHT((e}bY>)7c4>;sZG5bo=yI*BNh`=iJ4V3({n9rh#((#n{zu0`l+$+_ zJ4g|M`bZjQN{`sBGOM3dM&C-jZI+R~#Tk7cL2b}C85GDL9tYn3psKuqn8yA98lbW6 zL`>gJd=;Q?{i)7>RjbMvoZ)@MNWR>@ zrUNmx{|*{jjrcsw6Mu<#5#nZ4vhEAp&PY_S?P|5*gQ+np2Y!S)?AR8EUGJFJE;Q+# z?Y1U;d3#fneqFo0NnhID(xhL}KCek%)P7!*zOcQuNxyL&w69>=%Srn>(q2m19i+X8 zv=@?gJ87@(!*!;C&A1lLXM&?yf6|8PcKrogyUng2wzW6e^`~v^cDsJS*4|>*pRl#h zv+IxB+RwA=kJ{Q>?fNkrB>nZ8Zi5S{%hriQx?-Gm9i@yM*hU8xNIyjrb1)`#C4UQ*|c zx0X+rpWl4z)hlHI9205F-Q475@p_ zugZ?S2ON7p_yApa_lfhV;AfSst+Ur){K~I@6oZm_AJeQy==ByRoT&A>;&0u1p!8$2 zt4AGsA4FqTSC3Wv$IY&unA6o4%KpQS>5~{~*44#isMS@GHBsy8(Rx=8FNnWz&aO_J zZ+3HhvHQ6eVWs@^o|mh84%)!N#A(+5iIc4F$IQM@H{&D8lkdM@t$w(^#ntptaCP!U z=+9n-pGqYNB9`qTPrm#s+X`t_{BK*z2Lej324o-b%Nhf41U(!E}kEmA1<&o<)^ii<-&%OUKH$zv`I& zHm=58;s}JAOT36grF0y3bEWh~<@OV6Zd_7&&~kmWeGc!R=rdhnVofDJOT%712p8D< zvSa#QwD#jyhLY{?yngWAD-XUm@A~I)XIK1fbW?nRUDvt?ey4Yw`s>+6zoE&j?g*6% zIe_U7&lnzX)l1|9ufYYp7$$4{P91*MKa1-Kr+)fG2vKFIt^Bj{Z)U0U&6Y0AJW+D zeYx`YV^r_7-c;_QnXb~d^ibuBrHA&P6;54vR&wNt2{icPZp(k3_`Z>}(lZjYe-r_*44Dep!Eg? zdY}?$Ese2NNRQUsgg#)d9v!Vlx}-;Ial(Gc)CNQrwTfa;PSt=$QyvChNLXpU?%oZ|c!npAbVHU6*tzrr-nS0hHIcZ?(!PrZvn>0NFr#efS|P zqzjpW^aym68azz!~5Sa0WO7oB_@NXMi)n8Q=_X1~>zp0nPwt zfHS}u;0$mEI0Kvk&H!hCGr$?(3~&ZG1DpZQ0B3+Rz!~5Sa0WO7oB__jCxn4%{5|9% z{+`hn5sxA!v*`WLiT%dk)4dz<4Dc}UH^2$tZQz3Y_Ej$fZU(jhd0-lN0Qdng3%m!c zy?NeoZzy*J@uljl5Zs1|yN5KBC@2mbfa0poS4YUKq zfbGC8paL8OegT{YmOQkt+6mkQM1T@74Lkrm4!i{{`R2ZA97qFq0AB!}0WSI0zUsBW z05Ai54fr1LB5(|N3uwXL8Fm4~z^%Xz;C|p);5b0MbpW5_zl#j>u6b#Yf~SI0 zv4`$D@^n*nzp0nPwtfHS}u;0$mEI0Kvk&H!hCGr$@6lri8E zby?G0N=X++`UVmkVxfq4l@N^%CVT__P%JSV=<}{zal;L)H0qB=1L05tdHAdKq(2bx z`(yq{qR$ueCHevpuQ)ELVlJBmGGlr=@1z4X#GI6r^f4jo4+cWm z9;51kp~O(QFCO%JC$o8|vCDXk^F4%t;Q`Z_K&U_L71dHfENQYTc6D}lc6-F_@|2n_ zWSmm}XhBiLOfl2b+2a<_?vQsFH+ zWv37w^aq1pF_|rhNjfy7PD9Wa5A_cEBi>R`(>3cWSam=ayImtn_rP#`$F7A%9}Me^Vq78c6hpL$OF0efe;* zgn`(4lliDu!Eq=#Y09akR3(>7N@`E3kkzN08GXAmucS*kS%^nLfjOALzC0ZB$wCu(BsV=I!k4DQ3N% z&NbcLJ(|MuSM;PUA(=Lc)^xgiQVp`AvV1q?Yb9^@sx=-68E<#z8c%mmN@9Y$N1tFq zSC0b0v&Pfaqv=f9(<4u^YjyQ}&V|urvYX`0&YCQ#x7B1_s^{l+!fbSe^m9A&QZ1q9 z>Pq@#UEY~3)^zH*x76~|^~{FLH#FAJR&r-otzNQTPd{6(>*#fzw4AI}Rg3wWd|N~R zCmLkALDm{%wL!+AHnnzkD#ox8FR5a-o>*14L9L6o6*H{r3aH;!llZ5)>PBeeXUT@y)M~y#shBdnh~+Ee zHLLRtUCTFiE#K9kw7o7*$PKnC4SmZOJ@r;S^$N(ZC&m?HV9AUfdQHDjs;f-o>$0TP zyR6n}RP*EYW=3*gtdvSMaTMn+)e`wEY%p~oqbpWoJKV;Si`@-!y|R*l zN0>TlU424=J!ZBvSVqaFn z$x%~7QbEe#c^5UN{Z6x{4^L;Bct5(Dq<0$6vUqGT5e@gQ_lkPHC~Df6bF|ncrG`d( z<2OXzBCb-t9g#adfV_s*^agQsf6y`qSde*WwU4dS|6VHuFapkJ6 zuH{TJ9vJ7Yb&g6xpTFN155}Tq_vo>rjY+C3X6Wf^J`7!Hc~mOpbUakCvY@pHo_YO& z0a}Gby`rqA#L0Aq;543|#`DQ&$b67eX^*8UMAs*xfq@V`K8J(xfj|h$f>JU$#aMw+ z(e<(LaQ!LG4j&VY5vV`;jAy<$hV_KG>M0RXwK?fpvR=TljAX6U7|q{lEA)h$ zV-2gaY_ghha*F=LI057D;0}4&aC9zp|22zH}-iO76IpK9!rBmi+;_#F{hJ_4eYNf0$v(>0LS}L$Z)TCTi&qAwIn8+5=VnHzuL>7(Jh*K`4g`2|b zylJv-1PjPOe*mjI@7iqM%Pc;7O~jV6o~{)_&=(r;%7sKc>Watuome~d4JGQC0(>6p z*|4>+VO=_h1Lmay7PpEzWw>B(cxX6qi{*t_8ukaUo;BC7Sm2uOIXvi#`n_&pIO_Ip z*}O&GjLE>0-?DYfScjE#Q*y#gLSEWI7S@)BhU1yZ*rs8>xqLNOg;>P~Hw1BoK`aPA zd^~CsiC2?pjvx-=xZMqMdf?nxOk%07#*&#Gk&bm<*B>Q(38~{|Z$kV0E|hzQ{1K>| zJ}PQzN*vARFk)k}lor!+QPD*iUR#t^xOPew^Rk+eiyoJr%9$(HIrkOqE%dRh=EVP~ zugWPLaGe&0H^m0Sp}99(vXsrG+3g~xN~(&*sgkBE`Rq>EpT>G=-m)aM52RUOo>9@x_H#O%@ZX1`uZZ+l6Yw{Ygm}m6iTk=l!tQmQm&p~X@an`-e=D5ab3b&l6;Vz`TQ4ofNhy5Y%t`62ZSr5XsVzwxE zT&)Rk-AFjlmk9N(PkgikSaVY$tt#2Hvyk5IRNdW4ArQirB-HEoViz?M>kAM0FdJs` zPGfh&dKrm_Vgc+p*rspJE<@-GL@`Zl^7a_ds@`}cLYql*ti5sCSFpWDedEV&*paSI z(`s|_V7o_k0$s&XjhIlaog~rF8w}%4Iu{E>L?pT?)LR?VVUKb9d0j=1*@=43SQqL; z#U@8t6h^Se8w^JRu}vR-7m2PBsf1}vrB1Oe58HYgdrI1WW(yL|efKtOwHrk1-xK~D D7`K=( literal 0 HcmV?d00001 diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out new file mode 100755 index 0000000000000000000000000000000000000000..141c61ecbea315995f30ffbb48d31ae80355f6b8 GIT binary patch literal 520 zcma)2u};EJ6um7Jg~1d?WhfI2ghbO{(8;lGYSRjY1w!Z}fr+ke4*r1O;%_i&;$M_= z+FsLi;wGo(o^$SdxqXNG#|O)@M9Y?jP`#$jOCS7M2EKUkN8*T`=edm;0oD+NL(>&` zdjI`m`|^$M&;IXzvMiHHvR|4g2AfU63+>EoXL#=1y1^iKZ2l~TeYCXe9A({YvGJa3mK=r;O=Em@}^gh*9=AP7iWzH?2Y4o5jzksjtB6 sk7C|Mehtm@ntQc;Skp4!uHJ4XOiZ*f5{7Y-ls$tx31`#DM4;7FPTGYzMgRZ+ literal 0 HcmV?d00001 diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp index 6de8c667e7a7..d535742016ac 100644 --- a/source/Commands/CommandObjectRegister.cpp +++ b/source/Commands/CommandObjectRegister.cpp @@ -7,12 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "llvm/ADT/STLExtras.h" - -// Project includes #include "CommandObjectRegister.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/RegisterValue.h" @@ -32,6 +26,7 @@ #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/DataExtractor.h" +#include "llvm/Support/Errno.h" using namespace lldb; using namespace lldb_private; @@ -178,8 +173,8 @@ class CommandObjectRegisterRead : public CommandObjectParsed { if (set_idx < reg_ctx->GetRegisterSetCount()) { if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) { if (errno) - result.AppendErrorWithFormat("register read failed: %s\n", - strerror(errno)); + result.AppendErrorWithFormatv("register read failed: {0}\n", + llvm::sys::StrError()); else result.AppendError("unknown error while reading registers.\n"); result.SetStatus(eReturnStatusFailed); diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp index 6328e433852a..0c929c22f75f 100644 --- a/source/Core/Address.cpp +++ b/source/Core/Address.cpp @@ -361,8 +361,9 @@ addr_t Address::GetOpcodeLoadAddress(Target *target, } bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target, - AddressClass addr_class) { - if (SetLoadAddress(load_addr, target)) { + AddressClass addr_class, + bool allow_section_end) { + if (SetLoadAddress(load_addr, target, allow_section_end)) { if (target) { if (addr_class == eAddressClassInvalid) addr_class = GetAddressClass(); @@ -1001,9 +1002,10 @@ AddressClass Address::GetAddressClass() const { return eAddressClassUnknown; } -bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target) { - if (target && - target->GetSectionLoadList().ResolveLoadAddress(load_addr, *this)) +bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target, + bool allow_section_end) { + if (target && target->GetSectionLoadList().ResolveLoadAddress( + load_addr, *this, allow_section_end)) return true; m_section_wp.reset(); m_offset = load_addr; diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp index 91b73847ac1f..bfe9750f70f0 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Core/ArchSpec.cpp @@ -24,11 +24,11 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" // for Twine -#include "llvm/Support/COFF.h" -#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH -#include "llvm/Support/ELF.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/BinaryFormat/MachO.h" // for CPUType::CPU_T... +#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH #include "llvm/Support/Host.h" -#include "llvm/Support/MachO.h" // for CPUType::CPU_T... #include // for shared_ptr #include diff --git a/source/Core/CMakeLists.txt b/source/Core/CMakeLists.txt index 7dcec050d866..806227793f24 100644 --- a/source/Core/CMakeLists.txt +++ b/source/Core/CMakeLists.txt @@ -67,6 +67,7 @@ add_lldb_library(lldbCore lldbPluginObjectFileJIT LINK_COMPONENTS + BinaryFormat Support Demangle ) diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp index f6428ced0164..3b76dd361ff3 100644 --- a/source/Core/Section.cpp +++ b/source/Core/Section.cpp @@ -220,18 +220,18 @@ addr_t Section::GetLoadBaseAddress(Target *target) const { return load_base_addr; } -bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr) const { +bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr, + bool allow_section_end) const { const size_t num_children = m_children.GetSize(); - if (num_children > 0) { - for (size_t i = 0; i < num_children; i++) { - Section *child_section = m_children.GetSectionAtIndex(i).get(); + for (size_t i = 0; i < num_children; i++) { + Section *child_section = m_children.GetSectionAtIndex(i).get(); - addr_t child_offset = child_section->GetOffset(); - if (child_offset <= offset && - offset - child_offset < child_section->GetByteSize()) - return child_section->ResolveContainedAddress(offset - child_offset, - so_addr); - } + addr_t child_offset = child_section->GetOffset(); + if (child_offset <= offset && + offset - child_offset < + child_section->GetByteSize() + (allow_section_end ? 1 : 0)) + return child_section->ResolveContainedAddress(offset - child_offset, + so_addr, allow_section_end); } so_addr.SetOffset(offset); so_addr.SetSection(const_cast
    (this)->shared_from_this()); diff --git a/source/DataFormatters/TypeCategory.cpp b/source/DataFormatters/TypeCategory.cpp index db3372c52925..184a8c98de62 100644 --- a/source/DataFormatters/TypeCategory.cpp +++ b/source/DataFormatters/TypeCategory.cpp @@ -36,23 +36,8 @@ TypeCategoryImpl::TypeCategoryImpl( static bool IsApplicable(lldb::LanguageType category_lang, lldb::LanguageType valobj_lang) { switch (category_lang) { - // these are not languages that LLDB would ordinarily deal with - // only allow an exact equality here, since we really don't know - // any better - case eLanguageTypeAda83: - case eLanguageTypeCobol74: - case eLanguageTypeCobol85: - case eLanguageTypeFortran77: - case eLanguageTypeFortran90: - case eLanguageTypePascal83: - case eLanguageTypeModula2: - case eLanguageTypeJava: - case eLanguageTypeAda95: - case eLanguageTypeFortran95: - case eLanguageTypePLI: - case eLanguageTypeUPC: - case eLanguageTypeD: - case eLanguageTypePython: + // Unless we know better, allow only exact equality. + default: return category_lang == valobj_lang; // the C family, we consider it as one @@ -80,7 +65,7 @@ static bool IsApplicable(lldb::LanguageType category_lang, valobj_lang == eLanguageTypeC_plus_plus || valobj_lang == eLanguageTypeObjC; - default: + // Categories with unspecified language match everything. case eLanguageTypeUnknown: return true; } diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index da35022c813c..d78961e5bffc 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -68,6 +68,7 @@ #include "lldb/Utility/Status.h" #include "lldb/lldb-private-forward.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #if defined(_WIN32) @@ -217,10 +218,9 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { if (errno == EINTR) continue; else { - if (log) - log->Printf( - "%s (arg = %p) thread exiting because waitpid failed (%s)...", - __FUNCTION__, arg, strerror(errno)); + LLDB_LOG(log, + "arg = {0}, thread exiting because waitpid failed ({1})...", + arg, llvm::sys::StrError()); break; } } else if (wait_pid > 0) { diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 7a0c92b44918..c3b237a87302 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -36,6 +36,7 @@ #include // Other libraries and framework includes +#include "llvm/Support/Errno.h" #include "llvm/Support/ErrorHandling.h" #if defined(__APPLE__) #include "llvm/ADT/SmallVector.h" @@ -461,10 +462,8 @@ size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, return 0; default: - if (log) - log->Printf( - "%p ConnectionFileDescriptor::Read (), unexpected error: %s", - static_cast(this), strerror(error_value)); + LLDB_LOG(log, "this = {0}, unexpected error: {1}", this, + llvm::sys::StrError(error_value)); status = eConnectionStatusError; break; // Break to close.... } diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp index 378670cd2a9a..1eace5cd24cd 100644 --- a/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -14,6 +14,7 @@ #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" +#include "llvm/Support/Errno.h" #include #include @@ -204,8 +205,8 @@ ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info, ::pid_t pid = ::fork(); if (pid == -1) { // Fork failed - error.SetErrorStringWithFormat("Fork failed with error message: %s", - strerror(errno)); + error.SetErrorStringWithFormatv("Fork failed with error message: {0}", + llvm::sys::StrError()); return HostProcess(LLDB_INVALID_PROCESS_ID); } if (pid == 0) { diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp index 193c5864d01f..4d9227598cef 100644 --- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -95,7 +95,7 @@ bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) { // or '-' can be omitted bool valid_prefix = false; - if (name[0] == '+' || name[0] == '-') { + if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) { valid_prefix = name[1] == '['; if (name[0] == '+') m_type = eTypeClassMethod; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index 566fefaf7984..9cac499c0ff0 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -171,6 +171,7 @@ UtilityFunction *AppleObjCRuntimeV1::CreateObjectChecker(const char *name) { " \n", name); assert(strformatsize < (int)sizeof(buf->contents)); + (void)strformatsize; Status error; return GetTargetRef().GetUtilityFunctionForLanguage( diff --git a/source/Plugins/ObjectFile/ELF/CMakeLists.txt b/source/Plugins/ObjectFile/ELF/CMakeLists.txt index a941b8d55848..e0680b07efc5 100644 --- a/source/Plugins/ObjectFile/ELF/CMakeLists.txt +++ b/source/Plugins/ObjectFile/ELF/CMakeLists.txt @@ -8,5 +8,6 @@ add_lldb_library(lldbPluginObjectFileELF PLUGIN lldbSymbol lldbTarget LINK_COMPONENTS + BinaryFormat Support ) diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.h b/source/Plugins/ObjectFile/ELF/ELFHeader.h index e6738a1ecb2b..4e2d3155ebb9 100644 --- a/source/Plugins/ObjectFile/ELF/ELFHeader.h +++ b/source/Plugins/ObjectFile/ELF/ELFHeader.h @@ -21,7 +21,7 @@ #ifndef liblldb_ELFHeader_h_ #define liblldb_ELFHeader_h_ -#include "llvm/Support/ELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-types.h" diff --git a/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt b/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt index 1e8fb85c72c9..04321f276551 100644 --- a/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt +++ b/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt @@ -8,5 +8,6 @@ add_lldb_library(lldbPluginObjectFilePECOFF PLUGIN lldbSymbol lldbTarget LINK_COMPONENTS + BinaryFormat Support ) diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index dcb9527f24c8..4739a4934aa6 100644 --- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -10,7 +10,7 @@ #include "ObjectFilePECOFF.h" #include "WindowsMiniDump.h" -#include "llvm/Support/COFF.h" +#include "llvm/BinaryFormat/COFF.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/FileSpecList.h" diff --git a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp index 6845a36730c9..c6daf6ccea6e 100644 --- a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp +++ b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp @@ -35,6 +35,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "llvm/Support/Errno.h" #include "CFBundle.h" #include "CFString.h" @@ -319,13 +320,12 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, ::posix_spawnattr_setsigdefault(&attr, &all_signals); if ((error_code = ::posix_spawnattr_setflags(&attr, flags)) != 0) { - if (log) - log->Printf("::posix_spawnattr_setflags(&attr, " - "POSIX_SPAWN_START_SUSPENDED%s) failed: %s", - flags & _POSIX_SPAWN_DISABLE_ASLR - ? " | _POSIX_SPAWN_DISABLE_ASLR" - : "", - strerror(error_code)); + LLDB_LOG(log, + "::posix_spawnattr_setflags(&attr, " + "POSIX_SPAWN_START_SUSPENDED{0}) failed: {1}", + flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR" + : "", + llvm::sys::StrError(error_code)); error.SetError(error_code, eErrorTypePOSIX); return error; } @@ -341,10 +341,10 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, error_code = ::posix_spawnattr_setbinpref_np(&attr, 1, &desired_cpu_type, &ocount); if (error_code != 0) { - if (log) - log->Printf("::posix_spawnattr_setbinpref_np(&attr, 1, " - "cpu_type = 0x%8.8x, count => %llu): %s", - desired_cpu_type, (uint64_t)ocount, strerror(error_code)); + LLDB_LOG(log, + "::posix_spawnattr_setbinpref_np(&attr, 1, " + "cpu_type = {0:x8}, count => {1}): {2}", + desired_cpu_type, ocount, llvm::sys::StrError(error_code)); error.SetError(error_code, eErrorTypePOSIX); return error; } @@ -361,10 +361,8 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, posix_spawn_file_actions_t file_actions; if ((error_code = ::posix_spawn_file_actions_init(&file_actions)) != 0) { - if (log) - log->Printf("::posix_spawn_file_actions_init(&file_actions) " - "failed: %s", - strerror(error_code)); + LLDB_LOG(log, "::posix_spawn_file_actions_init(&file_actions) failed: {0}", + llvm::sys::StrError(error_code)); error.SetError(error_code, eErrorTypePOSIX); return error; } @@ -409,11 +407,11 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, error_code = ::posix_spawnp(pid, path, &file_actions, &attr, (char *const *)argv, (char *const *)envp); if (error_code != 0) { - if (log) - log->Printf("::posix_spawnp(pid => %p, path = '%s', file_actions " - "= %p, attr = %p, argv = %p, envp = %p) failed: %s", - pid, path, &file_actions, &attr, argv, envp, - strerror(error_code)); + LLDB_LOG(log, + "::posix_spawnp(pid => {0}, path = '{1}', file_actions " + "= {2}, attr = {3}, argv = {4}, envp = {5}) failed: {6}", + pid, path, &file_actions, &attr, argv, envp, + llvm::sys::StrError(error_code)); error.SetError(error_code, eErrorTypePOSIX); return error; } diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 34d99cd39de2..10dd14753914 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -30,6 +30,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/Status.h" +#include "llvm/Support/Errno.h" #include "FreeBSDThread.h" #include "Plugins/Process/POSIX/CrashReason.h" @@ -529,10 +530,8 @@ void ResumeOperation::Execute(ProcessMonitor *monitor) { if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data)) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - if (log) - log->Printf("ResumeOperation (%" PRIu64 ") failed: %s", pid, - strerror(errno)); + LLDB_LOG(log, "ResumeOperation ({0}) failed: {1}", pid, + llvm::sys::StrError(errno)); m_result = false; } else m_result = true; diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 15e7c9b5f698..a130472c72d0 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -43,14 +43,14 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StringExtractor.h" +#include "llvm/Support/Errno.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Threading.h" #include "NativeThreadLinux.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "Procfs.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Threading.h" - #include #include #include @@ -97,7 +97,7 @@ static bool ProcessVmReadvSupported() { LLDB_LOG(log, "syscall process_vm_readv failed (error: {0}). Fast memory " "reads disabled.", - strerror(errno)); + llvm::sys::StrError()); }); return is_supported; @@ -1988,7 +1988,7 @@ Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size, LLDB_LOG(log, "using process_vm_readv to read {0} bytes from inferior " "address {1:x}: {2}", - size, addr, success ? "Success" : strerror(errno)); + size, addr, success ? "Success" : llvm::sys::StrError(errno)); if (success) return Status(); diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 312c1887b581..bce77d7e0a32 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -329,7 +329,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { if (abi) pc = abi->FixCodeAddress(pc); - m_current_pc.SetLoadAddress(pc, &process->GetTarget()); + const bool allow_section_end = true; + m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end); // If we don't have a Module for some reason, we're not going to find // symbol/function information - just @@ -477,11 +478,12 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { // Or if we're in the middle of the stack (and not "above" an asynchronous // event like sigtramp), // and our "current" pc is the start of a function... - if (m_sym_ctx_valid && GetNextFrame()->m_frame_type != eTrapHandlerFrame && + if (GetNextFrame()->m_frame_type != eTrapHandlerFrame && GetNextFrame()->m_frame_type != eDebuggerFrame && - addr_range.GetBaseAddress().IsValid() && - addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() && - addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()) { + (!m_sym_ctx_valid || + (addr_range.GetBaseAddress().IsValid() && + addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() && + addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()))) { decr_pc_and_recompute_addr_range = true; } diff --git a/source/Plugins/Process/elf-core/CMakeLists.txt b/source/Plugins/Process/elf-core/CMakeLists.txt index b358697d25af..c7ffae695320 100644 --- a/source/Plugins/Process/elf-core/CMakeLists.txt +++ b/source/Plugins/Process/elf-core/CMakeLists.txt @@ -17,5 +17,6 @@ add_lldb_library(lldbPluginProcessElfCore PLUGIN lldbPluginObjectFileELF lldbPluginProcessUtility LINK_COMPONENTS + BinaryFormat Support ) diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 5a459e80348b..71eb6437ceed 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -27,7 +27,7 @@ #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/Log.h" -#include "llvm/Support/ELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Threading.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index cb00e840673f..f5418763d67b 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -3732,8 +3732,8 @@ static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) { } } } - assert(!"Shouldn't call GetContainingFunctionWithAbstractOrigin on something " - "not in a function"); + assert(0 && "Shouldn't call GetContainingFunctionWithAbstractOrigin on " + "something not in a function"); return DWARFDIE(); } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 279efe320a46..252a9807a3b5 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1958,7 +1958,7 @@ void SymbolFileDWARF::Index() { &function_fullname_index, &function_method_index, &function_selector_index, &objc_class_selectors_index, &global_index, &type_index, - &namespace_index](uint32_t cu_idx) { + &namespace_index](size_t cu_idx) { DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); if (dwarf_cu) { dwarf_cu->Index( @@ -1967,10 +1967,9 @@ void SymbolFileDWARF::Index() { objc_class_selectors_index[cu_idx], global_index[cu_idx], type_index[cu_idx], namespace_index[cu_idx]); } - return cu_idx; }; - auto extract_fn = [debug_info, &clear_cu_dies](uint32_t cu_idx) { + auto extract_fn = [debug_info, &clear_cu_dies](size_t cu_idx) { DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); if (dwarf_cu) { // dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the diff --git a/source/Target/SectionLoadList.cpp b/source/Target/SectionLoadList.cpp index 7f12c262f47e..31ccf17369db 100644 --- a/source/Target/SectionLoadList.cpp +++ b/source/Target/SectionLoadList.cpp @@ -207,8 +207,8 @@ bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp, return erased; } -bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, - Address &so_addr) const { +bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr, + bool allow_section_end) const { // First find the top level section that this load address exists in std::lock_guard guard(m_mutex); if (!m_addr_to_sect.empty()) { @@ -220,10 +220,11 @@ bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, const addr_t pos_load_addr = pos->first; if (load_addr >= pos_load_addr) { addr_t offset = load_addr - pos_load_addr; - if (offset < pos->second->GetByteSize()) { + if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) { // We have found the top level section, now we need to find the // deepest child section. - return pos->second->ResolveContainedAddress(offset, so_addr); + return pos->second->ResolveContainedAddress(offset, so_addr, + allow_section_end); } } } else { @@ -233,10 +234,12 @@ bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, m_addr_to_sect.rbegin(); if (load_addr >= rpos->first) { addr_t offset = load_addr - rpos->first; - if (offset < rpos->second->GetByteSize()) { + if (offset < + rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) { // We have found the top level section, now we need to find the // deepest child section. - return rpos->second->ResolveContainedAddress(offset, so_addr); + return rpos->second->ResolveContainedAddress(offset, so_addr, + allow_section_end); } } } diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp index 9deebcaf9250..4ef4a399290a 100644 --- a/source/Target/StackFrame.cpp +++ b/source/Target/StackFrame.cpp @@ -191,9 +191,10 @@ const Address &StackFrame::GetFrameCodeAddress() { if (thread_sp) { TargetSP target_sp(thread_sp->CalculateTarget()); if (target_sp) { + const bool allow_section_end = true; if (m_frame_code_addr.SetOpcodeLoadAddress( m_frame_code_addr.GetOffset(), target_sp.get(), - eAddressClassCode)) { + eAddressClassCode, allow_section_end)) { ModuleSP module_sp(m_frame_code_addr.GetModule()); if (module_sp) { m_sc.module_sp = module_sp; diff --git a/source/Utility/CMakeLists.txt b/source/Utility/CMakeLists.txt index a1675670f0b4..31b14acda962 100644 --- a/source/Utility/CMakeLists.txt +++ b/source/Utility/CMakeLists.txt @@ -38,5 +38,6 @@ add_lldb_library(lldbUtility # lldbUtility cannot have any dependencies LINK_COMPONENTS + BinaryFormat Support ) diff --git a/source/Utility/Status.cpp b/source/Utility/Status.cpp index ba87d3e5144f..6ecc7717620b 100644 --- a/source/Utility/Status.cpp +++ b/source/Utility/Status.cpp @@ -11,10 +11,11 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/VASPrintf.h" -#include "lldb/lldb-defines.h" // for LLDB_GENERIC_ERROR -#include "lldb/lldb-enumerations.h" // for ErrorType, ErrorType::eErr... -#include "llvm/ADT/SmallString.h" // for SmallString -#include "llvm/ADT/StringRef.h" // for StringRef +#include "lldb/lldb-defines.h" // for LLDB_GENERIC_ERROR +#include "lldb/lldb-enumerations.h" // for ErrorType, ErrorType::eErr... +#include "llvm/ADT/SmallString.h" // for SmallString +#include "llvm/ADT/StringRef.h" // for StringRef +#include "llvm/Support/Errno.h" #include "llvm/Support/FormatProviders.h" // for format_provider #include @@ -27,7 +28,6 @@ #endif #include // for uint32_t -#include // for strerror namespace llvm { class raw_ostream; @@ -121,23 +121,21 @@ const char *Status::AsCString(const char *default_error_str) const { return nullptr; if (m_string.empty()) { - const char *s = nullptr; switch (m_type) { case eErrorTypeMachKernel: #if defined(__APPLE__) - s = ::mach_error_string(m_code); + if (const char *s = ::mach_error_string(m_code)) + m_string.assign(s); #endif break; case eErrorTypePOSIX: - s = ::strerror(m_code); + m_string = llvm::sys::StrError(m_code); break; default: break; } - if (s != nullptr) - m_string.assign(s); } if (m_string.empty()) { if (default_error_str) diff --git a/source/Utility/TaskPool.cpp b/source/Utility/TaskPool.cpp index d8306dc7dc8f..d33f23cd861c 100644 --- a/source/Utility/TaskPool.cpp +++ b/source/Utility/TaskPool.cpp @@ -75,7 +75,7 @@ void TaskPoolImpl::Worker(TaskPoolImpl *pool) { } void TaskMapOverInt(size_t begin, size_t end, - std::function const &func) { + const llvm::function_ref &func) { std::atomic idx{begin}; size_t num_workers = std::min(end, std::thread::hardware_concurrency()); diff --git a/source/Utility/VMRange.cpp b/source/Utility/VMRange.cpp index 5eccd292a851..105b1a58c48c 100644 --- a/source/Utility/VMRange.cpp +++ b/source/Utility/VMRange.cpp @@ -25,34 +25,13 @@ using namespace lldb_private; bool VMRange::ContainsValue(const VMRange::collection &coll, lldb::addr_t value) { ValueInRangeUnaryPredicate in_range_predicate(value); - VMRange::const_iterator pos; - VMRange::const_iterator end = coll.end(); - pos = std::find_if(coll.begin(), end, in_range_predicate); - if (pos != end) - return true; - return false; + return llvm::find_if(coll, in_range_predicate) != coll.end(); } bool VMRange::ContainsRange(const VMRange::collection &coll, const VMRange &range) { RangeInRangeUnaryPredicate in_range_predicate(range); - VMRange::const_iterator pos; - VMRange::const_iterator end = coll.end(); - pos = std::find_if(coll.begin(), end, in_range_predicate); - if (pos != end) - return true; - return false; -} - -size_t VMRange::FindRangeIndexThatContainsValue(const VMRange::collection &coll, - lldb::addr_t value) { - ValueInRangeUnaryPredicate in_range_predicate(value); - VMRange::const_iterator begin = coll.begin(); - VMRange::const_iterator end = coll.end(); - VMRange::const_iterator pos = std::find_if(begin, end, in_range_predicate); - if (pos != end) - return std::distance(begin, pos); - return UINT32_MAX; + return llvm::find_if(coll, in_range_predicate) != coll.end(); } void VMRange::Dump(Stream *s, lldb::addr_t offset, uint32_t addr_width) const { @@ -66,8 +45,7 @@ bool lldb_private::operator==(const VMRange &lhs, const VMRange &rhs) { } bool lldb_private::operator!=(const VMRange &lhs, const VMRange &rhs) { - return lhs.GetBaseAddress() != rhs.GetBaseAddress() || - lhs.GetEndAddress() != rhs.GetEndAddress(); + return !(lhs == rhs); } bool lldb_private::operator<(const VMRange &lhs, const VMRange &rhs) { @@ -79,25 +57,13 @@ bool lldb_private::operator<(const VMRange &lhs, const VMRange &rhs) { } bool lldb_private::operator<=(const VMRange &lhs, const VMRange &rhs) { - if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) - return true; - else if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) - return false; - return lhs.GetEndAddress() <= rhs.GetEndAddress(); + return !(lhs > rhs); } bool lldb_private::operator>(const VMRange &lhs, const VMRange &rhs) { - if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) - return true; - else if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) - return false; - return lhs.GetEndAddress() > rhs.GetEndAddress(); + return rhs < lhs; } bool lldb_private::operator>=(const VMRange &lhs, const VMRange &rhs) { - if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) - return true; - else if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) - return false; - return lhs.GetEndAddress() >= rhs.GetEndAddress(); + return !(lhs < rhs); } diff --git a/tools/lldb-server/lldb-gdbserver.cpp b/tools/lldb-server/lldb-gdbserver.cpp index 6139bfabee3d..412d775e8394 100644 --- a/tools/lldb-server/lldb-gdbserver.cpp +++ b/tools/lldb-server/lldb-gdbserver.cpp @@ -21,8 +21,6 @@ // C++ Includes -// Other libraries and framework includes -#include "llvm/ADT/StringRef.h" #include "Acceptor.h" #include "LLDBServerUtilities.h" @@ -36,6 +34,8 @@ #include "lldb/Host/Socket.h" #include "lldb/Host/StringConvert.h" #include "lldb/Utility/Status.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Errno.h" #ifndef LLGS_PROGRAM_NAME #define LLGS_PROGRAM_NAME "lldb-server" @@ -398,10 +398,9 @@ int main_gdbserver(int argc, char *argv[]) { { const ::pid_t new_sid = setsid(); if (new_sid == -1) { - const char *errno_str = strerror(errno); - fprintf(stderr, "failed to set new session id for %s (%s)\n", - LLGS_PROGRAM_NAME, - errno_str ? errno_str : ""); + llvm::errs() << llvm::formatv( + "failed to set new session id for {0} ({1})\n", LLGS_PROGRAM_NAME, + llvm::sys::StrError()); } } break; diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index f78879db09b4..c7c3140b121a 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -68,9 +68,10 @@ add_subdirectory(Signals) add_subdirectory(Symbol) add_subdirectory(SymbolFile) add_subdirectory(Target) +add_subdirectory(tools) add_subdirectory(UnwindAssembly) add_subdirectory(Utility) if(LLDB_CAN_USE_DEBUGSERVER) add_subdirectory(debugserver) -endif() \ No newline at end of file +endif() diff --git a/unittests/Core/ArchSpecTest.cpp b/unittests/Core/ArchSpecTest.cpp index 8fed7adba07c..98b77e1826b1 100644 --- a/unittests/Core/ArchSpecTest.cpp +++ b/unittests/Core/ArchSpecTest.cpp @@ -11,7 +11,7 @@ #include "lldb/Core/ArchSpec.h" -#include "llvm/Support/MachO.h" +#include "llvm/BinaryFormat/MachO.h" using namespace lldb; using namespace lldb_private; diff --git a/unittests/Core/StructuredDataTest.cpp b/unittests/Core/StructuredDataTest.cpp index cac330304179..cdcf3236cd77 100644 --- a/unittests/Core/StructuredDataTest.cpp +++ b/unittests/Core/StructuredDataTest.cpp @@ -12,7 +12,7 @@ #include "lldb/Core/StructuredData.h" #include "lldb/Utility/StreamString.h" -#include "llvm/Support/MachO.h" +#include "llvm/BinaryFormat/MachO.h" using namespace lldb; using namespace lldb_private; diff --git a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp index c9ab0b6050a0..8f6f9f0684a3 100644 --- a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -318,8 +318,6 @@ TEST_F(GDBRemoteCommunicationClientTest, SendSignalsToIgnore) { if (HasFailure()) return; - const lldb::tid_t tid = 0x47; - const uint32_t reg_num = 4; std::future result = std::async(std::launch::async, [&] { return client.SendSignalsToIgnore({2, 3, 5, 7, 0xB, 0xD, 0x11}); }); @@ -406,7 +404,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) { R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})"; HandlePacket(server, (expected_packet1 + expected_packet2), "1"); ASSERT_TRUE(error.Success()); - ASSERT_EQ(result.get(), 1); + ASSERT_EQ(result.get(), 1u); error.Clear(); result = std::async(std::launch::async, [&] { @@ -468,7 +466,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) { std::string expected_packet2 = R"("traceid" : 3})"; HandlePacket(server, expected_packet1+expected_packet2, "123456"); ASSERT_TRUE(result.get().Success()); - ASSERT_EQ(buffer.size(), 3); + ASSERT_EQ(buffer.size(), 3u); ASSERT_EQ(buf[0], 0x12); ASSERT_EQ(buf[1], 0x34); ASSERT_EQ(buf[2], 0x56); @@ -480,7 +478,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) { HandlePacket(server, expected_packet1+expected_packet2, "E23"); ASSERT_FALSE(result.get().Success()); - ASSERT_EQ(buffer2.size(), 0); + ASSERT_EQ(buffer2.size(), 0u); } TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) { @@ -506,7 +504,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) { std::string expected_packet2 = R"("traceid" : 3})"; HandlePacket(server, expected_packet1+expected_packet2, "123456"); ASSERT_TRUE(result.get().Success()); - ASSERT_EQ(buffer.size(), 3); + ASSERT_EQ(buffer.size(), 3u); ASSERT_EQ(buf[0], 0x12); ASSERT_EQ(buf[1], 0x34); ASSERT_EQ(buf[2], 0x56); @@ -518,7 +516,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) { HandlePacket(server, expected_packet1+expected_packet2, "E23"); ASSERT_FALSE(result.get().Success()); - ASSERT_EQ(buffer2.size(), 0); + ASSERT_EQ(buffer2.size(), 0u); } TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) { @@ -545,8 +543,8 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) { R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])"; HandlePacket(server, expected_packet, response1+response2); ASSERT_TRUE(result.get().Success()); - ASSERT_EQ(options.getTraceBufferSize(), 8192); - ASSERT_EQ(options.getMetaDataBufferSize(), 8192); + ASSERT_EQ(options.getTraceBufferSize(), 8192u); + ASSERT_EQ(options.getMetaDataBufferSize(), 8192u); ASSERT_EQ(options.getType(), 1); auto custom_params = options.getTraceParams(); @@ -556,9 +554,8 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) { ASSERT_TRUE(custom_params); ASSERT_EQ(custom_params->GetType(), eStructuredDataTypeDictionary); - ASSERT_TRUE( - custom_params->GetValueForKeyAsInteger("psb", psb_value)); - ASSERT_EQ(psb_value, 1); + ASSERT_TRUE(custom_params->GetValueForKeyAsInteger("psb", psb_value)); + ASSERT_EQ(psb_value, 1u); ASSERT_TRUE( custom_params->GetValueForKeyAsString("tracetech", trace_tech_value)); ASSERT_STREQ(trace_tech_value.data(), "intel-pt"); diff --git a/unittests/tools/CMakeLists.txt b/unittests/tools/CMakeLists.txt new file mode 100644 index 000000000000..2d41864d98f4 --- /dev/null +++ b/unittests/tools/CMakeLists.txt @@ -0,0 +1,3 @@ +if(CMAKE_SYSTEM_NAME MATCHES "Android|Linux|NetBSD") + add_subdirectory(lldb-server) +endif() diff --git a/unittests/tools/lldb-server/CMakeLists.txt b/unittests/tools/lldb-server/CMakeLists.txt new file mode 100644 index 000000000000..b7113c3d260c --- /dev/null +++ b/unittests/tools/lldb-server/CMakeLists.txt @@ -0,0 +1,13 @@ +function(add_lldb_test_executable test_name) + set(EXCLUDE_FROM_ALL ON) + add_llvm_executable(${test_name} NO_INSTALL_RPATH ${ARGN}) + set(outdir ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}) + set_output_directory(${test_name} BINARY_DIR ${outdir} LIBRARY_DIR ${outdir}) +endfunction() + +add_lldb_test_executable(thread_inferior inferior/thread_inferior.cpp) + +add_definitions(-DLLDB_SERVER="$") +add_definitions(-DTHREAD_INFERIOR="${CMAKE_CURRENT_BINARY_DIR}/thread_inferior") +add_subdirectory(tests) +add_dependencies(LLDBServerTests thread_inferior) diff --git a/unittests/tools/lldb-server/inferior/thread_inferior.cpp b/unittests/tools/lldb-server/inferior/thread_inferior.cpp new file mode 100644 index 000000000000..d968e9ef71ea --- /dev/null +++ b/unittests/tools/lldb-server/inferior/thread_inferior.cpp @@ -0,0 +1,41 @@ +//===-- thread_inferior.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) { + int thread_count = 2; + if (argc > 1) { + thread_count = std::stoi(argv[1], nullptr, 10); + } + + std::atomic delay(true); + std::vector threads; + for (int i = 0; i < thread_count; i++) { + threads.push_back(std::thread([&delay] { + while (delay.load()) + std::this_thread::sleep_for(std::chrono::seconds(1)); + })); + } + + // Cause a break. + volatile char *p = NULL; + *p = 'a'; + + delay.store(false); + for (std::thread& t : threads) { + t.join(); + } + + return 0; +} diff --git a/unittests/tools/lldb-server/tests/CMakeLists.txt b/unittests/tools/lldb-server/tests/CMakeLists.txt new file mode 100644 index 000000000000..4ef4165b27fe --- /dev/null +++ b/unittests/tools/lldb-server/tests/CMakeLists.txt @@ -0,0 +1,15 @@ +add_lldb_unittest(LLDBServerTests + TestClient.cpp + MessageObjects.cpp + ThreadIdsInJstopinfoTest.cpp + + LINK_LIBS + lldbHost + lldbCore + lldbInterpreter + lldbTarget + lldbPluginPlatformLinux + lldbPluginProcessGDBRemote + LINK_COMPONENTS + Support + ) diff --git a/unittests/tools/lldb-server/tests/MessageObjects.cpp b/unittests/tools/lldb-server/tests/MessageObjects.cpp new file mode 100644 index 000000000000..fd44bf6b23a9 --- /dev/null +++ b/unittests/tools/lldb-server/tests/MessageObjects.cpp @@ -0,0 +1,207 @@ +//===-- MessageObjects.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MessageObjects.h" +#include "lldb/Core/StructuredData.h" +#include "llvm/ADT/StringExtras.h" +#include "gtest/gtest.h" + +using namespace lldb_private; +using namespace llvm; +using namespace llvm::support; +namespace llgs_tests { + +Expected ProcessInfo::Create(StringRef response) { + ProcessInfo process_info; + auto elements_or_error = SplitPairList("ProcessInfo", response); + if (!elements_or_error) + return elements_or_error.takeError(); + + auto &elements = *elements_or_error; + if (elements["pid"].getAsInteger(16, process_info.m_pid)) + return make_parsing_error("ProcessInfo: pid"); + if (elements["parent-pid"].getAsInteger(16, process_info.m_parent_pid)) + return make_parsing_error("ProcessInfo: parent-pid"); + if (elements["real-uid"].getAsInteger(16, process_info.m_real_uid)) + return make_parsing_error("ProcessInfo: real-uid"); + if (elements["real-gid"].getAsInteger(16, process_info.m_real_gid)) + return make_parsing_error("ProcessInfo: real-uid"); + if (elements["effective-uid"].getAsInteger(16, process_info.m_effective_uid)) + return make_parsing_error("ProcessInfo: effective-uid"); + if (elements["effective-gid"].getAsInteger(16, process_info.m_effective_gid)) + return make_parsing_error("ProcessInfo: effective-gid"); + if (elements["ptrsize"].getAsInteger(10, process_info.m_ptrsize)) + return make_parsing_error("ProcessInfo: ptrsize"); + + process_info.m_triple = fromHex(elements["triple"]); + StringRef endian_str = elements["endian"]; + if (endian_str == "little") + process_info.m_endian = support::little; + else if (endian_str == "big") + process_info.m_endian = support::big; + else + return make_parsing_error("ProcessInfo: endian"); + + return process_info; +} + +lldb::pid_t ProcessInfo::GetPid() const { return m_pid; } + +endianness ProcessInfo::GetEndian() const { return m_endian; } + +//====== ThreadInfo ============================================================ +ThreadInfo::ThreadInfo(StringRef name, StringRef reason, + const RegisterMap ®isters, unsigned int signal) + : m_name(name.str()), m_reason(reason.str()), m_registers(registers), + m_signal(signal) {} + +StringRef ThreadInfo::ReadRegister(unsigned int register_id) const { + return m_registers.lookup(register_id); +} + +bool ThreadInfo::ReadRegisterAsUint64(unsigned int register_id, + uint64_t &value) const { + StringRef value_str(m_registers.lookup(register_id)); + if (value_str.getAsInteger(16, value)) { + GTEST_LOG_(ERROR) + << formatv("ThreadInfo: Unable to parse register value at {0}.", + register_id) + .str(); + return false; + } + + sys::swapByteOrder(value); + return true; +} + +//====== JThreadsInfo ========================================================== +Expected JThreadsInfo::Create(StringRef response, + endianness endian) { + JThreadsInfo jthreads_info; + + StructuredData::ObjectSP json = StructuredData::ParseJSON(response); + StructuredData::Array *array = json->GetAsArray(); + if (!array) + return make_parsing_error("JThreadsInfo: JSON array"); + + for (size_t i = 0; i < array->GetSize(); i++) { + StructuredData::Dictionary *thread_info; + array->GetItemAtIndexAsDictionary(i, thread_info); + if (!thread_info) + return make_parsing_error("JThreadsInfo: JSON obj at {0}", i); + + StringRef name, reason; + thread_info->GetValueForKeyAsString("name", name); + thread_info->GetValueForKeyAsString("reason", reason); + uint64_t signal; + thread_info->GetValueForKeyAsInteger("signal", signal); + uint64_t tid; + thread_info->GetValueForKeyAsInteger("tid", tid); + + StructuredData::Dictionary *register_dict; + thread_info->GetValueForKeyAsDictionary("registers", register_dict); + if (!register_dict) + return make_parsing_error("JThreadsInfo: registers JSON obj"); + + RegisterMap registers; + + auto keys_obj = register_dict->GetKeys(); + auto keys = keys_obj->GetAsArray(); + for (size_t i = 0; i < keys->GetSize(); i++) { + StringRef key_str, value_str; + keys->GetItemAtIndexAsString(i, key_str); + register_dict->GetValueForKeyAsString(key_str, value_str); + unsigned int register_id; + if (key_str.getAsInteger(10, register_id)) + return make_parsing_error("JThreadsInfo: register key[{0}]", i); + + registers[register_id] = value_str.str(); + } + + jthreads_info.m_thread_infos[tid] = + ThreadInfo(name, reason, registers, signal); + } + + return jthreads_info; +} + +const ThreadInfoMap &JThreadsInfo::GetThreadInfos() const { + return m_thread_infos; +} + +//====== StopReply ============================================================= +const U64Map &StopReply::GetThreadPcs() const { return m_thread_pcs; } + +Expected StopReply::Create(StringRef response, + llvm::support::endianness endian) { + StopReply stop_reply; + + auto elements_or_error = SplitPairList("StopReply", response); + if (auto split_error = elements_or_error.takeError()) { + return std::move(split_error); + } + + auto elements = *elements_or_error; + stop_reply.m_name = elements["name"]; + stop_reply.m_reason = elements["reason"]; + + SmallVector threads; + SmallVector pcs; + elements["threads"].split(threads, ','); + elements["thread-pcs"].split(pcs, ','); + if (threads.size() != pcs.size()) + return make_parsing_error("StopReply: thread/PC count mismatch"); + + for (size_t i = 0; i < threads.size(); i++) { + lldb::tid_t thread_id; + uint64_t pc; + if (threads[i].getAsInteger(16, thread_id)) + return make_parsing_error("StopReply: thread ID at [{0}].", i); + if (pcs[i].getAsInteger(16, pc)) + return make_parsing_error("StopReply: thread PC at [{0}].", i); + + stop_reply.m_thread_pcs[thread_id] = pc; + } + + for (auto i = elements.begin(); i != elements.end(); i++) { + StringRef key = i->getKey(); + StringRef val = i->getValue(); + if (key.size() >= 9 && key[0] == 'T' && key.substr(3, 6) == "thread") { + if (val.getAsInteger(16, stop_reply.m_thread)) + return make_parsing_error("StopReply: thread id"); + if (key.substr(1, 2).getAsInteger(16, stop_reply.m_signal)) + return make_parsing_error("StopReply: stop signal"); + } else if (key.size() == 2) { + unsigned int reg; + if (!key.getAsInteger(16, reg)) { + stop_reply.m_registers[reg] = val.str(); + } + } + } + + return stop_reply; +} + +//====== Globals =============================================================== +Expected> SplitPairList(StringRef caller, StringRef str) { + SmallVector elements; + str.split(elements, ';'); + + StringMap pairs; + for (StringRef s : elements) { + std::pair pair = s.split(':'); + if (pairs.count(pair.first)) + return make_parsing_error("{0}: Duplicate Key: {1}", caller, pair.first); + + pairs.insert(s.split(':')); + } + + return pairs; +} +} // namespace llgs_tests diff --git a/unittests/tools/lldb-server/tests/MessageObjects.h b/unittests/tools/lldb-server/tests/MessageObjects.h new file mode 100644 index 000000000000..82551e2bb549 --- /dev/null +++ b/unittests/tools/lldb-server/tests/MessageObjects.h @@ -0,0 +1,102 @@ +//===-- MessageObjects.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-types.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" +#include + +namespace llgs_tests { +class ThreadInfo; +typedef llvm::DenseMap ThreadInfoMap; +typedef llvm::DenseMap U64Map; +typedef llvm::DenseMap RegisterMap; + +class ProcessInfo { +public: + static llvm::Expected Create(llvm::StringRef response); + lldb::pid_t GetPid() const; + llvm::support::endianness GetEndian() const; + +private: + ProcessInfo() = default; + lldb::pid_t m_pid; + lldb::pid_t m_parent_pid; + uint32_t m_real_uid; + uint32_t m_real_gid; + uint32_t m_effective_uid; + uint32_t m_effective_gid; + std::string m_triple; + llvm::SmallString<16> m_ostype; + llvm::support::endianness m_endian; + unsigned int m_ptrsize; +}; + +class ThreadInfo { +public: + ThreadInfo() = default; + ThreadInfo(llvm::StringRef name, llvm::StringRef reason, + const RegisterMap ®isters, unsigned int signal); + + llvm::StringRef ReadRegister(unsigned int register_id) const; + bool ReadRegisterAsUint64(unsigned int register_id, uint64_t &value) const; + +private: + std::string m_name; + std::string m_reason; + RegisterMap m_registers; + unsigned int m_signal; +}; + +class JThreadsInfo { +public: + static llvm::Expected Create(llvm::StringRef response, + llvm::support::endianness endian); + + const ThreadInfoMap &GetThreadInfos() const; + +private: + JThreadsInfo() = default; + ThreadInfoMap m_thread_infos; +}; + +class StopReply { +public: + static llvm::Expected Create(llvm::StringRef response, + llvm::support::endianness endian); + const U64Map &GetThreadPcs() const; + +private: + StopReply() = default; + void ParseResponse(llvm::StringRef response, + llvm::support::endianness endian); + unsigned int m_signal; + lldb::tid_t m_thread; + std::string m_name; + U64Map m_thread_pcs; + RegisterMap m_registers; + std::string m_reason; +}; + +// Common functions for parsing packet data. +llvm::Expected> +SplitPairList(llvm::StringRef caller, llvm::StringRef s); + +template +llvm::Error make_parsing_error(llvm::StringRef format, Args &&... args) { + std::string error = + "Unable to parse " + + llvm::formatv(format.data(), std::forward(args)...).str(); + return llvm::make_error(error, + llvm::inconvertibleErrorCode()); +} +} // namespace llgs_tests diff --git a/unittests/tools/lldb-server/tests/TestClient.cpp b/unittests/tools/lldb-server/tests/TestClient.cpp new file mode 100644 index 000000000000..540d7979055c --- /dev/null +++ b/unittests/tools/lldb-server/tests/TestClient.cpp @@ -0,0 +1,287 @@ +//===-- TestClient.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "TestClient.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" +#include "lldb/Host/posix/ProcessLauncherPosix.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Target/ProcessLaunchInfo.h" +#include "llvm/ADT/StringExtras.h" +#include "gtest/gtest.h" +#include +#include +#include +#include + +using namespace lldb; +using namespace lldb_private; +using namespace llvm; + +namespace llgs_tests { +void TestClient::Initialize() { HostInfo::Initialize(); } + +TestClient::TestClient(const std::string &test_name, + const std::string &test_case_name) + : m_test_name(test_name), m_test_case_name(test_case_name), + m_pc_register(UINT_MAX) {} + +TestClient::~TestClient() {} + +bool TestClient::StartDebugger() { + const ArchSpec &arch_spec = HostInfo::GetArchitecture(); + Args args; + args.AppendArgument(LLDB_SERVER); + args.AppendArgument("gdbserver"); + args.AppendArgument("--log-channels=gdb-remote packets"); + args.AppendArgument("--reverse-connect"); + std::string log_file_name = GenerateLogFileName(arch_spec); + if (log_file_name.size()) { + args.AppendArgument("--log-file=" + log_file_name); + } + + Status error; + TCPSocket listen_socket(true, false); + error = listen_socket.Listen("127.0.0.1:0", 5); + if (error.Fail()) { + GTEST_LOG_(ERROR) << "Unable to open listen socket."; + return false; + } + + char connect_remote_address[64]; + snprintf(connect_remote_address, sizeof(connect_remote_address), + "localhost:%u", listen_socket.GetLocalPortNumber()); + + args.AppendArgument(connect_remote_address); + + m_server_process_info.SetArchitecture(arch_spec); + m_server_process_info.SetArguments(args, true); + Status status = Host::LaunchProcess(m_server_process_info); + if (status.Fail()) { + GTEST_LOG_(ERROR) + << formatv("Failure to launch lldb server: {0}.", status).str(); + return false; + } + + char connect_remote_uri[64]; + snprintf(connect_remote_uri, sizeof(connect_remote_uri), "connect://%s", + connect_remote_address); + Socket *accept_socket; + listen_socket.Accept(accept_socket); + SetConnection(new ConnectionFileDescriptor(accept_socket)); + + SendAck(); // Send this as a handshake. + return true; +} + +bool TestClient::StopDebugger() { + std::string response; + return SendMessage("k", response, PacketResult::ErrorDisconnected); +} + +bool TestClient::SetInferior(llvm::ArrayRef inferior_args) { + std::stringstream command; + command << "A"; + for (size_t i = 0; i < inferior_args.size(); i++) { + if (i > 0) + command << ','; + std::string hex_encoded = toHex(inferior_args[i]); + command << hex_encoded.size() << ',' << i << ',' << hex_encoded; + } + + if (!SendMessage(command.str())) + return false; + if (!SendMessage("qLaunchSuccess")) + return false; + std::string response; + if (!SendMessage("qProcessInfo", response)) + return false; + auto create_or_error = ProcessInfo::Create(response); + if (auto create_error = create_or_error.takeError()) { + GTEST_LOG_(ERROR) << toString(std::move(create_error)); + return false; + } + + m_process_info = *create_or_error; + return true; +} + +bool TestClient::ListThreadsInStopReply() { + return SendMessage("QListThreadsInStopReply"); +} + +bool TestClient::SetBreakpoint(unsigned long address) { + std::stringstream command; + command << "Z0," << std::hex << address << ",1"; + return SendMessage(command.str()); +} + +bool TestClient::ContinueAll() { return Continue("vCont;c"); } + +bool TestClient::ContinueThread(unsigned long thread_id) { + return Continue(formatv("vCont;c:{0:x-}", thread_id).str()); +} + +const ProcessInfo &TestClient::GetProcessInfo() { return *m_process_info; } + +Optional TestClient::GetJThreadsInfo() { + std::string response; + if (!SendMessage("jThreadsInfo", response)) + return llvm::None; + auto creation = JThreadsInfo::Create(response, m_process_info->GetEndian()); + if (auto create_error = creation.takeError()) { + GTEST_LOG_(ERROR) << toString(std::move(create_error)); + return llvm::None; + } + + return std::move(*creation); +} + +const StopReply &TestClient::GetLatestStopReply() { + return m_stop_reply.getValue(); +} + +bool TestClient::SendMessage(StringRef message) { + std::string dummy_string; + return SendMessage(message, dummy_string); +} + +bool TestClient::SendMessage(StringRef message, std::string &response_string) { + if (!SendMessage(message, response_string, PacketResult::Success)) + return false; + else if (response_string[0] == 'E') { + GTEST_LOG_(ERROR) << "Error " << response_string + << " while sending message: " << message.str(); + return false; + } + + return true; +} + +bool TestClient::SendMessage(StringRef message, std::string &response_string, + PacketResult expected_result) { + StringExtractorGDBRemote response; + GTEST_LOG_(INFO) << "Send Packet: " << message.str(); + PacketResult result = SendPacketAndWaitForResponse(message, response, false); + response.GetEscapedBinaryData(response_string); + GTEST_LOG_(INFO) << "Read Packet: " << response_string; + if (result != expected_result) { + GTEST_LOG_(ERROR) << FormatFailedResult(message, result); + return false; + } + + return true; +} + +unsigned int TestClient::GetPcRegisterId() { + if (m_pc_register != UINT_MAX) + return m_pc_register; + + for (unsigned int register_id = 0;; register_id++) { + std::string message = formatv("qRegisterInfo{0:x-}", register_id).str(); + std::string response; + if (!SendMessage(message, response)) { + GTEST_LOG_(ERROR) << "Unable to query register ID for PC register."; + return UINT_MAX; + } + + auto elements_or_error = SplitPairList("GetPcRegisterId", response); + if (auto split_error = elements_or_error.takeError()) { + GTEST_LOG_(ERROR) << "GetPcRegisterId: Error splitting response: " + << response; + return UINT_MAX; + } + + auto elements = *elements_or_error; + if (elements["alt-name"] == "pc" || elements["generic"] == "pc") { + m_pc_register = register_id; + break; + } + } + + return m_pc_register; +} + +bool TestClient::Continue(StringRef message) { + if (!m_process_info.hasValue()) { + GTEST_LOG_(ERROR) << "Continue() called before m_process_info initialized."; + return false; + } + + std::string response; + if (!SendMessage(message, response)) + return false; + auto creation = StopReply::Create(response, m_process_info->GetEndian()); + if (auto create_error = creation.takeError()) { + GTEST_LOG_(ERROR) << toString(std::move(create_error)); + return false; + } + + m_stop_reply = std::move(*creation); + return true; +} + +std::string TestClient::GenerateLogFileName(const ArchSpec &arch) const { + char *log_directory = getenv("LOG_FILE_DIRECTORY"); + if (!log_directory) + return ""; + + if (!llvm::sys::fs::is_directory(log_directory)) { + GTEST_LOG_(WARNING) << "Cannot access log directory: " << log_directory; + return ""; + } + + std::string log_file_name; + raw_string_ostream log_file(log_file_name); + log_file << log_directory << "/lldb-" << m_test_case_name << '-' + << m_test_name << '-' << arch.GetArchitectureName() << ".log"; + return log_file.str(); +} + +std::string TestClient::FormatFailedResult(const std::string &message, + PacketResult result) { + std::string formatted_error; + raw_string_ostream error_stream(formatted_error); + error_stream << "Failure sending message: " << message << " Result: "; + + switch (result) { + case PacketResult::ErrorSendFailed: + error_stream << "ErrorSendFailed"; + break; + case PacketResult::ErrorSendAck: + error_stream << "ErrorSendAck"; + break; + case PacketResult::ErrorReplyFailed: + error_stream << "ErrorReplyFailed"; + break; + case PacketResult::ErrorReplyTimeout: + error_stream << "ErrorReplyTimeout"; + break; + case PacketResult::ErrorReplyInvalid: + error_stream << "ErrorReplyInvalid"; + break; + case PacketResult::ErrorReplyAck: + error_stream << "ErrorReplyAck"; + break; + case PacketResult::ErrorDisconnected: + error_stream << "ErrorDisconnected"; + break; + case PacketResult::ErrorNoSequenceLock: + error_stream << "ErrorNoSequenceLock"; + break; + default: + error_stream << "Unknown Error"; + } + + error_stream.str(); + return formatted_error; +} +} // namespace llgs_tests diff --git a/unittests/tools/lldb-server/tests/TestClient.h b/unittests/tools/lldb-server/tests/TestClient.h new file mode 100644 index 000000000000..ae620cc97207 --- /dev/null +++ b/unittests/tools/lldb-server/tests/TestClient.h @@ -0,0 +1,61 @@ +//===-- TestClient.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MessageObjects.h" +#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Target/ProcessLaunchInfo.h" +#include "llvm/ADT/Optional.h" +#include +#include + +namespace llgs_tests { +// TODO: Make the test client an abstract base class, with different children +// for different types of connections: llgs v. debugserver +class TestClient + : public lldb_private::process_gdb_remote::GDBRemoteCommunicationClient { +public: + static void Initialize(); + TestClient(const std::string &test_name, const std::string &test_case_name); + virtual ~TestClient(); + LLVM_NODISCARD bool StartDebugger(); + LLVM_NODISCARD bool StopDebugger(); + LLVM_NODISCARD bool SetInferior(llvm::ArrayRef inferior_args); + LLVM_NODISCARD bool ListThreadsInStopReply(); + LLVM_NODISCARD bool SetBreakpoint(unsigned long address); + LLVM_NODISCARD bool ContinueAll(); + LLVM_NODISCARD bool ContinueThread(unsigned long thread_id); + const ProcessInfo &GetProcessInfo(); + llvm::Optional GetJThreadsInfo(); + const StopReply &GetLatestStopReply(); + LLVM_NODISCARD bool SendMessage(llvm::StringRef message); + LLVM_NODISCARD bool SendMessage(llvm::StringRef message, + std::string &response_string); + LLVM_NODISCARD bool SendMessage(llvm::StringRef message, + std::string &response_string, + PacketResult expected_result); + unsigned int GetPcRegisterId(); + +private: + LLVM_NODISCARD bool Continue(llvm::StringRef message); + LLVM_NODISCARD bool GenerateConnectionAddress(std::string &address); + std::string GenerateLogFileName(const lldb_private::ArchSpec &arch) const; + std::string FormatFailedResult( + const std::string &message, + lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult + result); + + llvm::Optional m_process_info; + llvm::Optional m_stop_reply; + lldb_private::ProcessLaunchInfo m_server_process_info; + std::string m_test_name; + std::string m_test_case_name; + unsigned int m_pc_register; +}; +} // namespace llgs_tests diff --git a/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp b/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp new file mode 100644 index 000000000000..961b0a3b3167 --- /dev/null +++ b/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp @@ -0,0 +1,58 @@ +//===-- ThreadsInJstopinfoTest.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "TestClient.h" +#include "gtest/gtest.h" +#include + +using namespace llgs_tests; + +class ThreadsInJstopinfoTest : public ::testing::Test { +protected: + virtual void SetUp() { TestClient::Initialize(); } +}; + +TEST_F(ThreadsInJstopinfoTest, TestStopReplyContainsThreadPcsLlgs) { + std::vector inferior_args; + // This inferior spawns N threads, then forces a break. + inferior_args.push_back(THREAD_INFERIOR); + inferior_args.push_back("4"); + + auto test_info = ::testing::UnitTest::GetInstance()->current_test_info(); + + TestClient client(test_info->name(), test_info->test_case_name()); + ASSERT_TRUE(client.StartDebugger()); + ASSERT_TRUE(client.SetInferior(inferior_args)); + ASSERT_TRUE(client.ListThreadsInStopReply()); + ASSERT_TRUE(client.ContinueAll()); + unsigned int pc_reg = client.GetPcRegisterId(); + ASSERT_NE(pc_reg, UINT_MAX); + + auto jthreads_info = client.GetJThreadsInfo(); + ASSERT_TRUE(jthreads_info); + + auto stop_reply = client.GetLatestStopReply(); + auto stop_reply_pcs = stop_reply.GetThreadPcs(); + auto thread_infos = jthreads_info->GetThreadInfos(); + ASSERT_EQ(stop_reply_pcs.size(), thread_infos.size()) + << "Thread count mismatch."; + + for (auto stop_reply_pc : stop_reply_pcs) { + unsigned long tid = stop_reply_pc.first; + ASSERT_TRUE(thread_infos.find(tid) != thread_infos.end()) + << "Thread ID: " << tid << " not in JThreadsInfo."; + uint64_t pc_value; + ASSERT_TRUE(thread_infos[tid].ReadRegisterAsUint64(pc_reg, pc_value)) + << "Failure reading ThreadInfo register " << pc_reg; + ASSERT_EQ(stop_reply_pcs[tid], pc_value) + << "Mismatched PC for thread: " << tid; + } + + ASSERT_TRUE(client.StopDebugger()); +} From 325377b57338e700317f5e423e5b0f1c08d99a39 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 16 Jun 2017 21:03:44 +0000 Subject: [PATCH 15/22] Vendor import of clang trunk r305575: https://llvm.org/svn/llvm-project/cfe/trunk@305575 --- docs/ClangFormatStyleOptions.rst | 10 +- docs/ReleaseNotes.rst | 25 ++ docs/UndefinedBehaviorSanitizer.rst | 6 + include/clang/Basic/AllDiagnostics.h | 2 +- include/clang/Basic/BuiltinsPPC.def | 8 +- .../Basic/DiagnosticSerializationKinds.td | 34 +- include/clang/Format/Format.h | 36 ++ include/clang/Frontend/FrontendOptions.h | 4 +- include/clang/Lex/MacroArgs.h | 16 +- include/clang/Sema/Sema.h | 2 + lib/AST/ASTContext.cpp | 3 +- lib/AST/ExprClassification.cpp | 4 +- lib/AST/ExprConstant.cpp | 33 +- lib/AST/ItaniumMangle.cpp | 2 + lib/AST/ODRHash.cpp | 47 ++- lib/CodeGen/BackendUtil.cpp | 8 +- lib/CodeGen/CGBuiltin.cpp | 21 + lib/CodeGen/CGCall.cpp | 2 + lib/CodeGen/CGCoroutine.cpp | 66 ++- lib/CodeGen/CGDebugInfo.cpp | 18 +- lib/CodeGen/CGExpr.cpp | 47 ++- lib/CodeGen/CGExprScalar.cpp | 51 ++- lib/CodeGen/CGOpenMPRuntime.cpp | 2 +- lib/CodeGen/CodeGenFunction.h | 4 + lib/CodeGen/CodeGenModule.cpp | 10 +- lib/CodeGen/CodeGenModule.h | 7 +- lib/Driver/ToolChains/Clang.cpp | 3 + lib/Format/Format.cpp | 16 +- lib/Format/NamespaceEndCommentsFixer.cpp | 64 ++- lib/Format/UnwrappedLineFormatter.cpp | 80 +++- lib/Format/UnwrappedLineParser.cpp | 5 + lib/Format/WhitespaceManager.h | 4 + lib/Frontend/ASTConsumers.cpp | 2 +- lib/Frontend/CompilerInvocation.cpp | 10 +- lib/Index/IndexDecl.cpp | 13 + lib/Index/IndexSymbol.cpp | 4 + lib/Lex/MacroArgs.cpp | 20 +- lib/Sema/SemaCodeComplete.cpp | 10 +- lib/Sema/SemaCoroutine.cpp | 35 +- lib/Sema/SemaDeclAttr.cpp | 14 +- lib/Sema/SemaExpr.cpp | 8 +- lib/Sema/SemaExprCXX.cpp | 9 +- lib/Sema/SemaLambda.cpp | 16 +- lib/Sema/SemaStmt.cpp | 58 ++- lib/Serialization/ASTReader.cpp | 154 +++++++ lib/Serialization/ASTReaderDecl.cpp | 85 ++-- lib/StaticAnalyzer/Core/CallEvent.cpp | 6 + test/Analysis/DynamicTypePropagation.m | 12 + test/Analysis/analyzer_test.py | 31 +- test/CodeCompletion/member-access.cpp | 18 + test/CodeGen/Inputs/thinlto-multi-module.ll | 9 + test/CodeGen/attributes.c | 10 + test/CodeGen/avx-builtins.c | 48 +++ test/CodeGen/builtins-ppc-error.c | 33 ++ test/CodeGen/dependent-lib.c | 8 +- test/CodeGen/linker-option.c | 4 +- test/CodeGen/mips-debug-info-bitfield.c | 17 + test/CodeGen/pragma-comment.c | 4 +- test/CodeGen/pragma-detect_mismatch.c | 4 +- test/CodeGen/thinlto-backend-option.ll | 6 +- test/CodeGen/thinlto-multi-module.ll | 4 +- test/CodeGen/ubsan-pointer-overflow.m | 72 +++- test/CodeGen/ubsan-volatile.c | 7 + test/CodeGenCXX/ms-thread_local.cpp | 4 +- test/CodeGenCoroutines/coro-await.cpp | 50 ++- test/CodeGenObjC/availability-cf-link-guard.m | 5 +- test/Coverage/ast-printing.c | 1 + test/Coverage/ast-printing.cpp | 1 + test/Driver/m_and_mm.c | 12 + test/Index/Core/index-source.cpp | 44 +- test/Index/availability.c | 18 +- test/Misc/pr32207.c | 4 + test/Modules/autolink.m | 6 +- test/Modules/autolinkTBD.m | 6 +- test/Modules/module-impl-with-link.c | 3 +- test/Modules/odr_hash.cpp | 391 +++++++++++++++++- test/Sema/integer-overflow.c | 8 - test/Sema/xray-log-args-class.cpp | 7 + test/SemaCXX/co_await-range-for.cpp | 165 ++++++++ test/SemaCXX/cxx1z-decomposition.cpp | 6 + test/SemaCXX/nested-name-spec.cpp | 7 + test/SemaCXX/warn-unused-lambda-capture.cpp | 5 + tools/clang-format/git-clang-format | 2 + tools/libclang/CIndex.cpp | 120 ++++-- unittests/AST/CommentLexer.cpp | 3 +- unittests/ASTMatchers/ASTMatchersTest.h | 9 +- unittests/Basic/VirtualFileSystemTest.cpp | 6 +- unittests/Format/FormatTest.cpp | 261 ++++++++++++ .../Format/NamespaceEndCommentsFixerTest.cpp | 56 +++ unittests/Lex/LexerTest.cpp | 73 +++- unittests/Tooling/LookupTest.cpp | 6 +- 91 files changed, 2244 insertions(+), 406 deletions(-) create mode 100644 test/CodeGen/Inputs/thinlto-multi-module.ll create mode 100644 test/CodeGen/mips-debug-info-bitfield.c create mode 100644 test/CodeGen/ubsan-volatile.c create mode 100644 test/Misc/pr32207.c create mode 100644 test/Sema/xray-log-args-class.cpp create mode 100644 test/SemaCXX/co_await-range-for.cpp diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index 9e0bacaf7c14..fb014241809c 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -521,12 +521,12 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ true: - class foo {}; - - false: class foo {}; + false: + class foo {}; + * ``bool AfterControlStatement`` Wrap control statements (``if``/``for``/``while``/``switch``/..). .. code-block:: c++ @@ -603,12 +603,12 @@ the configuration (without a prefix: ``Auto``). struct foo { int x; - } + }; false: struct foo { int x; - } + }; * ``bool AfterUnion`` Wrap union definitions. diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index f7e31e5c98d5..f9a3317811eb 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -187,6 +187,31 @@ Static Analyzer ... +Undefined Behavior Sanitizer (UBSan) +------------------------------------ + +- The Undefined Behavior Sanitizer has a new check for pointer overflow. This + check is on by default. The flag to control this functionality is + -fsanitize=pointer-overflow. + + Pointer overflow is an indicator of undefined behavior: when a pointer + indexing expression wraps around the address space, or produces other + unexpected results, its result may not point to a valid object. + +- UBSan has several new checks which detect violations of nullability + annotations. These checks are off by default. The flag to control this group + of checks is -fsanitize=nullability. The checks can be individially enabled + by -fsanitize=nullability-arg (which checks calls), + -fsanitize=nullability-assign (which checks assignments), and + -fsanitize=nullability-return (which checks return statements). + +- UBSan can now detect invalid loads from bitfields and from ObjC BOOLs. + +- UBSan can now avoid emitting unnecessary type checks in C++ class methods and + in several other cases where the result is known at compile-time. UBSan can + also avoid emitting unnecessary overflow checks in arithmetic expressions + with promoted integer operands. + Core Analysis Improvements ========================== diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst index ea776a770470..85dd549baaf8 100644 --- a/docs/UndefinedBehaviorSanitizer.rst +++ b/docs/UndefinedBehaviorSanitizer.rst @@ -148,6 +148,12 @@ You can also use the following check groups: nullability does not have undefined behavior, it is often unintentional, so UBSan offers to catch it. +Volatile +-------- + +The ``null``, ``alignment``, ``object-size``, and ``vptr`` checks do not apply +to pointers to types with the ``volatile`` qualifier. + Stack traces and report symbolization ===================================== If you want UBSan to print symbolized stack trace for each error report, you diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h index 18a2b8a31871..fc861a1952a5 100644 --- a/include/clang/Basic/AllDiagnostics.h +++ b/include/clang/Basic/AllDiagnostics.h @@ -28,7 +28,7 @@ namespace clang { template class StringSizerHelper { - char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1]; + static_assert(SizeOfStr <= FieldType(~0U), "Field too small!"); public: enum { Size = SizeOfStr }; }; diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index 119490314b26..faa70a48edc3 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -51,10 +51,10 @@ BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "") BUILTIN(__builtin_altivec_vrfip, "V4fV4f", "") -BUILTIN(__builtin_altivec_vcfsx, "V4fV4ii", "") -BUILTIN(__builtin_altivec_vcfux, "V4fV4ii", "") -BUILTIN(__builtin_altivec_vctsxs, "V4SiV4fi", "") -BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fi", "") +BUILTIN(__builtin_altivec_vcfsx, "V4fV4iIi", "") +BUILTIN(__builtin_altivec_vcfux, "V4fV4iIi", "") +BUILTIN(__builtin_altivec_vctsxs, "V4SiV4fIi", "") +BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fIi", "") BUILTIN(__builtin_altivec_dss, "vUi", "") BUILTIN(__builtin_altivec_dssall, "v", "") diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 7c9e8c8980aa..0a59a633232c 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -121,10 +121,12 @@ def err_module_odr_violation_mismatch_decl : Error< "%q0 has different definitions in different modules; first difference is " "%select{definition in module '%2'|defined here}1 found " "%select{end of class|public access specifier|private access specifier|" - "protected access specifier|static assert|field|method}3">; + "protected access specifier|static assert|field|method|type alias|typedef|" + "data member}3">; def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " "%select{end of class|public access specifier|private access specifier|" - "protected access specifier|static assert|field|method}1">; + "protected access specifier|static assert|field|method|type alias|typedef|" + "data member}1">; def err_module_odr_violation_mismatch_decl_diff : Error< "%q0 has different definitions in different modules; first difference is " @@ -149,7 +151,17 @@ def err_module_odr_violation_mismatch_decl_diff : Error< "method %4 is %select{not inline|inline}5|" "method %4 that has %5 parameter%s5|" "method %4 with %ordinal5 parameter of type %6%select{| decayed from %8}7|" - "method %4 with %ordinal5 parameter named %6}3">; + "method %4 with %ordinal5 parameter named %6|" + "method %4 with %ordinal5 parameter with%select{out|}6 a default argument|" + "method %4 with %ordinal5 parameter with a default argument|" + "%select{typedef|type alias}4 name %5|" + "%select{typedef|type alias}4 %5 with underlying type %6|" + "data member with name %4|" + "data member %4 with type %5|" + "data member %4 with%select{out|}5 an initializer|" + "data member %4 with an initializer|" + "data member %4 %select{is constexpr|is not constexpr}5|" + "}3">; def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "%select{" @@ -172,15 +184,27 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "method %2 is %select{not inline|inline}3|" "method %2 that has %3 parameter%s3|" "method %2 with %ordinal3 parameter of type %4%select{| decayed from %6}5|" - "method %2 with %ordinal3 parameter named %4}1">; + "method %2 with %ordinal3 parameter named %4|" + "method %2 with %ordinal3 parameter with%select{out|}4 a default argument|" + "method %2 with %ordinal3 parameter with a different default argument|" + "%select{typedef|type alias}2 name %3|" + "%select{typedef|type alias}2 %3 with different underlying type %4|" + "data member with name %2|" + "data member %2 with different type %3|" + "data member %2 with%select{out|}3 an initializer|" + "data member %2 with a different initializer|" + "data member %2 %select{is constexpr|is not constexpr}3|" + "}1">; def err_module_odr_violation_mismatch_decl_unknown : Error< "%q0 %select{with definition in module '%2'|defined here}1 has different " "definitions in different modules; first difference is this " - "%select{||||static assert|field|method|unexpected decl}3">; + "%select{||||static assert|field|method|type alias|typedef|data member|" + "unexpected decl}3">; def note_module_odr_violation_mismatch_decl_unknown : Note< "but in '%0' found " "%select{||||different static assert|different field|different method|" + "different type alias|different typedef|different data member|" "another unexpected decl}1">; def warn_duplicate_module_file_extension : Warning< diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 7ec3e22ca4d7..1891c06eba51 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -688,6 +688,18 @@ struct FormatStyle { bool BeforeElse; /// \brief Indent the wrapped braces themselves. bool IndentBraces; + /// \brief If ``false``, empty function body can be put on a single line. + /// This option is used only if the opening brace of the function has + /// already been wrapped, i.e. the `AfterFunction` brace wrapping mode is + /// set, and the function could/should not be put on a single line (as per + /// `AllowShortFunctionsOnASingleLine` and constructor formatting options). + /// \code + /// int f() vs. inf f() + /// {} { + /// } + /// \endcode + /// + bool SplitEmptyFunctionBody; }; /// \brief Control of individual brace wrapping cases. @@ -779,6 +791,29 @@ struct FormatStyle { /// \endcode bool BreakBeforeInheritanceComma; + /// \brief If ``true``, consecutive namespace declarations will be on the same + /// line. If ``false``, each namespace is declared on a new line. + /// \code + /// true: + /// namespace Foo { namespace Bar { + /// }} + /// + /// false: + /// namespace Foo { + /// namespace Bar { + /// } + /// } + /// \endcode + /// + /// If it does not fit on a single line, the overflowing namespaces get + /// wrapped: + /// \code + /// namespace Foo { namespace Bar { + /// namespace Extra { + /// }}} + /// \endcode + bool CompactNamespaces; + /// \brief If the constructor initializers don't fit on a line, put each /// initializer on its own line. /// \code @@ -1410,6 +1445,7 @@ struct FormatStyle { BreakBeforeBraces == R.BreakBeforeBraces && BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators && BreakConstructorInitializers == R.BreakConstructorInitializers && + CompactNamespaces == R.CompactNamespaces && BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations && BreakStringLiterals == R.BreakStringLiterals && ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas && diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 36c046891b47..e757a7e397e3 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -317,8 +317,8 @@ class FrontendOptions { /// \brief Auxiliary triple for CUDA compilation. std::string AuxTriple; - /// \brief If non-empty, search the pch input file as it was a header - // included by this file. + /// \brief If non-empty, search the pch input file as if it was a header + /// included by this file. std::string FindPchSource; /// Filename to write statistics to. diff --git a/include/clang/Lex/MacroArgs.h b/include/clang/Lex/MacroArgs.h index 7b2a48561ff6..cfe46ceb0979 100644 --- a/include/clang/Lex/MacroArgs.h +++ b/include/clang/Lex/MacroArgs.h @@ -53,9 +53,12 @@ class MacroArgs { /// Preprocessor owns which we use to avoid thrashing malloc/free. MacroArgs *ArgCache; - MacroArgs(unsigned NumToks, bool varargsElided) - : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided), - ArgCache(nullptr) {} + /// MacroArgs - The number of arguments the invoked macro expects. + unsigned NumMacroArgs; + + MacroArgs(unsigned NumToks, bool varargsElided, unsigned MacroArgs) + : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided), + ArgCache(nullptr), NumMacroArgs(MacroArgs) {} ~MacroArgs() = default; public: @@ -94,10 +97,9 @@ class MacroArgs { SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd); - /// getNumArguments - Return the number of arguments passed into this macro - /// invocation. - unsigned getNumArguments() const { return NumUnexpArgTokens; } - + /// getNumMacroArguments - Return the number of arguments the invoked macro + /// expects. + unsigned getNumMacroArguments() const { return NumMacroArgs; } /// isVarargsElidedUse - Return true if this is a C99 style varargs macro /// invocation and there was no argument specified for the "..." argument. If diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 8025668e664e..1dedf4ba24ce 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -8364,6 +8364,8 @@ class Sema { //===--------------------------------------------------------------------===// // C++ Coroutines TS // + bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, + StringRef Keyword); ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E); ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E); StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 62b19685c677..2300801c1a9c 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3565,7 +3565,7 @@ QualType ASTContext::getSubstTemplateTypeParmPackType( = new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon, ArgPack); Types.push_back(SubstParm); - SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); + SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos); return QualType(SubstParm, 0); } @@ -8547,6 +8547,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, HowLong = 2; break; } + break; } } diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index c035a42439a3..d149bdd0cdf9 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -190,7 +190,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: - case Expr::CoyieldExprClass: return Cl::CL_PRValue; // Next come the complicated cases. @@ -414,7 +413,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return ClassifyInternal(Ctx, cast(E)->getInit(0)); case Expr::CoawaitExprClass: - return ClassifyInternal(Ctx, cast(E)->getResumeExpr()); + case Expr::CoyieldExprClass: + return ClassifyInternal(Ctx, cast(E)->getResumeExpr()); } llvm_unreachable("unhandled expression kind in classification"); diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 17d0ce67dcf9..768947d00ac4 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -4588,7 +4588,7 @@ class ExprEvaluatorBase } bool handleCallExpr(const CallExpr *E, APValue &Result, - const LValue *ResultSlot) { + const LValue *ResultSlot) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); @@ -4597,23 +4597,6 @@ class ExprEvaluatorBase auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; - struct EvaluateIgnoredRAII { - public: - EvaluateIgnoredRAII(EvalInfo &Info, llvm::ArrayRef ToEval) - : Info(Info), ToEval(ToEval) {} - ~EvaluateIgnoredRAII() { - if (Info.noteFailure()) { - for (auto E : ToEval) - EvaluateIgnoredValue(Info, E); - } - } - void cancel() { ToEval = {}; } - void drop_front() { ToEval = ToEval.drop_front(); } - private: - EvalInfo &Info; - llvm::ArrayRef ToEval; - } EvalArguments(Info, Args); - // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { const ValueDecl *Member = nullptr; @@ -4663,12 +4646,10 @@ class ExprEvaluatorBase if (Args.empty()) return Error(E); - const Expr *FirstArg = Args[0]; - Args = Args.drop_front(); - EvalArguments.drop_front(); - if (!EvaluateObjectArgument(Info, FirstArg, ThisVal)) + if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) return false; This = &ThisVal; + Args = Args.slice(1); } else if (MD && MD->isLambdaStaticInvoker()) { // Map the static invoker for the lambda back to the call operator. // Conveniently, we don't have to slice out the 'this' argument (as is @@ -4720,12 +4701,8 @@ class ExprEvaluatorBase const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) - return false; - - EvalArguments.cancel(); - - if (!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || + !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index c9bb45a37eb5..dc25e5213bae 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -4550,9 +4550,11 @@ CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) { const FunctionProtoType *Proto = cast(FD->getType()->getAs()); + FunctionTypeDepthState saved = TrackReturnTypeTags.FunctionTypeDepth.push(); TrackReturnTypeTags.FunctionTypeDepth.enterResultType(); TrackReturnTypeTags.mangleType(Proto->getReturnType()); TrackReturnTypeTags.FunctionTypeDepth.leaveResultType(); + TrackReturnTypeTags.FunctionTypeDepth.pop(saved); return TrackReturnTypeTags.AbiTagsRoot.getSortedUniqueUsedAbiTags(); } diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 08593da89bbd..05bed658f3fc 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -140,7 +140,33 @@ void ODRHash::AddTemplateName(TemplateName Name) { } } -void ODRHash::AddTemplateArgument(TemplateArgument TA) {} +void ODRHash::AddTemplateArgument(TemplateArgument TA) { + const auto Kind = TA.getKind(); + ID.AddInteger(Kind); + + switch (Kind) { + case TemplateArgument::Null: + case TemplateArgument::Type: + case TemplateArgument::Declaration: + case TemplateArgument::NullPtr: + case TemplateArgument::Integral: + break; + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + AddTemplateName(TA.getAsTemplateOrTemplatePattern()); + break; + case TemplateArgument::Expression: + AddStmt(TA.getAsExpr()); + break; + case TemplateArgument::Pack: + ID.AddInteger(TA.pack_size()); + for (auto SubTA : TA.pack_elements()) { + AddTemplateArgument(SubTA); + } + break; + } +} + void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {} void ODRHash::clear() { @@ -226,6 +252,17 @@ class ODRDeclVisitor : public ConstDeclVisitor { Inherited::VisitValueDecl(D); } + void VisitVarDecl(const VarDecl *D) { + Hash.AddBoolean(D->isStaticLocal()); + Hash.AddBoolean(D->isConstexpr()); + const bool HasInit = D->hasInit(); + Hash.AddBoolean(HasInit); + if (HasInit) { + AddStmt(D->getInit()); + } + Inherited::VisitVarDecl(D); + } + void VisitParmVarDecl(const ParmVarDecl *D) { // TODO: Handle default arguments. Inherited::VisitParmVarDecl(D); @@ -310,6 +347,7 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) { case Decl::StaticAssert: case Decl::TypeAlias: case Decl::Typedef: + case Decl::Var: return true; } } @@ -527,6 +565,13 @@ class ODRTypeVisitor : public TypeVisitor { Hash.AddTemplateName(T->getTemplateName()); VisitType(T); } + + void VisitTemplateTypeParmType(const TemplateTypeParmType *T) { + ID.AddInteger(T->getDepth()); + ID.AddInteger(T->getIndex()); + Hash.AddBoolean(T->isParameterPack()); + AddDecl(T->getDecl()); + } }; void ODRHash::AddType(const Type *T) { diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 9c4316fb1cd5..bd01902a032b 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -964,11 +964,11 @@ Expected clang::FindThinLTOModule(MemoryBufferRef MBRef) { if (!BMsOrErr) return BMsOrErr.takeError(); - // The bitcode file may contain multiple modules, we want the one with a - // summary. + // The bitcode file may contain multiple modules, we want the one that is + // marked as being the ThinLTO module. for (BitcodeModule &BM : *BMsOrErr) { - Expected HasSummary = BM.hasSummary(); - if (HasSummary && *HasSummary) + Expected LTOInfo = BM.getLTOInfo(); + if (LTOInfo && LTOInfo->IsThinLTO) return BM; } diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 3b4f8854a9ca..8f0c22d1f7ef 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -7923,6 +7923,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } // We can't handle 8-31 immediates with native IR, use the intrinsic. + // Except for predicates that create constants. Intrinsic::ID ID; switch (BuiltinID) { default: llvm_unreachable("Unsupported intrinsic!"); @@ -7930,12 +7931,32 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, ID = Intrinsic::x86_sse_cmp_ps; break; case X86::BI__builtin_ia32_cmpps256: + // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector + // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0... + if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) { + Value *Constant = (CC == 0xf || CC == 0x1f) ? + llvm::Constant::getAllOnesValue(Builder.getInt32Ty()) : + llvm::Constant::getNullValue(Builder.getInt32Ty()); + Value *Vec = Builder.CreateVectorSplat( + Ops[0]->getType()->getVectorNumElements(), Constant); + return Builder.CreateBitCast(Vec, Ops[0]->getType()); + } ID = Intrinsic::x86_avx_cmp_ps_256; break; case X86::BI__builtin_ia32_cmppd: ID = Intrinsic::x86_sse2_cmp_pd; break; case X86::BI__builtin_ia32_cmppd256: + // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector + // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0... + if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) { + Value *Constant = (CC == 0xf || CC == 0x1f) ? + llvm::Constant::getAllOnesValue(Builder.getInt64Ty()) : + llvm::Constant::getNullValue(Builder.getInt64Ty()); + Value *Vec = Builder.CreateVectorSplat( + Ops[0]->getType()->getVectorNumElements(), Constant); + return Builder.CreateBitCast(Vec, Ops[0]->getType()); + } ID = Intrinsic::x86_avx_cmp_pd_256; break; } diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 079064733585..c65dc18be306 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1795,6 +1795,8 @@ void CodeGenModule::ConstructAttributeList( FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); if (TargetDecl->hasAttr()) FuncAttrs.addAttribute(llvm::Attribute::NoReturn); + if (TargetDecl->hasAttr()) + FuncAttrs.addAttribute(llvm::Attribute::Cold); if (TargetDecl->hasAttr()) FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); if (TargetDecl->hasAttr()) diff --git a/lib/CodeGen/CGCoroutine.cpp b/lib/CodeGen/CGCoroutine.cpp index bc5f6327c9a0..a65faa602b33 100644 --- a/lib/CodeGen/CGCoroutine.cpp +++ b/lib/CodeGen/CGCoroutine.cpp @@ -148,25 +148,18 @@ static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) { // // See llvm's docs/Coroutines.rst for more details. // -static RValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro, +namespace { + struct LValueOrRValue { + LValue LV; + RValue RV; + }; +} +static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro, CoroutineSuspendExpr const &S, AwaitKind Kind, AggValueSlot aggSlot, - bool ignoreResult) { + bool ignoreResult, bool forLValue) { auto *E = S.getCommonExpr(); - // FIXME: rsmith 5/22/2017. Does it still make sense for us to have a - // UO_Coawait at all? As I recall, the only purpose it ever had was to - // represent a dependent co_await expression that couldn't yet be resolved to - // a CoawaitExpr. But now we have (and need!) a separate DependentCoawaitExpr - // node to store unqualified lookup results, it seems that the UnaryOperator - // portion of the representation serves no purpose (and as seen in this patch, - // it's getting in the way). Can we remove it? - - // Skip passthrough operator co_await (present when awaiting on an LValue). - if (auto *UO = dyn_cast(E)) - if (UO->getOpcode() == UO_Coawait) - E = UO->getSubExpr(); - auto Binder = CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E); auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); }); @@ -217,7 +210,12 @@ static RValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro, // Emit await_resume expression. CGF.EmitBlock(ReadyBlock); - return CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult); + LValueOrRValue Res; + if (forLValue) + Res.LV = CGF.EmitLValue(S.getResumeExpr()); + else + Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult); + return Res; } RValue CodeGenFunction::EmitCoawaitExpr(const CoawaitExpr &E, @@ -225,13 +223,13 @@ RValue CodeGenFunction::EmitCoawaitExpr(const CoawaitExpr &E, bool ignoreResult) { return emitSuspendExpression(*this, *CurCoro.Data, E, CurCoro.Data->CurrentAwaitKind, aggSlot, - ignoreResult); + ignoreResult, /*forLValue*/false).RV; } RValue CodeGenFunction::EmitCoyieldExpr(const CoyieldExpr &E, AggValueSlot aggSlot, bool ignoreResult) { return emitSuspendExpression(*this, *CurCoro.Data, E, AwaitKind::Yield, - aggSlot, ignoreResult); + aggSlot, ignoreResult, /*forLValue*/false).RV; } void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) { @@ -240,6 +238,38 @@ void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) { EmitBranchThroughCleanup(CurCoro.Data->FinalJD); } + +#ifndef NDEBUG +static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx, + const CoroutineSuspendExpr *E) { + const auto *RE = E->getResumeExpr(); + // Is it possible for RE to be a CXXBindTemporaryExpr wrapping + // a MemberCallExpr? + assert(isa(RE) && "unexpected suspend expression type"); + return cast(RE)->getCallReturnType(Ctx); +} +#endif + +LValue +CodeGenFunction::EmitCoawaitLValue(const CoawaitExpr *E) { + assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && + "Can't have a scalar return unless the return type is a " + "reference type!"); + return emitSuspendExpression(*this, *CurCoro.Data, *E, + CurCoro.Data->CurrentAwaitKind, AggValueSlot::ignored(), + /*ignoreResult*/false, /*forLValue*/true).LV; +} + +LValue +CodeGenFunction::EmitCoyieldLValue(const CoyieldExpr *E) { + assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && + "Can't have a scalar return unless the return type is a " + "reference type!"); + return emitSuspendExpression(*this, *CurCoro.Data, *E, + AwaitKind::Yield, AggValueSlot::ignored(), + /*ignoreResult*/false, /*forLValue*/true).LV; +} + // Hunts for the parameter reference in the parameter copy/move declaration. namespace { struct GetParamRef : public StmtVisitor { diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index ebb264eb61c9..b00d296fe34a 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1041,7 +1041,13 @@ llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl, assert(SizeInBits > 0 && "found named 0-width bitfield"); uint64_t StorageOffsetInBits = CGM.getContext().toBits(BitFieldInfo.StorageOffset); - uint64_t OffsetInBits = StorageOffsetInBits + BitFieldInfo.Offset; + uint64_t Offset = BitFieldInfo.Offset; + // The bit offsets for big endian machines are reversed for big + // endian target, compensate for that as the DIDerivedType requires + // un-reversed offsets. + if (CGM.getDataLayout().isBigEndian()) + Offset = BitFieldInfo.StorageSize - BitFieldInfo.Size - Offset; + uint64_t OffsetInBits = StorageOffsetInBits + Offset; llvm::DINode::DIFlags Flags = getAccessFlag(BitFieldDecl->getAccess(), RD); return DBuilder.createBitFieldMemberType( RecordTy, Name, File, Line, SizeInBits, OffsetInBits, StorageOffsetInBits, @@ -3484,13 +3490,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, if (VD->hasAttr()) { // Here, we need an offset *into* the alloca. CharUnits offset = CharUnits::fromQuantity(32); - Expr.push_back(llvm::dwarf::DW_OP_plus); + Expr.push_back(llvm::dwarf::DW_OP_plus_uconst); // offset of __forwarding field offset = CGM.getContext().toCharUnitsFromBits( CGM.getTarget().getPointerWidth(0)); Expr.push_back(offset.getQuantity()); Expr.push_back(llvm::dwarf::DW_OP_deref); - Expr.push_back(llvm::dwarf::DW_OP_plus); + Expr.push_back(llvm::dwarf::DW_OP_plus_uconst); // offset of x field offset = CGM.getContext().toCharUnitsFromBits(XOffset); Expr.push_back(offset.getQuantity()); @@ -3599,17 +3605,17 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( SmallVector addr; addr.push_back(llvm::dwarf::DW_OP_deref); - addr.push_back(llvm::dwarf::DW_OP_plus); + addr.push_back(llvm::dwarf::DW_OP_plus_uconst); addr.push_back(offset.getQuantity()); if (isByRef) { addr.push_back(llvm::dwarf::DW_OP_deref); - addr.push_back(llvm::dwarf::DW_OP_plus); + addr.push_back(llvm::dwarf::DW_OP_plus_uconst); // offset of __forwarding field offset = CGM.getContext().toCharUnitsFromBits(target.getPointerSizeInBits(0)); addr.push_back(offset.getQuantity()); addr.push_back(llvm::dwarf::DW_OP_deref); - addr.push_back(llvm::dwarf::DW_OP_plus); + addr.push_back(llvm::dwarf::DW_OP_plus_uconst); // offset of x field offset = CGM.getContext().toCharUnitsFromBits(XOffset); addr.push_back(offset.getQuantity()); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 9f800a75b5bc..7359006677f4 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -549,6 +549,11 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, if (Ptr->getType()->getPointerAddressSpace()) return; + // Don't check pointers to volatile data. The behavior here is implementation- + // defined. + if (Ty.isVolatileQualified()) + return; + SanitizerScope SanScope(this); SmallVector, 3> Checks; @@ -1158,6 +1163,11 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::MaterializeTemporaryExprClass: return EmitMaterializeTemporaryExpr(cast(E)); + + case Expr::CoawaitExprClass: + return EmitCoawaitLValue(cast(E)); + case Expr::CoyieldExprClass: + return EmitCoyieldLValue(cast(E)); } } @@ -3002,10 +3012,11 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF, llvm::Value *ptr, ArrayRef indices, bool inbounds, + bool signedIndices, SourceLocation loc, const llvm::Twine &name = "arrayidx") { if (inbounds) { - return CGF.EmitCheckedInBoundsGEP(ptr, indices, loc, name); + return CGF.EmitCheckedInBoundsGEP(ptr, indices, signedIndices, loc, name); } else { return CGF.Builder.CreateGEP(ptr, indices, name); } @@ -3038,7 +3049,7 @@ static QualType getFixedSizeElementType(const ASTContext &ctx, static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, ArrayRef indices, QualType eltType, bool inbounds, - SourceLocation loc, + bool signedIndices, SourceLocation loc, const llvm::Twine &name = "arrayidx") { // All the indices except that last must be zero. #ifndef NDEBUG @@ -3058,8 +3069,8 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, CharUnits eltAlign = getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); - llvm::Value *eltPtr = - emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, loc, name); + llvm::Value *eltPtr = emitArraySubscriptGEP( + CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name); return Address(eltPtr, eltAlign); } @@ -3069,6 +3080,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // in lexical order (this complexity is, sadly, required by C++17). llvm::Value *IdxPre = (E->getLHS() == E->getIdx()) ? EmitScalarExpr(E->getIdx()) : nullptr; + bool SignedIndices = false; auto EmitIdxAfterBase = [&, IdxPre](bool Promote) -> llvm::Value * { auto *Idx = IdxPre; if (E->getLHS() != E->getIdx()) { @@ -3078,6 +3090,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, QualType IdxTy = E->getIdx()->getType(); bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType(); + SignedIndices |= IdxSigned; if (SanOpts.has(SanitizerKind::ArrayBounds)) EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, Accessed); @@ -3113,7 +3126,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, QualType EltType = LV.getType()->castAs()->getElementType(); Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true, - E->getExprLoc()); + SignedIndices, E->getExprLoc()); return MakeAddrLValue(Addr, EltType, LV.getBaseInfo()); } @@ -3142,7 +3155,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(), !getLangOpts().isSignedOverflowDefined(), - E->getExprLoc()); + SignedIndices, E->getExprLoc()); } else if (const ObjCObjectType *OIT = E->getType()->getAs()){ // Indexing over an interface, as in "NSString *P; P[4];" @@ -3167,8 +3180,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // Do the GEP. CharUnits EltAlign = getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); - llvm::Value *EltPtr = emitArraySubscriptGEP( - *this, Addr.getPointer(), ScaledIdx, false, E->getExprLoc()); + llvm::Value *EltPtr = + emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false, + SignedIndices, E->getExprLoc()); Addr = Address(EltPtr, EltAlign); // Cast back. @@ -3190,11 +3204,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, auto *Idx = EmitIdxAfterBase(/*Promote*/true); // Propagate the alignment from the array itself to the result. - Addr = emitArraySubscriptGEP(*this, ArrayLV.getAddress(), - {CGM.getSize(CharUnits::Zero()), Idx}, - E->getType(), - !getLangOpts().isSignedOverflowDefined(), - E->getExprLoc()); + Addr = emitArraySubscriptGEP( + *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, + E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, + E->getExprLoc()); BaseInfo = ArrayLV.getBaseInfo(); } else { // The base must be a pointer; emit it with an estimate of its alignment. @@ -3202,7 +3215,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, auto *Idx = EmitIdxAfterBase(/*Promote*/true); Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), !getLangOpts().isSignedOverflowDefined(), - E->getExprLoc()); + SignedIndices, E->getExprLoc()); } LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo); @@ -3375,7 +3388,7 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, Idx = Builder.CreateNSWMul(Idx, NumElements); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(), !getLangOpts().isSignedOverflowDefined(), - E->getExprLoc()); + /*SignedIndices=*/false, E->getExprLoc()); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the // base to be a ArrayToPointerDecay implicit cast. While correct, it is @@ -3395,14 +3408,14 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, EltPtr = emitArraySubscriptGEP( *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), - E->getExprLoc()); + /*SignedIndices=*/false, E->getExprLoc()); BaseInfo = ArrayLV.getBaseInfo(); } else { Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, BaseTy, ResultExprTy, IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), - E->getExprLoc()); + /*SignedIndices=*/false, E->getExprLoc()); } return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index f9d1fe468748..43c86495f3d3 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1851,6 +1851,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *input; int amount = (isInc ? 1 : -1); + bool signedIndex = !isInc; if (const AtomicType *atomicTy = type->getAs()) { type = atomicTy->getValueType(); @@ -1940,8 +1941,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, numElts, "vla.inc"); else - value = CGF.EmitCheckedInBoundsGEP(value, numElts, E->getExprLoc(), - "vla.inc"); + value = CGF.EmitCheckedInBoundsGEP(value, numElts, signedIndex, + E->getExprLoc(), "vla.inc"); // Arithmetic on function pointers (!) is just +-1. } else if (type->isFunctionType()) { @@ -1951,8 +1952,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, amt, "incdec.funcptr"); else - value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(), - "incdec.funcptr"); + value = CGF.EmitCheckedInBoundsGEP(value, amt, signedIndex, + E->getExprLoc(), "incdec.funcptr"); value = Builder.CreateBitCast(value, input->getType()); // For everything else, we can just do a simple increment. @@ -1961,8 +1962,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, amt, "incdec.ptr"); else - value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(), - "incdec.ptr"); + value = CGF.EmitCheckedInBoundsGEP(value, amt, signedIndex, + E->getExprLoc(), "incdec.ptr"); } // Vector increment/decrement. @@ -2043,8 +2044,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, sizeValue, "incdec.objptr"); else - value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, E->getExprLoc(), - "incdec.objptr"); + value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, signedIndex, + E->getExprLoc(), "incdec.objptr"); value = Builder.CreateBitCast(value, input->getType()); } @@ -2661,13 +2662,15 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, std::swap(pointerOperand, indexOperand); } + bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType(); + bool mayHaveNegativeGEPIndex = isSigned || isSubtraction; + unsigned width = cast(index->getType())->getBitWidth(); auto &DL = CGF.CGM.getDataLayout(); auto PtrTy = cast(pointer->getType()); if (width != DL.getTypeSizeInBits(PtrTy)) { // Zero-extend or sign-extend the pointer value according to // whether the index is signed or not. - bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType(); index = CGF.Builder.CreateIntCast(index, DL.getIntPtrType(PtrTy), isSigned, "idx.ext"); } @@ -2711,8 +2714,9 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr"); } else { index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index"); - pointer = CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(), - "add.ptr"); + pointer = + CGF.EmitCheckedInBoundsGEP(pointer, index, mayHaveNegativeGEPIndex, + op.E->getExprLoc(), "add.ptr"); } return pointer; } @@ -2729,8 +2733,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, if (CGF.getLangOpts().isSignedOverflowDefined()) return CGF.Builder.CreateGEP(pointer, index, "add.ptr"); - return CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(), - "add.ptr"); + return CGF.EmitCheckedInBoundsGEP(pointer, index, mayHaveNegativeGEPIndex, + op.E->getExprLoc(), "add.ptr"); } // Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and @@ -3848,6 +3852,7 @@ LValue CodeGenFunction::EmitCompoundAssignmentLValue( Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, ArrayRef IdxList, + bool SignedIndices, SourceLocation Loc, const Twine &Name) { Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name); @@ -3905,7 +3910,7 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, auto *ResultAndOverflow = Builder.CreateCall( (Opcode == BO_Add) ? SAddIntrinsic : SMulIntrinsic, {LHS, RHS}); OffsetOverflows = Builder.CreateOr( - OffsetOverflows, Builder.CreateExtractValue(ResultAndOverflow, 1)); + Builder.CreateExtractValue(ResultAndOverflow, 1), OffsetOverflows); return Builder.CreateExtractValue(ResultAndOverflow, 0); }; @@ -3951,12 +3956,18 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, // 1) The total offset doesn't overflow, and // 2) The sign of the difference between the computed address and the base // pointer matches the sign of the total offset. - llvm::Value *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr); - llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr); - auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero); - llvm::Value *ValidGEP = Builder.CreateAnd( - Builder.CreateNot(OffsetOverflows), - Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid)); + llvm::Value *ValidGEP; + auto *NoOffsetOverflow = Builder.CreateNot(OffsetOverflows); + auto *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr); + if (SignedIndices) { + auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero); + llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr); + ValidGEP = Builder.CreateAnd( + Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid), + NoOffsetOverflow); + } else { + ValidGEP = Builder.CreateAnd(PosOrZeroValid, NoOffsetOverflow); + } llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc)}; // Pass the computed GEP to the runtime to avoid emitting poisoned arguments. diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 468838e56e38..8d83255ac139 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -6327,7 +6327,7 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { } } - // If we are in target mode we do not emit any global (declare target is not + // If we are in target mode, we do not emit any global (declare target is not // implemented yet). Therefore we signal that GD was processed in this case. return true; } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 42ffd0d3efcc..831eedf9e478 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2550,9 +2550,11 @@ class CodeGenFunction : public CodeGenTypeCache { RValue EmitCoawaitExpr(const CoawaitExpr &E, AggValueSlot aggSlot = AggValueSlot::ignored(), bool ignoreResult = false); + LValue EmitCoawaitLValue(const CoawaitExpr *E); RValue EmitCoyieldExpr(const CoyieldExpr &E, AggValueSlot aggSlot = AggValueSlot::ignored(), bool ignoreResult = false); + LValue EmitCoyieldLValue(const CoyieldExpr *E); RValue EmitCoroutineIntrinsic(const CallExpr *E, unsigned int IID); void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false); @@ -3554,8 +3556,10 @@ class CodeGenFunction : public CodeGenTypeCache { /// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to /// detect undefined behavior when the pointer overflow sanitizer is enabled. + /// \p SignedIndices indicates whether any of the GEP indices are signed. llvm::Value *EmitCheckedInBoundsGEP(llvm::Value *Ptr, ArrayRef IdxList, + bool SignedIndices, SourceLocation Loc, const Twine &Name = ""); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 77adf7b441a2..19a055075604 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1243,7 +1243,7 @@ void CodeGenModule::AddDependentLib(StringRef Lib) { /// \brief Add link options implied by the given module, including modules /// it depends on, using a postorder walk. static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod, - SmallVectorImpl &Metadata, + SmallVectorImpl &Metadata, llvm::SmallPtrSet &Visited) { // Import this module's parent. if (Mod->Parent && Visited.insert(Mod->Parent).second) { @@ -1331,7 +1331,7 @@ void CodeGenModule::EmitModuleLinkOptions() { // Add link options for all of the imported modules in reverse topological // order. We don't do anything to try to order import link flags with respect // to linker options inserted by things like #pragma comment(). - SmallVector MetadataArgs; + SmallVector MetadataArgs; Visited.clear(); for (Module *M : LinkModules) if (Visited.insert(M).second) @@ -1340,9 +1340,9 @@ void CodeGenModule::EmitModuleLinkOptions() { LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end()); // Add the linker options metadata flag. - getModule().addModuleFlag(llvm::Module::AppendUnique, "Linker Options", - llvm::MDNode::get(getLLVMContext(), - LinkerOptionsMetadata)); + auto *NMD = getModule().getOrInsertNamedMetadata("llvm.linker.options"); + for (auto *MD : LinkerOptionsMetadata) + NMD->addOperand(MD); } void CodeGenModule::EmitDeferred() { diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 0a71c635e8f0..59e56a6ba194 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -429,7 +429,7 @@ class CodeGenModule : public CodeGenTypeCache { llvm::SmallPtrSet EmittedModuleInitializers; /// \brief A vector of metadata strings. - SmallVector LinkerOptionsMetadata; + SmallVector LinkerOptionsMetadata; /// @name Cache for Objective-C runtime types /// @{ @@ -1058,13 +1058,14 @@ class CodeGenModule : public CodeGenTypeCache { void RefreshTypeCacheForClass(const CXXRecordDecl *Class); - /// \brief Appends Opts to the "Linker Options" metadata value. + /// \brief Appends Opts to the "llvm.linker.options" metadata value. void AppendLinkerOptions(StringRef Opts); /// \brief Appends a detect mismatch command to the linker options. void AddDetectMismatch(StringRef Name, StringRef Value); - /// \brief Appends a dependent lib to the "Linker Options" metadata value. + /// \brief Appends a dependent lib to the "llvm.linker.options" metadata + /// value. void AddDependentLib(StringRef Lib); llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD); diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 6d3dbb5b5204..bd4e894d6504 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -980,6 +980,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, DepTarget = Args.MakeArgString(llvm::sys::path::filename(P)); } + if (!A->getOption().matches(options::OPT_MD) && !A->getOption().matches(options::OPT_MMD)) { + CmdArgs.push_back("-w"); + } CmdArgs.push_back("-MT"); SmallString<128> Quoted; QuoteTarget(DepTarget, Quoted); diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 2ef6516e02ee..39da87cf9988 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -310,6 +310,8 @@ template <> struct MappingTraits { IO.mapOptional("BreakBeforeBinaryOperators", Style.BreakBeforeBinaryOperators); IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); + IO.mapOptional("BreakBeforeInheritanceComma", + Style.BreakBeforeInheritanceComma); IO.mapOptional("BreakBeforeTernaryOperators", Style.BreakBeforeTernaryOperators); @@ -330,8 +332,7 @@ template <> struct MappingTraits { IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); IO.mapOptional("ColumnLimit", Style.ColumnLimit); IO.mapOptional("CommentPragmas", Style.CommentPragmas); - IO.mapOptional("BreakBeforeInheritanceComma", - Style.BreakBeforeInheritanceComma); + IO.mapOptional("CompactNamespaces", Style.CompactNamespaces); IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", Style.ConstructorInitializerAllOnOneLineOrOnePerLine); IO.mapOptional("ConstructorInitializerIndentWidth", @@ -410,6 +411,7 @@ template <> struct MappingTraits { IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); IO.mapOptional("BeforeElse", Wrapping.BeforeElse); IO.mapOptional("IndentBraces", Wrapping.IndentBraces); + IO.mapOptional("SplitEmptyFunctionBody", Wrapping.SplitEmptyFunctionBody); } }; @@ -485,7 +487,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { return Style; FormatStyle Expanded = Style; Expanded.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false}; + false, false, false, false, false, true}; switch (Style.BreakBeforeBraces) { case FormatStyle::BS_Linux: Expanded.BraceWrapping.AfterClass = true; @@ -498,6 +500,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { Expanded.BraceWrapping.AfterFunction = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; + Expanded.BraceWrapping.SplitEmptyFunctionBody = false; break; case FormatStyle::BS_Stroustrup: Expanded.BraceWrapping.AfterFunction = true; @@ -517,7 +520,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { break; case FormatStyle::BS_GNU: Expanded.BraceWrapping = {true, true, true, true, true, true, - true, true, true, true, true}; + true, true, true, true, true, true}; break; case FormatStyle::BS_WebKit: Expanded.BraceWrapping.AfterFunction = true; @@ -548,19 +551,20 @@ FormatStyle getLLVMStyle() { LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; LLVMStyle.AlwaysBreakTemplateDeclarations = false; - LLVMStyle.BinPackParameters = true; LLVMStyle.BinPackArguments = true; + LLVMStyle.BinPackParameters = true; LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; LLVMStyle.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false}; + false, false, false, false, false, true}; LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; LLVMStyle.BreakBeforeInheritanceComma = false; LLVMStyle.BreakStringLiterals = true; LLVMStyle.ColumnLimit = 80; LLVMStyle.CommentPragmas = "^ IWYU pragma:"; + LLVMStyle.CompactNamespaces = false; LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; LLVMStyle.ConstructorInitializerIndentWidth = 4; LLVMStyle.ContinuationIndentWidth = 4; diff --git a/lib/Format/NamespaceEndCommentsFixer.cpp b/lib/Format/NamespaceEndCommentsFixer.cpp index 88cf123c1899..1bbb41f757ae 100644 --- a/lib/Format/NamespaceEndCommentsFixer.cpp +++ b/lib/Format/NamespaceEndCommentsFixer.cpp @@ -107,6 +107,24 @@ void updateEndComment(const FormatToken *RBraceTok, StringRef EndCommentText, << llvm::toString(std::move(Err)) << "\n"; } } + +const FormatToken * +getNamespaceToken(const AnnotatedLine *line, + const SmallVectorImpl &AnnotatedLines) { + if (!line->Affected || line->InPPDirective || !line->startsWith(tok::r_brace)) + return nullptr; + size_t StartLineIndex = line->MatchingOpeningBlockLineIndex; + if (StartLineIndex == UnwrappedLine::kInvalidIndex) + return nullptr; + assert(StartLineIndex < AnnotatedLines.size()); + const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First; + // Detect "(inline)? namespace" in the beginning of a line. + if (NamespaceTok->is(tok::kw_inline)) + NamespaceTok = NamespaceTok->getNextNonComment(); + if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace)) + return nullptr; + return NamespaceTok; +} } // namespace NamespaceEndCommentsFixer::NamespaceEndCommentsFixer(const Environment &Env, @@ -120,20 +138,14 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze( AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(), AnnotatedLines.end()); tooling::Replacements Fixes; + std::string AllNamespaceNames = ""; + size_t StartLineIndex = SIZE_MAX; + unsigned int CompactedNamespacesCount = 0; for (size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) { - if (!AnnotatedLines[I]->Affected || AnnotatedLines[I]->InPPDirective || - !AnnotatedLines[I]->startsWith(tok::r_brace)) - continue; const AnnotatedLine *EndLine = AnnotatedLines[I]; - size_t StartLineIndex = EndLine->MatchingOpeningBlockLineIndex; - if (StartLineIndex == UnwrappedLine::kInvalidIndex) - continue; - assert(StartLineIndex < E); - const FormatToken *NamespaceTok = AnnotatedLines[StartLineIndex]->First; - // Detect "(inline)? namespace" in the beginning of a line. - if (NamespaceTok->is(tok::kw_inline)) - NamespaceTok = NamespaceTok->getNextNonComment(); - if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace)) + const FormatToken *NamespaceTok = + getNamespaceToken(EndLine, AnnotatedLines); + if (!NamespaceTok) continue; FormatToken *RBraceTok = EndLine->First; if (RBraceTok->Finalized) @@ -145,6 +157,27 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze( if (RBraceTok->Next && RBraceTok->Next->is(tok::semi)) { EndCommentPrevTok = RBraceTok->Next; } + if (StartLineIndex == SIZE_MAX) + StartLineIndex = EndLine->MatchingOpeningBlockLineIndex; + std::string NamespaceName = computeName(NamespaceTok); + if (Style.CompactNamespaces) { + if ((I + 1 < E) && + getNamespaceToken(AnnotatedLines[I + 1], AnnotatedLines) && + StartLineIndex - CompactedNamespacesCount - 1 == + AnnotatedLines[I + 1]->MatchingOpeningBlockLineIndex && + !AnnotatedLines[I + 1]->First->Finalized) { + if (hasEndComment(EndCommentPrevTok)) { + // remove end comment, it will be merged in next one + updateEndComment(EndCommentPrevTok, std::string(), SourceMgr, &Fixes); + } + CompactedNamespacesCount++; + AllNamespaceNames = "::" + NamespaceName + AllNamespaceNames; + continue; + } + NamespaceName += std::move(AllNamespaceNames); + CompactedNamespacesCount = 0; + AllNamespaceNames = std::string(); + } // The next token in the token stream after the place where the end comment // token must be. This is either the next token on the current line or the // first token on the next line. @@ -156,17 +189,16 @@ tooling::Replacements NamespaceEndCommentsFixer::analyze( bool AddNewline = EndCommentNextTok && EndCommentNextTok->NewlinesBefore == 0 && EndCommentNextTok->isNot(tok::eof); - const std::string NamespaceName = computeName(NamespaceTok); const std::string EndCommentText = computeEndCommentText(NamespaceName, AddNewline); if (!hasEndComment(EndCommentPrevTok)) { bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1; if (!isShort) addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes); - continue; - } - if (!validEndComment(EndCommentPrevTok, NamespaceName)) + } else if (!validEndComment(EndCommentPrevTok, NamespaceName)) { updateEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes); + } + StartLineIndex = SIZE_MAX; } return Fixes; } diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp index 01504da0a29b..7f644651a6ab 100644 --- a/lib/Format/UnwrappedLineFormatter.cpp +++ b/lib/Format/UnwrappedLineFormatter.cpp @@ -66,6 +66,13 @@ class LevelIndentTracker { Indent += Offset; } + /// \brief Update the indent state given that \p Line indent should be + /// skipped. + void skipLine(const AnnotatedLine &Line) { + while (IndentForLevel.size() <= Line.Level) + IndentForLevel.push_back(Indent); + } + /// \brief Update the level indent to adapt to the given \p Line. /// /// When a line is not formatted, we move the subsequent lines on the same @@ -127,12 +134,31 @@ class LevelIndentTracker { unsigned Indent = 0; }; +bool isNamespaceDeclaration(const AnnotatedLine *Line) { + const FormatToken *NamespaceTok = Line->First; + // Detect "(inline)? namespace" in the beginning of a line. + if (NamespaceTok->is(tok::kw_inline)) + NamespaceTok = NamespaceTok->getNextNonComment(); + return NamespaceTok && NamespaceTok->is(tok::kw_namespace); +} + +bool isEndOfNamespace(const AnnotatedLine *Line, + const SmallVectorImpl &AnnotatedLines) { + if (!Line->startsWith(tok::r_brace)) + return false; + size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex; + if (StartLineIndex == UnwrappedLine::kInvalidIndex) + return false; + assert(StartLineIndex < AnnotatedLines.size()); + return isNamespaceDeclaration(AnnotatedLines[StartLineIndex]); +} + class LineJoiner { public: LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords, const SmallVectorImpl &Lines) - : Style(Style), Keywords(Keywords), End(Lines.end()), - Next(Lines.begin()) {} + : Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()), + AnnotatedLines(Lines) {} /// \brief Returns the next line, merging multiple lines into one if possible. const AnnotatedLine *getNextMergedLine(bool DryRun, @@ -142,7 +168,7 @@ class LineJoiner { const AnnotatedLine *Current = *Next; IndentTracker.nextLine(*Current); unsigned MergedLines = - tryFitMultipleLinesInOne(IndentTracker.getIndent(), Next, End); + tryFitMultipleLinesInOne(IndentTracker, Next, End); if (MergedLines > 0 && Style.ColumnLimit == 0) // Disallow line merging if there is a break at the start of one of the // input lines. @@ -159,9 +185,11 @@ class LineJoiner { private: /// \brief Calculates how many lines can be merged into 1 starting at \p I. unsigned - tryFitMultipleLinesInOne(unsigned Indent, + tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker, SmallVectorImpl::const_iterator I, SmallVectorImpl::const_iterator E) { + const unsigned Indent = IndentTracker.getIndent(); + // Can't join the last line with anything. if (I + 1 == E) return 0; @@ -186,6 +214,12 @@ class LineJoiner { ? 0 : Limit - TheLine->Last->TotalLength; + if (TheLine->Last->is(TT_FunctionLBrace) && + TheLine->First == TheLine->Last && + !Style.BraceWrapping.SplitEmptyFunctionBody && + I[1]->First->is(tok::r_brace)) + return tryMergeSimpleBlock(I, E, Limit); + // FIXME: TheLine->Level != 0 might or might not be the right check to do. // If necessary, change to something smarter. bool MergeShortFunctions = @@ -195,6 +229,38 @@ class LineJoiner { (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline && TheLine->Level != 0); + if (Style.CompactNamespaces) { + if (isNamespaceDeclaration(TheLine)) { + int i = 0; + unsigned closingLine = TheLine->MatchingOpeningBlockLineIndex - 1; + for (; I + 1 + i != E && isNamespaceDeclaration(I[i + 1]) && + closingLine == I[i + 1]->MatchingOpeningBlockLineIndex && + I[i + 1]->Last->TotalLength < Limit; + i++, closingLine--) { + // No extra indent for compacted namespaces + IndentTracker.skipLine(*I[i + 1]); + + Limit -= I[i + 1]->Last->TotalLength; + } + return i; + } + + if (isEndOfNamespace(TheLine, AnnotatedLines)) { + int i = 0; + unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1; + for (; I + 1 + i != E && isEndOfNamespace(I[i + 1], AnnotatedLines) && + openingLine == I[i + 1]->MatchingOpeningBlockLineIndex; + i++, openingLine--) { + // No space between consecutive braces + I[i + 1]->First->SpacesRequiredBefore = !I[i]->Last->is(tok::r_brace); + + // Indent like the outer-most namespace + IndentTracker.nextLine(*I[i + 1]); + } + return i; + } + } + if (TheLine->Last->is(TT_FunctionLBrace) && TheLine->First != TheLine->Last) { return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0; @@ -215,7 +281,10 @@ class LineJoiner { Limit -= 2; unsigned MergedLines = 0; - if (MergeShortFunctions) { + if (MergeShortFunctions || + (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && + I[1]->First == I[1]->Last && I + 2 != E && + I[2]->First->is(tok::r_brace))) { MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); // If we managed to merge the block, count the function header, which is // on a separate line. @@ -449,6 +518,7 @@ class LineJoiner { const SmallVectorImpl::const_iterator End; SmallVectorImpl::const_iterator Next; + const SmallVectorImpl &AnnotatedLines; }; static void markFinalized(FormatToken *Tok) { diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index eda7ef36434d..27436dda67a7 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -492,6 +492,11 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel, nextToken(); Line->Level = InitialLevel; Line->MatchingOpeningBlockLineIndex = OpeningLineIndex; + if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) { + // Update the opening line to add the forward reference as well + (*CurrentLines)[OpeningLineIndex].MatchingOpeningBlockLineIndex = + CurrentLines->size() - 1; + } } static bool isGoogScope(const UnwrappedLine &Line) { diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h index 6be4af262276..50df59d09641 100644 --- a/lib/Format/WhitespaceManager.h +++ b/lib/Format/WhitespaceManager.h @@ -43,6 +43,10 @@ class WhitespaceManager { /// \brief Replaces the whitespace in front of \p Tok. Only call once for /// each \c AnnotatedToken. + /// + /// \p StartOfTokenColumn is the column at which the token will start after + /// this replacement. It is needed for determining how \p Spaces is turned + /// into tabs and spaces for some format styles. void replaceWhitespace(FormatToken &Tok, unsigned Newlines, unsigned Spaces, unsigned StartOfTokenColumn, bool InPPDirective = false); diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 720baa5e0f7a..7dc475e26f76 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -142,7 +142,7 @@ std::unique_ptr clang::CreateASTDumper(StringRef FilterString, bool DumpDecls, bool Deserialize, bool DumpLookups) { - assert((DumpDecls || DumpLookups) && "nothing to dump"); + assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); return llvm::make_unique(nullptr, Deserialize ? ASTPrinter::DumpFull : DumpDecls ? ASTPrinter::Dump : diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index bb635b7ad714..1667af2d12bb 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -649,8 +649,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables); Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); - const Arg *A = Args.getLastArg(OPT_flto, OPT_flto_EQ); - Opts.EmitSummaryIndex = A && A->containsValue("thin"); + Opts.EmitSummaryIndex = false; + if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { + StringRef S = A->getValue(); + if (S == "thin") + Opts.EmitSummaryIndex = true; + else if (S != "full") + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S; + } Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false); if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) { if (IK.getLanguage() != InputKind::LLVM_IR) diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index 870b4e4fe825..2162c039c48b 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -293,6 +293,12 @@ class IndexingDeclVisitor : public ConstDeclVisitor { return true; } + bool VisitDecompositionDecl(const DecompositionDecl *D) { + for (const auto *Binding : D->bindings()) + TRY_DECL(Binding, IndexCtx.handleDecl(Binding)); + return Base::VisitDecompositionDecl(D); + } + bool VisitFieldDecl(const FieldDecl *D) { SmallVector Relations; gatherTemplatePseudoOverrides(D, Relations); @@ -682,6 +688,13 @@ class IndexingDeclVisitor : public ConstDeclVisitor { bool VisitImportDecl(const ImportDecl *D) { return IndexCtx.importedModule(D); } + + bool VisitStaticAssertDecl(const StaticAssertDecl *D) { + IndexCtx.indexBody(D->getAssertExpr(), + dyn_cast(D->getDeclContext()), + D->getLexicalDeclContext()); + return true; + } }; } // anonymous namespace diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp index 0b20970acc3b..bf358a372149 100644 --- a/lib/Index/IndexSymbol.cpp +++ b/lib/Index/IndexSymbol.cpp @@ -301,6 +301,10 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { Info.Kind = SymbolKind::TypeAlias; Info.Lang = SymbolLanguage::CXX; break; + case Decl::Binding: + Info.Kind = SymbolKind::Variable; + Info.Lang = SymbolLanguage::CXX; + break; default: break; } diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp index 1c1979d8e83d..a201d1659073 100644 --- a/lib/Lex/MacroArgs.cpp +++ b/lib/Lex/MacroArgs.cpp @@ -44,20 +44,22 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI, // Otherwise, use the best fit. ClosestMatch = (*Entry)->NumUnexpArgTokens; } - + MacroArgs *Result; if (!ResultEnt) { // Allocate memory for a MacroArgs object with the lexer tokens at the end. - Result = (MacroArgs*)malloc(sizeof(MacroArgs) + - UnexpArgTokens.size() * sizeof(Token)); + Result = (MacroArgs *)malloc(sizeof(MacroArgs) + + UnexpArgTokens.size() * sizeof(Token)); // Construct the MacroArgs object. - new (Result) MacroArgs(UnexpArgTokens.size(), VarargsElided); + new (Result) + MacroArgs(UnexpArgTokens.size(), VarargsElided, MI->getNumArgs()); } else { Result = *ResultEnt; // Unlink this node from the preprocessors singly linked list. *ResultEnt = Result->ArgCache; Result->NumUnexpArgTokens = UnexpArgTokens.size(); Result->VarargsElided = VarargsElided; + Result->NumMacroArgs = MI->getNumArgs(); } // Copy the actual unexpanded tokens to immediately after the result ptr. @@ -298,12 +300,10 @@ const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, Preprocessor &PP, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd) { - assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!"); - if (StringifiedArgs.empty()) { - StringifiedArgs.resize(getNumArguments()); - memset((void*)&StringifiedArgs[0], 0, - sizeof(StringifiedArgs[0])*getNumArguments()); - } + assert(ArgNo < getNumMacroArguments() && "Invalid argument number!"); + if (StringifiedArgs.empty()) + StringifiedArgs.resize(getNumMacroArguments(), {}); + if (StringifiedArgs[ArgNo].isNot(tok::string_literal)) StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP, /*Charify=*/false, diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index b9349dc06bff..83c3bd27596c 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -4542,8 +4542,10 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext) { if (!SS.getScopeRep() || !CodeCompleter) return; - - DeclContext *Ctx = computeDeclContext(SS, EnteringContext); + + // Always pretend to enter a context to ensure that a dependent type + // resolves to a dependent record. + DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true); if (!Ctx) return; @@ -4573,7 +4575,9 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, Results.ExitScope(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer); + LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, + /*IncludeGlobalScope=*/true, + /*IncludeDependentBases=*/true); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index 06ae66076e8a..b05c0998d3dd 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -470,11 +470,11 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc, return ScopeInfo; } -static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc, - StringRef Keyword) { - if (!checkCoroutineContext(S, KWLoc, Keyword)) +bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc, + StringRef Keyword) { + if (!checkCoroutineContext(*this, KWLoc, Keyword)) return false; - auto *ScopeInfo = S.getCurFunction(); + auto *ScopeInfo = getCurFunction(); assert(ScopeInfo->CoroutinePromise); // If we have existing coroutine statements then we have already built @@ -484,24 +484,24 @@ static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc, ScopeInfo->setNeedsCoroutineSuspends(false); - auto *Fn = cast(S.CurContext); + auto *Fn = cast(CurContext); SourceLocation Loc = Fn->getLocation(); // Build the initial suspend point auto buildSuspends = [&](StringRef Name) mutable -> StmtResult { ExprResult Suspend = - buildPromiseCall(S, ScopeInfo->CoroutinePromise, Loc, Name, None); + buildPromiseCall(*this, ScopeInfo->CoroutinePromise, Loc, Name, None); if (Suspend.isInvalid()) return StmtError(); - Suspend = buildOperatorCoawaitCall(S, SC, Loc, Suspend.get()); + Suspend = buildOperatorCoawaitCall(*this, SC, Loc, Suspend.get()); if (Suspend.isInvalid()) return StmtError(); - Suspend = S.BuildResolvedCoawaitExpr(Loc, Suspend.get(), - /*IsImplicit*/ true); - Suspend = S.ActOnFinishFullExpr(Suspend.get()); + Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(), + /*IsImplicit*/ true); + Suspend = ActOnFinishFullExpr(Suspend.get()); if (Suspend.isInvalid()) { - S.Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) + Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) << ((Name == "initial_suspend") ? 0 : 1); - S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword; + Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword; return StmtError(); } return cast(Suspend.get()); @@ -521,7 +521,7 @@ static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc, } ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) { - if (!actOnCoroutineBodyStart(*this, S, Loc, "co_await")) { + if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) { CorrectDelayedTyposInExpr(E); return ExprError(); } @@ -613,7 +613,7 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E, } ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) { - if (!actOnCoroutineBodyStart(*this, S, Loc, "co_yield")) { + if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) { CorrectDelayedTyposInExpr(E); return ExprError(); } @@ -658,14 +658,15 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { if (RSS.IsInvalid) return ExprError(); - Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1], - RSS.Results[2], RSS.OpaqueValue); + Expr *Res = + new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1], + RSS.Results[2], RSS.OpaqueValue); return Res; } StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) { - if (!actOnCoroutineBodyStart(*this, S, Loc, "co_return")) { + if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) { CorrectDelayedTyposInExpr(E); return StmtError(); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 6c492fac9eb9..b43642f5493b 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -313,8 +313,8 @@ static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range, /// \returns true if IdxExpr is a valid index. template static bool checkFunctionOrMethodParameterIndex( - Sema &S, const Decl *D, const AttrInfo& Attr, - unsigned AttrArgNum, const Expr *IdxExpr, uint64_t &Idx) { + Sema &S, const Decl *D, const AttrInfo &Attr, unsigned AttrArgNum, + const Expr *IdxExpr, uint64_t &Idx, bool AllowImplicitThis = false) { assert(isFunctionOrMethodOrBlock(D)); // In C++ the implicit 'this' function parameter also counts. @@ -341,7 +341,7 @@ static bool checkFunctionOrMethodParameterIndex( return false; } Idx--; // Convert to zero-based. - if (HasImplicitThisParam) { + if (HasImplicitThisParam && !AllowImplicitThis) { if (Idx == 0) { S.Diag(getAttrLoc(Attr), diag::err_attribute_invalid_implicit_this_argument) @@ -4604,14 +4604,16 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, static void handleXRayLogArgsAttr(Sema &S, Decl *D, const AttributeList &Attr) { uint64_t ArgCount; + if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, Attr.getArgAsExpr(0), - ArgCount)) + ArgCount, + true /* AllowImplicitThis*/)) return; // ArgCount isn't a parameter index [0;n), it's a count [1;n] - hence + 1. D->addAttr(::new (S.Context) - XRayLogArgsAttr(Attr.getRange(), S.Context, ++ArgCount, - Attr.getAttributeSpellingListIndex())); + XRayLogArgsAttr(Attr.getRange(), S.Context, ++ArgCount, + Attr.getAttributeSpellingListIndex())); } //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0f8f5c253ac6..75a6903392ea 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -12057,11 +12057,17 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, } break; case UO_Extension: - case UO_Coawait: resultType = Input.get()->getType(); VK = Input.get()->getValueKind(); OK = Input.get()->getObjectKind(); break; + case UO_Coawait: + // It's unnessesary to represent the pass-through operator co_await in the + // AST; just return the input expression instead. + assert(!Input.get()->getType()->isDependentType() && + "the co_await expression must be non-dependant before " + "building operator co_await"); + return Input; } if (resultType.isNull() || Input.isInvalid()) return ExprError(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 00a4b39f1423..a9ff21bc41ab 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -189,12 +189,15 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, // have one) and, if that fails to find a match, in the scope (if // we're allowed to look there). Found.clear(); - if (Step == 0 && LookupCtx) + if (Step == 0 && LookupCtx) { + if (RequireCompleteDeclContext(SS, LookupCtx)) + return nullptr; LookupQualifiedName(Found, LookupCtx); - else if (Step == 1 && LookInScope && S) + } else if (Step == 1 && LookInScope && S) { LookupName(Found, S); - else + } else { continue; + } // FIXME: Should we be suppressing ambiguities here? if (Found.isAmbiguous()) diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index a6239283b47b..d6b70610d461 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1492,6 +1492,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, bool ExplicitResultType; CleanupInfo LambdaCleanup; bool ContainsUnexpandedParameterPack; + bool IsGenericLambda; { CallOperator = LSI->CallOperator; Class = LSI->Lambda; @@ -1500,7 +1501,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, ExplicitResultType = !LSI->HasImplicitReturnType; LambdaCleanup = LSI->Cleanup; ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; - + IsGenericLambda = Class->isGenericLambda(); + CallOperator->setLexicalDeclContext(Class); Decl *TemplateOrNonTemplateCallOperatorDecl = CallOperator->getDescribedFunctionTemplate() @@ -1520,8 +1522,13 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, bool IsImplicit = I >= LSI->NumExplicitCaptures; // Warn about unused explicit captures. - if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) - DiagnoseUnusedLambdaCapture(From); + if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { + // Initialized captures that are non-ODR used may not be eliminated. + bool NonODRUsedInitCapture = + IsGenericLambda && From.isNonODRUsed() && From.getInitExpr(); + if (!NonODRUsedInitCapture) + DiagnoseUnusedLambdaCapture(From); + } // Handle 'this' capture. if (From.isThisCapture()) { @@ -1568,8 +1575,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // same parameter and return types as the closure type's function call // operator. // FIXME: Fix generic lambda to block conversions. - if (getLangOpts().Blocks && getLangOpts().ObjC1 && - !Class->isGenericLambda()) + if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda) addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 151b89ab8d2a..eed10b077eb8 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1989,11 +1989,11 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, return StmtError(); } - // Coroutines: 'for co_await' implicitly co_awaits its range. - if (CoawaitLoc.isValid()) { - ExprResult Coawait = ActOnCoawaitExpr(S, CoawaitLoc, Range); - if (Coawait.isInvalid()) return StmtError(); - Range = Coawait.get(); + // Build the coroutine state immediately and not later during template + // instantiation + if (!CoawaitLoc.isInvalid()) { + if (!ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await")) + return StmtError(); } // Build auto && __range = range-init @@ -2031,16 +2031,12 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, /// BeginExpr and EndExpr are set and FRS_Success is returned on success; /// CandidateSet and BEF are set and some non-success value is returned on /// failure. -static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, - Expr *BeginRange, Expr *EndRange, - QualType RangeType, - VarDecl *BeginVar, - VarDecl *EndVar, - SourceLocation ColonLoc, - OverloadCandidateSet *CandidateSet, - ExprResult *BeginExpr, - ExprResult *EndExpr, - BeginEndFunction *BEF) { +static Sema::ForRangeStatus +BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, + QualType RangeType, VarDecl *BeginVar, VarDecl *EndVar, + SourceLocation ColonLoc, SourceLocation CoawaitLoc, + OverloadCandidateSet *CandidateSet, ExprResult *BeginExpr, + ExprResult *EndExpr, BeginEndFunction *BEF) { DeclarationNameInfo BeginNameInfo( &SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc); DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"), @@ -2087,6 +2083,15 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, << ColonLoc << BEF_begin << BeginRange->getType(); return RangeStatus; } + if (!CoawaitLoc.isInvalid()) { + // FIXME: getCurScope() should not be used during template instantiation. + // We should pick up the set of unqualified lookup results for operator + // co_await during the initial parse. + *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc, + BeginExpr->get()); + if (BeginExpr->isInvalid()) + return Sema::FRS_DiagnosticIssued; + } if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc, diag::err_for_range_iter_deduction_failure)) { NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF); @@ -2206,8 +2211,12 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, // Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill // them in properly when we instantiate the loop. - if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) + if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) { + if (auto *DD = dyn_cast(LoopVar)) + for (auto *Binding : DD->bindings()) + Binding->setType(Context.DependentTy); LoopVar->setType(SubstAutoType(LoopVar->getType(), Context.DependentTy)); + } } else if (!BeginDeclStmt.get()) { SourceLocation RangeLoc = RangeVar->getLocation(); @@ -2249,6 +2258,11 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, // begin-expr is __range. BeginExpr = BeginRangeRef; + if (!CoawaitLoc.isInvalid()) { + BeginExpr = ActOnCoawaitExpr(S, ColonLoc, BeginExpr.get()); + if (BeginExpr.isInvalid()) + return StmtError(); + } if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc, diag::err_for_range_iter_deduction_failure)) { NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); @@ -2331,11 +2345,10 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, OverloadCandidateSet CandidateSet(RangeLoc, OverloadCandidateSet::CSK_Normal); BeginEndFunction BEFFailure; - ForRangeStatus RangeStatus = - BuildNonArrayForRange(*this, BeginRangeRef.get(), - EndRangeRef.get(), RangeType, - BeginVar, EndVar, ColonLoc, &CandidateSet, - &BeginExpr, &EndExpr, &BEFFailure); + ForRangeStatus RangeStatus = BuildNonArrayForRange( + *this, BeginRangeRef.get(), EndRangeRef.get(), RangeType, BeginVar, + EndVar, ColonLoc, CoawaitLoc, &CandidateSet, &BeginExpr, &EndExpr, + &BEFFailure); if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction && BEFFailure == BEF_begin) { @@ -2432,6 +2445,9 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get()); if (!IncrExpr.isInvalid() && CoawaitLoc.isValid()) + // FIXME: getCurScope() should not be used during template instantiation. + // We should pick up the set of unqualified lookup results for operator + // co_await during the initial parse. IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get()); if (!IncrExpr.isInvalid()) IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 94a8f609f57c..eeb0132c1690 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -9242,6 +9242,7 @@ void ASTReader::diagnoseOdrViolations() { // Used with err_module_odr_violation_mismatch_decl and // note_module_odr_violation_mismatch_decl + // This list should be the same Decl's as in ODRHash::isWhiteListedDecl enum { EndOfClass, PublicSpecifer, @@ -9250,6 +9251,9 @@ void ASTReader::diagnoseOdrViolations() { StaticAssert, Field, CXXMethod, + TypeAlias, + TypeDef, + Var, Other } FirstDiffType = Other, SecondDiffType = Other; @@ -9277,6 +9281,12 @@ void ASTReader::diagnoseOdrViolations() { return Field; case Decl::CXXMethod: return CXXMethod; + case Decl::TypeAlias: + return TypeAlias; + case Decl::Typedef: + return TypeDef; + case Decl::Var: + return Var; } }; @@ -9373,6 +9383,15 @@ void ASTReader::diagnoseOdrViolations() { MethodNumberParameters, MethodParameterType, MethodParameterName, + MethodParameterSingleDefaultArgument, + MethodParameterDifferentDefaultArgument, + TypedefName, + TypedefType, + VarName, + VarType, + VarSingleInitializer, + VarDifferentInitializer, + VarConstexpr, }; // These lambdas have the common portions of the ODR diagnostics. This @@ -9739,6 +9758,38 @@ void ASTReader::diagnoseOdrViolations() { ParameterMismatch = true; break; } + + const Expr *FirstInit = FirstParam->getInit(); + const Expr *SecondInit = SecondParam->getInit(); + if ((FirstInit == nullptr) != (SecondInit == nullptr)) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), + MethodParameterSingleDefaultArgument) + << FirstName << (I + 1) << (FirstInit == nullptr) + << (FirstInit ? FirstInit->getSourceRange() : SourceRange()); + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), + MethodParameterSingleDefaultArgument) + << SecondName << (I + 1) << (SecondInit == nullptr) + << (SecondInit ? SecondInit->getSourceRange() : SourceRange()); + ParameterMismatch = true; + break; + } + + if (FirstInit && SecondInit && + ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), + MethodParameterDifferentDefaultArgument) + << FirstName << (I + 1) << FirstInit->getSourceRange(); + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), + MethodParameterDifferentDefaultArgument) + << SecondName << (I + 1) << SecondInit->getSourceRange(); + ParameterMismatch = true; + break; + + } } if (ParameterMismatch) { @@ -9748,6 +9799,109 @@ void ASTReader::diagnoseOdrViolations() { break; } + case TypeAlias: + case TypeDef: { + TypedefNameDecl *FirstTD = cast(FirstDecl); + TypedefNameDecl *SecondTD = cast(SecondDecl); + auto FirstName = FirstTD->getDeclName(); + auto SecondName = SecondTD->getDeclName(); + if (FirstName != SecondName) { + ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(), + TypedefName) + << (FirstDiffType == TypeAlias) << FirstName; + ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(), + TypedefName) + << (FirstDiffType == TypeAlias) << SecondName; + Diagnosed = true; + break; + } + + QualType FirstType = FirstTD->getUnderlyingType(); + QualType SecondType = SecondTD->getUnderlyingType(); + if (ComputeQualTypeODRHash(FirstType) != + ComputeQualTypeODRHash(SecondType)) { + ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(), + TypedefType) + << (FirstDiffType == TypeAlias) << FirstName << FirstType; + ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(), + TypedefType) + << (FirstDiffType == TypeAlias) << SecondName << SecondType; + Diagnosed = true; + break; + } + break; + } + case Var: { + VarDecl *FirstVD = cast(FirstDecl); + VarDecl *SecondVD = cast(SecondDecl); + auto FirstName = FirstVD->getDeclName(); + auto SecondName = SecondVD->getDeclName(); + if (FirstName != SecondName) { + ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), + VarName) + << FirstName; + ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), + VarName) + << SecondName; + Diagnosed = true; + break; + } + + QualType FirstType = FirstVD->getType(); + QualType SecondType = SecondVD->getType(); + if (ComputeQualTypeODRHash(FirstType) != + ComputeQualTypeODRHash(SecondType)) { + ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), + VarType) + << FirstName << FirstType; + ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), + VarType) + << SecondName << SecondType; + Diagnosed = true; + break; + } + + const Expr *FirstInit = FirstVD->getInit(); + const Expr *SecondInit = SecondVD->getInit(); + if ((FirstInit == nullptr) != (SecondInit == nullptr)) { + ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), + VarSingleInitializer) + << FirstName << (FirstInit == nullptr) + << (FirstInit ? FirstInit->getSourceRange(): SourceRange()); + ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), + VarSingleInitializer) + << SecondName << (SecondInit == nullptr) + << (SecondInit ? SecondInit->getSourceRange() : SourceRange()); + Diagnosed = true; + break; + } + + if (FirstInit && SecondInit && + ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { + ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), + VarDifferentInitializer) + << FirstName << FirstInit->getSourceRange(); + ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), + VarDifferentInitializer) + << SecondName << SecondInit->getSourceRange(); + Diagnosed = true; + break; + } + + const bool FirstIsConstexpr = FirstVD->isConstexpr(); + const bool SecondIsConstexpr = SecondVD->isConstexpr(); + if (FirstIsConstexpr != SecondIsConstexpr) { + ODRDiagError(FirstVD->getLocation(), FirstVD->getSourceRange(), + VarConstexpr) + << FirstName << FirstIsConstexpr; + ODRDiagNote(SecondVD->getLocation(), SecondVD->getSourceRange(), + VarConstexpr) + << SecondName << SecondIsConstexpr; + Diagnosed = true; + break; + } + break; + } } if (Diagnosed == true) diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 9c467055fe55..ed103e629216 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -216,30 +216,6 @@ namespace clang { TypedefNameForLinkage(nullptr), HasPendingBody(false), IsDeclMarkedUsed(false) {} - template static - void AddLazySpecializations(T *D, - SmallVectorImpl& IDs) { - if (IDs.empty()) - return; - - // FIXME: We should avoid this pattern of getting the ASTContext. - ASTContext &C = D->getASTContext(); - - auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations; - - if (auto &Old = LazySpecializations) { - IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); - std::sort(IDs.begin(), IDs.end()); - IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); - } - - auto *Result = new (C) serialization::DeclID[1 + IDs.size()]; - *Result = IDs.size(); - std::copy(IDs.begin(), IDs.end(), Result + 1); - - LazySpecializations = Result; - } - template static Decl *getMostRecentDeclImpl(Redeclarable *D); static Decl *getMostRecentDeclImpl(...); @@ -268,7 +244,7 @@ namespace clang { void ReadFunctionDefinition(FunctionDecl *FD); void Visit(Decl *D); - void UpdateDecl(Decl *D, llvm::SmallVectorImpl&); + void UpdateDecl(Decl *D); static void setNextObjCCategory(ObjCCategoryDecl *Cat, ObjCCategoryDecl *Next) { @@ -1976,6 +1952,21 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { return Redecl; } +static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old, + SmallVectorImpl &IDs) { + assert(!IDs.empty() && "no IDs to add to list"); + if (Old) { + IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); + std::sort(IDs.begin(), IDs.end()); + IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); + } + + auto *Result = new (Context) DeclID[1 + IDs.size()]; + *Result = IDs.size(); + std::copy(IDs.begin(), IDs.end(), Result + 1); + return Result; +} + void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); @@ -1984,7 +1975,12 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { // the specializations. SmallVector SpecIDs; ReadDeclIDList(SpecIDs); - ASTDeclReader::AddLazySpecializations(D, SpecIDs); + + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); + } } if (D->getTemplatedDecl()->TemplateOrInstantiation) { @@ -2011,7 +2007,12 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { // the specializations. SmallVector SpecIDs; ReadDeclIDList(SpecIDs); - ASTDeclReader::AddLazySpecializations(D, SpecIDs); + + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); + } } } @@ -2117,7 +2118,12 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // This FunctionTemplateDecl owns a CommonPtr; read it. SmallVector SpecIDs; ReadDeclIDList(SpecIDs); - ASTDeclReader::AddLazySpecializations(D, SpecIDs); + + if (!SpecIDs.empty()) { + auto *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = newDeclIDList( + Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); + } } } @@ -3661,9 +3667,6 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { Decl *D = Record.D; ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); - - llvm::SmallVector PendingLazySpecializationIDs; - if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); DeclUpdateOffsets.erase(UpdI); @@ -3688,7 +3691,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID, SourceLocation()); - Reader.UpdateDecl(D, PendingLazySpecializationIDs); + Reader.UpdateDecl(D); // We might have made this declaration interesting. If so, remember that // we need to hand it off to the consumer. @@ -3700,17 +3703,6 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { } } } - // Add the lazy specializations to the template. - assert((PendingLazySpecializationIDs.empty() || isa(D) || - isa(D) || isa(D)) && - "Must not have pending specializations"); - if (auto *CTD = dyn_cast(D)) - ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs); - else if (auto *FTD = dyn_cast(D)) - ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs); - else if (auto *VTD = dyn_cast(D)) - ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs); - PendingLazySpecializationIDs.clear(); // Load the pending visible updates for this decl context, if it has any. auto I = PendingVisibleUpdates.find(ID); @@ -3907,8 +3899,7 @@ static void forAllLaterRedecls(DeclT *D, Fn F) { } } -void ASTDeclReader::UpdateDecl(Decl *D, - llvm::SmallVectorImpl &PendingLazySpecializationIDs) { +void ASTDeclReader::UpdateDecl(Decl *D) { while (Record.getIdx() < Record.size()) { switch ((DeclUpdateKind)Record.readInt()) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { @@ -3924,8 +3915,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, } case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: - // It will be added to the template's lazy specialization set. - PendingLazySpecializationIDs.push_back(ReadDeclID()); + // It will be added to the template's specializations set when loaded. + (void)Record.readDecl(); break; case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index ee761689f479..1858bfd89637 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -957,6 +957,12 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { return RuntimeDefinition(); DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver); + if (!DTI.isValid()) { + assert(isa(Receiver) && + "Unhandled untyped region class!"); + return RuntimeDefinition(); + } + QualType DynType = DTI.getType(); CanBeSubClassed = DTI.canBeASubClass(); ReceiverT = dyn_cast(DynType.getCanonicalType()); diff --git a/test/Analysis/DynamicTypePropagation.m b/test/Analysis/DynamicTypePropagation.m index 25a0ae35fd32..63904b842567 100644 --- a/test/Analysis/DynamicTypePropagation.m +++ b/test/Analysis/DynamicTypePropagation.m @@ -4,6 +4,9 @@ # error Compiler does not support Objective-C generics? #endif +typedef __typeof(sizeof(int)) size_t; +void *memset(void *, int, size_t); + #define nil 0 typedef unsigned long NSUInteger; typedef int BOOL; @@ -21,6 +24,7 @@ __attribute__((objc_root_class)) @end @interface NSArray : NSObject +- (void) init; - (BOOL)contains:(ObjectType)obj; - (ObjectType)getObjAtIndex:(NSUInteger)idx; - (ObjectType)objectAtIndexedSubscript:(NSUInteger)idx; @@ -55,3 +59,11 @@ void testArgument(NSArray *arr, id element) { // MyType! [element myFunction:0 myParam:0 ]; } + +// Do not try this at home! The analyzer shouldn't crash though when it +// tries to figure out the dynamic type behind the alloca's return value. +void testAlloca(size_t NSArrayClassSizeWeKnowSomehow) { + NSArray *arr = __builtin_alloca(NSArrayClassSizeWeKnowSomehow); + memset(arr, 0, NSArrayClassSizeWeKnowSomehow); + [arr init]; // no-crash +} diff --git a/test/Analysis/analyzer_test.py b/test/Analysis/analyzer_test.py index 58df11a4ba47..0aa2dbc1bb09 100644 --- a/test/Analysis/analyzer_test.py +++ b/test/Analysis/analyzer_test.py @@ -5,24 +5,39 @@ class AnalyzerTest(lit.formats.ShTest): def execute(self, test, litConfig): - result = self.executeWithAnalyzeSubstitution( - test, litConfig, '-analyzer-constraints=range') + results = [] - if result.code == lit.Test.FAIL: - return result + # Parse any test requirements ('REQUIRES: ') + saved_test = test + lit.TestRunner.parseIntegratedTestScript(test) + + if 'z3' not in test.requires: + results.append(self.executeWithAnalyzeSubstitution( + saved_test, litConfig, '-analyzer-constraints=range')) + + if results[-1].code == lit.Test.FAIL: + return results[-1] # If z3 backend available, add an additional run line for it if test.config.clang_staticanalyzer_z3 == '1': - result = self.executeWithAnalyzeSubstitution( - test, litConfig, '-analyzer-constraints=z3 -DANALYZER_CM_Z3') + results.append(self.executeWithAnalyzeSubstitution( + saved_test, litConfig, '-analyzer-constraints=z3 -DANALYZER_CM_Z3')) - return result + # Combine all result outputs into the last element + for x in results: + if x != results[-1]: + results[-1].output = x.output + results[-1].output + + if results: + return results[-1] + return lit.Test.Result(lit.Test.UNSUPPORTED, + "Test requires the following unavailable features: z3") def executeWithAnalyzeSubstitution(self, test, litConfig, substitution): saved_substitutions = list(test.config.substitutions) test.config.substitutions.append(('%analyze', substitution)) result = lit.TestRunner.executeShTest(test, litConfig, - self.execute_external) + self.execute_external) test.config.substitutions = saved_substitutions return result diff --git a/test/CodeCompletion/member-access.cpp b/test/CodeCompletion/member-access.cpp index 53af121951bb..a0dc7b485679 100644 --- a/test/CodeCompletion/member-access.cpp +++ b/test/CodeCompletion/member-access.cpp @@ -145,4 +145,22 @@ class Template { // CHECK-CC6: o2 : [#BaseTemplate#]o2 // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:142:11 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s } + + static void staticFn(T &obj); + + struct Nested { }; }; + +template +void dependentColonColonCompletion() { + Template::staticFn(); +// CHECK-CC7: function : [#void#]function() +// CHECK-CC7: Nested : Nested +// CHECK-CC7: o1 : [#BaseTemplate#]o1 +// CHECK-CC7: o2 : [#BaseTemplate#]o2 +// CHECK-CC7: staticFn : [#void#]staticFn(<#T &obj#>) +// CHECK-CC7: Template : Template +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:156:16 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s + typename Template::Nested m; +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:164:25 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s +} diff --git a/test/CodeGen/Inputs/thinlto-multi-module.ll b/test/CodeGen/Inputs/thinlto-multi-module.ll new file mode 100644 index 000000000000..e8dc16a8f572 --- /dev/null +++ b/test/CodeGen/Inputs/thinlto-multi-module.ll @@ -0,0 +1,9 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @f2() { + ret void +} + +!0 = !{i32 1, !"ThinLTO", i32 0} +!llvm.module.flags = !{ !0 } diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c index 9e5fa9f90651..34833a246920 100644 --- a/test/CodeGen/attributes.c +++ b/test/CodeGen/attributes.c @@ -56,6 +56,13 @@ void t4() {} void t7() __attribute__((noreturn, nothrow)); void t7() { while (1) {} } +// CHECK: define void @t72() [[COLDDEF:#[0-9]+]] { +void t71(void) __attribute__((cold)); +void t72() __attribute__((cold)); +void t72() { t71(); } +// CHECK: call void @t71() [[COLDSITE:#[0-9]+]] +// CHECK: declare void @t71() [[COLDDECL:#[0-9]+]] + // CHECK: define void @t10() [[NUW]] section "SECT" { void t10(void) __attribute__((section("SECT"))); void t10(void) {} @@ -92,3 +99,6 @@ void __attribute__((section(".bar"))) t22(void) {} // CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } // CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} } +// CHECK: attributes [[COLDDEF]] = { cold {{.*}}} +// CHECK: attributes [[COLDDECL]] = { cold {{.*}}} +// CHECK: attributes [[COLDSITE]] = { cold {{.*}}} diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index 90f428efb339..31a08440d061 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -1427,3 +1427,51 @@ float test_mm256_cvtss_f32(__m256 __a) // CHECK: extractelement <8 x float> %{{.*}}, i32 0 return _mm256_cvtss_f32(__a); } + +__m256 test_mm256_cmp_ps_true(__m256 a, __m256 b) { + // CHECK-LABEL: @test_mm256_cmp_ps_true + // CHECK: store <8 x float> zeroinitializer, <8 x float>* %tmp, align 32 + return _mm256_cmp_ps(a, b, _CMP_FALSE_OQ); +} + +__m256 test_mm256_cmp_pd_false(__m256 a, __m256 b) { + // CHECK-LABEL: @test_mm256_cmp_pd_false + // CHECK: store <4 x double> zeroinitializer, <4 x double>* %tmp, align 32 + return _mm256_cmp_pd(a, b, _CMP_FALSE_OQ); +} + +__m256 test_mm256_cmp_ps_strue(__m256 a, __m256 b) { + // CHECK-LABEL: @test_mm256_cmp_ps_strue + // CHECK: store <8 x float> zeroinitializer, <8 x float>* %tmp, align 32 + return _mm256_cmp_ps(a, b, _CMP_FALSE_OS); +} + +__m256 test_mm256_cmp_pd_sfalse(__m256 a, __m256 b) { + // CHECK-LABEL: @test_mm256_cmp_pd_sfalse + // CHECK: store <4 x double> zeroinitializer, <4 x double>* %tmp, align 32 + return _mm256_cmp_pd(a, b, _CMP_FALSE_OS); +} diff --git a/test/CodeGen/builtins-ppc-error.c b/test/CodeGen/builtins-ppc-error.c index c3d6e639d828..29eebf286100 100644 --- a/test/CodeGen/builtins-ppc-error.c +++ b/test/CodeGen/builtins-ppc-error.c @@ -11,6 +11,8 @@ #include extern vector signed int vsi; +extern vector signed int vui; +extern vector float vf; extern vector unsigned char vuc; void testInsertWord(void) { @@ -34,3 +36,34 @@ void testXXSLDWI(int index) { vec_xxsldwi(1, 2, 3); //expected-error {{first two arguments to '__builtin_vsx_xxsldwi' must be vectors}} vec_xxsldwi(vsi, vuc, 2); //expected-error {{first two arguments to '__builtin_vsx_xxsldwi' must have the same type}} } + +void testCTF(int index) { + vec_ctf(vsi, index); //expected-error {{argument to '__builtin_altivec_vcfsx' must be a constant integer}} + vec_ctf(vui, index); //expected-error {{argument to '__builtin_altivec_vcfsx' must be a constant integer}} +} + +void testVCFSX(int index) { + vec_vcfsx(vsi, index); //expected-error {{argument to '__builtin_altivec_vcfsx' must be a constant integer}} +} + +void testVCFUX(int index) { + vec_vcfux(vui, index); //expected-error {{argument to '__builtin_altivec_vcfux' must be a constant integer}} +} + +void testCTS(int index) { + vec_cts(vf, index); //expected-error {{argument to '__builtin_altivec_vctsxs' must be a constant integer}} + +} + +void testVCTSXS(int index) { + vec_vctsxs(vf, index); //expected-error {{argument to '__builtin_altivec_vctsxs' must be a constant integer}} +} + +void testCTU(int index) { + vec_ctu(vf, index); //expected-error {{argument to '__builtin_altivec_vctuxs' must be a constant integer}} + +} + +void testVCTUXS(int index) { + vec_vctuxs(vf, index); //expected-error {{argument to '__builtin_altivec_vctuxs' must be a constant integer}} +} diff --git a/test/CodeGen/dependent-lib.c b/test/CodeGen/dependent-lib.c index 9cf49c88d77b..7178a29692a1 100644 --- a/test/CodeGen/dependent-lib.c +++ b/test/CodeGen/dependent-lib.c @@ -3,14 +3,10 @@ // RUN: %clang_cc1 %s --dependent-lib=msvcrt -triple x86_64-pc-win32 -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 %s --dependent-lib=msvcrt -triple i686-pc-linux -emit-llvm -o - | FileCheck -check-prefix LINUX %s -// CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} -// CHECK: ![[link_opts]] = !{![[msvcrt:[0-9]+]]} +// CHECK: !llvm.linker.options = !{![[msvcrt:[0-9]+]]} // CHECK: ![[msvcrt]] = !{!"/DEFAULTLIB:msvcrt.lib"} -// LINUX: !llvm.module.flags = !{{{.*}}} -// LINUX: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} -// LINUX: ![[link_opts]] = !{![[msvcrt:[0-9]+]]} +// LINUX: !llvm.linker.options = !{![[msvcrt:[0-9]+]]} // LINUX: ![[msvcrt]] = !{!"-lmsvcrt"} int f(); diff --git a/test/CodeGen/linker-option.c b/test/CodeGen/linker-option.c index b1b2ec461c89..13bd981179b5 100644 --- a/test/CodeGen/linker-option.c +++ b/test/CodeGen/linker-option.c @@ -1,8 +1,6 @@ // RUN: %clang_cc1 %s --linker-option=/include:foo -triple i686-pc-win32 -emit-llvm -o - | FileCheck %s -// CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} -// CHECK: ![[link_opts]] = !{![[msvcrt:[0-9]+]]} +// CHECK: !llvm.linker.options = !{![[msvcrt:[0-9]+]]} // CHECK: ![[msvcrt]] = !{!"/include:foo"} int f(); diff --git a/test/CodeGen/mips-debug-info-bitfield.c b/test/CodeGen/mips-debug-info-bitfield.c new file mode 100644 index 000000000000..a0e2ed9cde86 --- /dev/null +++ b/test/CodeGen/mips-debug-info-bitfield.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -x c -debug-info-kind=limited -triple mips-none-linux-gnu -emit-llvm -o - %s | FileCheck %s + +struct fields +{ + unsigned a : 4; + unsigned b : 4; +} flags; + +// CHECK: !DIDerivedType(tag: DW_TAG_member, +// CHECK-SAME: {{.*}}name: "a" +// CHECK-NOT: {{.*}}offset: +// CHECK-SAME: {{.*}}flags: DIFlagBitField + +// CHECK: !DIDerivedType(tag: DW_TAG_member, +// CHECK-SAME: {{.*}}name: "b" +// CHECK-SAME: {{.*}}offset: 4 +// CHECK-SAME: {{.*}}flags: DIFlagBitField diff --git a/test/CodeGen/pragma-comment.c b/test/CodeGen/pragma-comment.c index 71a7dfc0b018..e20efacdcb22 100644 --- a/test/CodeGen/pragma-comment.c +++ b/test/CodeGen/pragma-comment.c @@ -14,9 +14,7 @@ #pragma comment(linker," /bar=" BAR) #pragma comment(linker," /foo=\"foo bar\"") -// CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} -// CHECK: ![[link_opts]] = !{![[msvcrt:[0-9]+]], ![[kernel32:[0-9]+]], ![[USER32:[0-9]+]], ![[space:[0-9]+]], ![[bar:[0-9]+]], ![[foo:[0-9]+]]} +// CHECK: !llvm.linker.options = !{![[msvcrt:[0-9]+]], ![[kernel32:[0-9]+]], ![[USER32:[0-9]+]], ![[space:[0-9]+]], ![[bar:[0-9]+]], ![[foo:[0-9]+]]} // CHECK: ![[msvcrt]] = !{!"/DEFAULTLIB:msvcrt.lib"} // CHECK: ![[kernel32]] = !{!"/DEFAULTLIB:kernel32.lib"} // CHECK: ![[USER32]] = !{!"/DEFAULTLIB:USER32.LIB"} diff --git a/test/CodeGen/pragma-detect_mismatch.c b/test/CodeGen/pragma-detect_mismatch.c index 08259fc6be71..066183d31264 100644 --- a/test/CodeGen/pragma-detect_mismatch.c +++ b/test/CodeGen/pragma-detect_mismatch.c @@ -6,8 +6,6 @@ #define BAR "2" #pragma detect_mismatch("test2", BAR) -// CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} -// CHECK: ![[link_opts]] = !{![[test:[0-9]+]], ![[test2:[0-9]+]]} +// CHECK: !llvm.linker.options = !{![[test:[0-9]+]], ![[test2:[0-9]+]]} // CHECK: ![[test]] = !{!"/FAILIFMISMATCH:\22test=1\22"} // CHECK: ![[test2]] = !{!"/FAILIFMISMATCH:\22test2=2\22"} diff --git a/test/CodeGen/thinlto-backend-option.ll b/test/CodeGen/thinlto-backend-option.ll index 4c7c0ea3efcd..4fcdd079df84 100644 --- a/test/CodeGen/thinlto-backend-option.ll +++ b/test/CodeGen/thinlto-backend-option.ll @@ -8,6 +8,8 @@ ; RUN: %clang -flto=thin -c -o %t.o %s ; RUN: llvm-lto -thinlto -o %t %t.o -; RUN: not %clang_cc1 -x ir %t.o -fthinlto-index=%t.thinlto.bc -backend-option -nonexistent -emit-obj -o /dev/null 2>&1 | FileCheck %s +; RUN: not %clang_cc1 -x ir %t.o -fthinlto-index=%t.thinlto.bc -backend-option -nonexistent -emit-obj -o /dev/null 2>&1 | FileCheck %s -check-prefix=UNKNOWN +; UNKNOWN: clang: Unknown command line argument '-nonexistent' -; CHECK: clang: Unknown command line argument '-nonexistent' +; RUN: not %clang_cc1 -flto=thinfoo 2>&1 | FileCheck %s -check-prefix=INVALID +; INVALID: error: invalid value 'thinfoo' in '-flto=thinfoo' diff --git a/test/CodeGen/thinlto-multi-module.ll b/test/CodeGen/thinlto-multi-module.ll index 21d28cf44da2..385d98c74d94 100644 --- a/test/CodeGen/thinlto-multi-module.ll +++ b/test/CodeGen/thinlto-multi-module.ll @@ -3,8 +3,8 @@ ; RUN: opt -module-summary -o %t1.o %s ; RUN: llvm-lto -thinlto -o %t %t1.o -; RUN: opt -o %t2.o %S/Inputs/thinlto_backend.ll -; RUN: llvm-cat -b -o %t1cat.o %t1.o %t2.o +; RUN: opt -module-summary -o %t2.o %S/Inputs/thinlto-multi-module.ll +; RUN: llvm-cat -b -o %t1cat.o %t2.o %t1.o ; RUN: cp %t1cat.o %t1.o ; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t3.o -x ir %t1.o -c -fthinlto-index=%t.thinlto.bc ; RUN: llvm-nm %t3.o | FileCheck --check-prefix=CHECK-OBJ %s diff --git a/test/CodeGen/ubsan-pointer-overflow.m b/test/CodeGen/ubsan-pointer-overflow.m index 56df95baff55..da622355fdb4 100644 --- a/test/CodeGen/ubsan-pointer-overflow.m +++ b/test/CodeGen/ubsan-pointer-overflow.m @@ -5,23 +5,21 @@ void unary_arith(char *p) { // CHECK: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 1, !nosanitize // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize - // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize - // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 true, i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize - // CHECK-NEXT: [[VALID:%.*]] = and i1 true, [[DIFFVALID]], !nosanitize - // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize + // CHECK-NEXT: br i1 [[POSVALID]]{{.*}}, !nosanitize // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize ++p; // CHECK: ptrtoint i8* {{.*}} to i64, !nosanitize // CHECK-NEXT: add i64 {{.*}}, -1, !nosanitize // CHECK: select i1 false{{.*}}, !nosanitize - // CHECK-NEXT: and i1 true{{.*}}, !nosanitize // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} --p; + // CHECK-NOT: select // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} p++; + // CHECK: select // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} p--; } @@ -30,22 +28,43 @@ void unary_arith(char *p) { void binary_arith(char *p, int i) { // CHECK: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %{{.*}}), !nosanitize // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize - // CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], !nosanitize // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize // CHECK-NEXT: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize + // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[SMULOFLOW]], true, !nosanitize // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize - // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize - // CHECK-DAG: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize - // CHECK-DAG: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize - // CHECK: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize + // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize + // CHECK: [[VALID:%.*]] = and i1 [[DIFFVALID]], [[OFFSETVALID]], !nosanitize // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize p + i; // CHECK: [[OFFSET:%.*]] = sub i64 0, {{.*}} // CHECK-NEXT: getelementptr inbounds {{.*}} [[OFFSET]] + // CHECK: select + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + p - i; +} + +// CHECK-LABEL: define void @binary_arith_unsigned +void binary_arith_unsigned(char *p, unsigned i) { + // CHECK: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %{{.*}}), !nosanitize + // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize + // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize + // CHECK-NEXT: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize + // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[SMULOFLOW]], true, !nosanitize + // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK: [[VALID:%.*]] = and i1 [[POSVALID]], [[OFFSETVALID]], !nosanitize + // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize + p + i; + + // CHECK: [[OFFSET:%.*]] = sub i64 0, {{.*}} + // CHECK-NEXT: getelementptr inbounds {{.*}} [[OFFSET]] + // CHECK: select // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} p - i; } @@ -55,16 +74,15 @@ void fixed_len_array(int k) { // CHECK: getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* [[ARR:%.*]], i64 0, i64 [[IDXPROM:%.*]] // CHECK-NEXT: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 40, i64 [[IDXPROM]]), !nosanitize // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize - // CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], !nosanitize // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize // CHECK-NEXT: [[BASE:%.*]] = ptrtoint [10 x [10 x i32]]* [[ARR]] to i64, !nosanitize // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize + // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[SMULOFLOW]], true, !nosanitize // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize - // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize - // CHECK-DAG: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize - // CHECK-DAG: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize - // CHECK: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize + // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize + // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize + // CHECK: [[VALID:%.*]] = and i1 [[DIFFVALID]], [[OFFSETVALID]], !nosanitize // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize @@ -101,6 +119,24 @@ void pointer_array(int **arr, int k) { arr[k][k]; } +// CHECK-LABEL: define void @pointer_array_unsigned_indices +void pointer_array_unsigned_indices(int **arr, unsigned k) { + // CHECK-NOT: select + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + // CHECK-NOT: select + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + arr[k][k]; +} + +// CHECK-LABEL: define void @pointer_array_mixed_indices +void pointer_array_mixed_indices(int **arr, int i, unsigned j) { + // CHECK: select + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + // CHECK-NOT: select + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} + arr[i][j]; +} + struct S1 { int pad1; union { @@ -118,6 +154,7 @@ void struct_index(struct S1 *p) { // CHECK: getelementptr inbounds %struct.S1, %struct.S1* [[P:%.*]], i64 10 // CHECK-NEXT: [[BASE:%.*]] = ptrtoint %struct.S1* [[P]] to i64, !nosanitize // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 240, !nosanitize + // CHECK: select // CHECK: @__ubsan_handle_pointer_overflow{{.*}} i64 [[BASE]], i64 [[COMPGEP]]) {{.*}}, !nosanitize // CHECK-NOT: @__ubsan_handle_pointer_overflow @@ -130,10 +167,12 @@ typedef void (*funcptr_t)(void); // CHECK-LABEL: define void @function_pointer_arith void function_pointer_arith(funcptr_t *p, int k) { // CHECK: add i64 {{.*}}, 8, !nosanitize + // CHECK-NOT: select // CHECK: @__ubsan_handle_pointer_overflow{{.*}} ++p; // CHECK: @llvm.smul.with.overflow.i64(i64 8, i64 {{.*}}), !nosanitize + // CHECK: select // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} p + k; } @@ -145,11 +184,13 @@ void variable_len_array_arith(int n, int k) { // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[INC:%.*]] // CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 [[INC]]), !nosanitize + // CHECK-NOT: select // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} ++p; // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]] // CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM]]), !nosanitize + // CHECK: select // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} p + k; } @@ -157,6 +198,7 @@ void variable_len_array_arith(int n, int k) { // CHECK-LABEL: define void @objc_id void objc_id(id *p) { // CHECK: add i64 {{.*}}, 8, !nosanitize + // CHECK-NOT: select // CHECK: @__ubsan_handle_pointer_overflow{{.*}} p++; } diff --git a/test/CodeGen/ubsan-volatile.c b/test/CodeGen/ubsan-volatile.c new file mode 100644 index 000000000000..ce54aada81fd --- /dev/null +++ b/test/CodeGen/ubsan-volatile.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=null,alignment,object-size,vptr -S -emit-llvm %s -o - | FileCheck %s + +// CHECK: @volatile_null_deref +void volatile_null_deref(volatile int *p) { + // CHECK-NOT: call{{.*}}ubsan + *p; +} diff --git a/test/CodeGenCXX/ms-thread_local.cpp b/test/CodeGenCXX/ms-thread_local.cpp index 5183ab5c32e1..dc7958d6eacf 100644 --- a/test/CodeGenCXX/ms-thread_local.cpp +++ b/test/CodeGenCXX/ms-thread_local.cpp @@ -27,7 +27,5 @@ A f() { return c; } -// CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} -// CHECK: ![[link_opts]] = !{![[dyn_tls_init:[0-9]+]]} +// CHECK: !llvm.linker.options = !{![[dyn_tls_init:[0-9]+]]} // CHECK: ![[dyn_tls_init]] = !{!"/include:___dyn_tls_init@12"} diff --git a/test/CodeGenCoroutines/coro-await.cpp b/test/CodeGenCoroutines/coro-await.cpp index 1e2deaa8f59a..fc6559f1e0ad 100644 --- a/test/CodeGenCoroutines/coro-await.cpp +++ b/test/CodeGenCoroutines/coro-await.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 \ +// RUN: -emit-llvm %s -o - -disable-llvm-passes -Wno-coroutine -Wno-unused | FileCheck %s namespace std { namespace experimental { @@ -278,3 +279,50 @@ void AwaitLValue() { suspend_always lval; co_await lval; } + +struct RefTag { }; + +struct AwaitResumeReturnsLValue { + bool await_ready(); + void await_suspend(std::experimental::coroutine_handle<>); + RefTag& await_resume(); +}; + + +template<> +struct std::experimental::coroutine_traits { + struct promise_type { + void get_return_object(); + init_susp initial_suspend(); + final_susp final_suspend(); + void return_void(); + AwaitResumeReturnsLValue yield_value(int); + }; +}; + +// Verifies that we don't crash when returning an lvalue from an await_resume() +// expression. +// CHECK-LABEL: define void @_Z18AwaitReturnsLValued(double) +void AwaitReturnsLValue(double) { + AwaitResumeReturnsLValue a; + // CHECK: %[[AVAR:.+]] = alloca %struct.AwaitResumeReturnsLValue, + // CHECK: %[[XVAR:.+]] = alloca %struct.RefTag*, + + // CHECK: %[[YVAR:.+]] = alloca %struct.RefTag*, + // CHECK-NEXT: %[[TMP1:.+]] = alloca %struct.AwaitResumeReturnsLValue, + + // CHECK: %[[ZVAR:.+]] = alloca %struct.RefTag*, + // CHECK-NEXT: %[[TMP2:.+]] = alloca %struct.AwaitResumeReturnsLValue, + + // CHECK: %[[RES1:.+]] = call dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* %[[AVAR]]) + // CHECK-NEXT: store %struct.RefTag* %[[RES1]], %struct.RefTag** %[[XVAR]], + RefTag& x = co_await a; + + // CHECK: %[[RES2:.+]] = call dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* %[[TMP1]]) + // CHECK-NEXT: store %struct.RefTag* %[[RES2]], %struct.RefTag** %[[YVAR]], + + RefTag& y = co_await AwaitResumeReturnsLValue{}; + // CHECK: %[[RES3:.+]] = call dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* %[[TMP2]]) + // CHECK-NEXT: store %struct.RefTag* %[[RES3]], %struct.RefTag** %[[ZVAR]], + RefTag& z = co_yield 42; +} diff --git a/test/CodeGenObjC/availability-cf-link-guard.m b/test/CodeGenObjC/availability-cf-link-guard.m index 918d13ffd9f4..6bd426476bba 100644 --- a/test/CodeGenObjC/availability-cf-link-guard.m +++ b/test/CodeGenObjC/availability-cf-link-guard.m @@ -37,9 +37,8 @@ void use_at_available() { // CHECK_NO_GUARD-NOT: __clang_at_available_requires_core_foundation_framework // CHECK_NO_GUARD-NOT: CFBundleGetVersionNumber -// CHECK_LINK_OPT: !"Linker Options", ![[OPTS:[0-9]+]] -// CHECK_LINK_OPT: ![[OPTS]] = !{![[FRAMEWORK:[0-9]+]] +// CHECK_LINK_OPT: !llvm.linker.options = !{![[FRAMEWORK:[0-9]+]] // CHECK_LINK_OPT: ![[FRAMEWORK]] = !{!"-framework", !"CoreFoundation"} -// CHECK_NO_GUARD-NOT: "Linker Options" +// CHECK_NO_GUARD-NOT: !llvm.linker.options // CHECK_NO_GUARD-NOT: CoreFoundation diff --git a/test/Coverage/ast-printing.c b/test/Coverage/ast-printing.c index eb22f92e66d7..dfda6c676f6f 100644 --- a/test/Coverage/ast-printing.c +++ b/test/Coverage/ast-printing.c @@ -3,6 +3,7 @@ // RUN: %clang_cc1 -ast-print %t.1.c -o %t.2.c // RUN: diff %t.1.c %t.2.c // RUN: %clang_cc1 -ast-dump %s +// RUN: %clang_cc1 -ast-dump-all %s // RUN: %clang_cc1 -print-decl-contexts %s #include "c-language-features.inc" diff --git a/test/Coverage/ast-printing.cpp b/test/Coverage/ast-printing.cpp index e03c51735335..bcd78be7d05b 100644 --- a/test/Coverage/ast-printing.cpp +++ b/test/Coverage/ast-printing.cpp @@ -3,6 +3,7 @@ // RUN: %clang_cc1 -std=c++14 -ast-print %t.1.cpp -o %t.2.cpp // RUN: diff %t.1.cpp %t.2.cpp // RUN: %clang_cc1 -std=c++14 -ast-dump %s +// RUN: %clang_cc1 -std=c++14 -ast-dump-all %s // RUN: %clang_cc1 -std=c++14 -print-decl-contexts %s // RUN: %clang_cc1 -std=c++14 -fdump-record-layouts %s diff --git a/test/Driver/m_and_mm.c b/test/Driver/m_and_mm.c index 18cf7abfa629..6e40c82cb16c 100644 --- a/test/Driver/m_and_mm.c +++ b/test/Driver/m_and_mm.c @@ -1,3 +1,15 @@ // RUN: %clang -### \ // RUN: -M -MM %s 2> %t // RUN: not grep '"-sys-header-deps"' %t + +// RUN: %clang -M -MM %s 2> %t +// RUN: not grep "warning" %t + +// RUN: %clang -MMD -MD %s 2> %t || true +// RUN: grep "warning" %t + +#warning "This warning shouldn't show up with -M and -MM" +int main (void) +{ + return 0; +} diff --git a/test/Index/Core/index-source.cpp b/test/Index/Core/index-source.cpp index 8b049314ffbe..10f2d8f77747 100644 --- a/test/Index/Core/index-source.cpp +++ b/test/Index/Core/index-source.cpp @@ -1,4 +1,4 @@ -// RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s +// RUN: c-index-test core -print-source-symbols -- %s -std=c++1z -target x86_64-apple-macosx10.7 | FileCheck %s // CHECK: [[@LINE+1]]:7 | class/C++ | Cls | [[Cls_USR:.*]] | | Def | rel: 0 class Cls { public: @@ -433,3 +433,45 @@ template T varDecl = T(); } // end namespace ensureDefaultTemplateParamsAreRecordedOnce + +struct StaticAssertRef { + static constexpr bool constVar = true; +}; + +static_assert(StaticAssertRef::constVar, "index static asserts"); +// CHECK: [[@LINE-1]]:32 | static-property/C++ | constVar | c:@S@StaticAssertRef@constVar | __ZN15StaticAssertRef8constVarE | Ref | rel: 0 +// CHECK: [[@LINE-2]]:15 | struct/C++ | StaticAssertRef | c:@S@StaticAssertRef | | Ref | rel: 0 + +void staticAssertInFn() { + static_assert(StaticAssertRef::constVar, "index static asserts"); +// CHECK: [[@LINE-1]]:34 | static-property/C++ | constVar | c:@S@StaticAssertRef@constVar | __ZN15StaticAssertRef8constVarE | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | staticAssertInFn | c:@F@staticAssertInFn# +// CHECK: [[@LINE-3]]:17 | struct/C++ | StaticAssertRef | c:@S@StaticAssertRef | | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | staticAssertInFn | c:@F@staticAssertInFn# +} + +namespace cpp17structuredBinding { + +struct Cpp17StructuredBinding { + int x, y; + + Cpp17StructuredBinding(int x, int y): x(x), y(y) { } +}; + +auto [structuredBinding1, structuredBinding2] = Cpp17StructuredBinding(Record::C, 0); +// CHECK: [[@LINE-1]]:7 | variable/C++ | structuredBinding1 | c:@N@cpp17structuredBinding@structuredBinding1 | | Decl,RelChild | rel: 1 +// CHECK-NEXT: RelChild | cpp17structuredBinding | c:@N@cpp17structuredBinding +// CHECK: [[@LINE-3]]:27 | variable/C++ | structuredBinding2 | c:@N@cpp17structuredBinding@structuredBinding2 | | Decl,RelChild | rel: 1 +// CHECK-NEXT: RelChild | cpp17structuredBinding | c:@N@cpp17structuredBinding + +void localStructuredBindingAndRef() { + int ref = structuredBinding1; +// CHECK: [[@LINE-1]]:13 | variable/C++ | structuredBinding1 | c:@N@cpp17structuredBinding@structuredBinding1 | | Ref,Read,RelCont | rel: 1 +// CHECK-NEXT: RelCont | localStructuredBindingAndRef | c:@N@cpp17structuredBinding@F@localStructuredBindingAndRef# + auto [localBinding1, localBinding2] = Cpp17StructuredBinding(ref, structuredBinding2); +// CHECK: [[@LINE-1]]:69 | variable/C++ | structuredBinding2 | c:@N@cpp17structuredBinding@structuredBinding2 | | Ref,Read,RelCont | rel: 1 +// CHECK-NEXT: RelCont | localStructuredBindingAndRef | c:@N@cpp17structuredBinding@F@localStructuredBindingAndRef# +// CHECK-NOT: localBinding +} + +} diff --git a/test/Index/availability.c b/test/Index/availability.c index b9d2c6f449c1..206b8a2a7105 100644 --- a/test/Index/availability.c +++ b/test/Index/availability.c @@ -8,13 +8,15 @@ enum { enum { old_enum_plat -} __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7) +} __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7))); -// RUN: c-index-test -test-load-source all %s > %t -// RUN: FileCheck -check-prefix=CHECK-1 %s < %t -// RUN: FileCheck -check-prefix=CHECK-2 %s < %t -// CHECK-1: (ios, introduced=3.2, deprecated=4.1) -// CHECK-2: (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7) +void bar(void) __attribute__((availability(macosx,introduced=10.4))) __attribute__((availability(macosx,obsoleted=10.6))) __attribute__((availability(ios,introduced=3.2))) __attribute__((availability(macosx,deprecated=10.5,message="use foobar"))); -// CHECK-2: EnumConstantDecl=old_enum:6:3 (Definition) (deprecated) -// CHECK-2: EnumConstantDecl=old_enum_plat:10:3 {{.*}} (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7) +void bar2(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7))) __attribute__((availability(ios,introduced=3.2,deprecated=10.0))) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7))) __attribute__((availability(ios,introduced=3.2,deprecated=10.0))); + +// RUN: c-index-test -test-load-source all %s | FileCheck %s +// CHECK: FunctionDecl=foo:3:6{{.*}}(ios, introduced=3.2, deprecated=4.1) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7) +// CHECK: EnumConstantDecl=old_enum:6:3 (Definition) (deprecated) +// CHECK: EnumConstantDecl=old_enum_plat:10:3 {{.*}} (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7) +// CHECK: FunctionDecl=bar:13:6{{.*}}(ios, introduced=3.2) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.6, message="use foobar") +// CHECK: FunctionDecl=bar2:15:6{{.*}}(ios, introduced=3.2, deprecated=10.0) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7) diff --git a/test/Misc/pr32207.c b/test/Misc/pr32207.c new file mode 100644 index 000000000000..f738e41684c6 --- /dev/null +++ b/test/Misc/pr32207.c @@ -0,0 +1,4 @@ +// test for r305179 +// RUN: %clang_cc1 -emit-llvm -O -mllvm -print-after-all %s -o %t 2>&1 | FileCheck %s +// CHECK: *** IR Dump After Function Integration/Inlining *** +void foo() {} diff --git a/test/Modules/autolink.m b/test/Modules/autolink.m index 28b9e40678f6..6aee0e11b120 100644 --- a/test/Modules/autolink.m +++ b/test/Modules/autolink.m @@ -36,9 +36,7 @@ int use_autolink_sub3() { // NOTE: "autolink_sub" is intentionally not linked. -// CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[AUTOLINK_OPTIONS:[0-9]+]]} -// CHECK: ![[AUTOLINK_OPTIONS]] = !{![[AUTOLINK_PCH:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]], ![[AUTOLINK:[0-9]+]], ![[DEPENDSONMODULE:[0-9]+]], ![[MODULE:[0-9]+]], ![[NOUMBRELLA:[0-9]+]]} +// CHECK: !llvm.linker.options = !{![[AUTOLINK_PCH:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]], ![[AUTOLINK:[0-9]+]], ![[DEPENDSONMODULE:[0-9]+]], ![[MODULE:[0-9]+]], ![[NOUMBRELLA:[0-9]+]]} // CHECK: ![[AUTOLINK_PCH]] = !{!"{{(\\01|-l|/DEFAULTLIB:)}}autolink_from_pch{{(\.lib)?}}"} // CHECK: ![[AUTOLINK_FRAMEWORK]] = !{!"-framework", !"autolink_framework"} // CHECK: ![[AUTOLINK]] = !{!"{{(\\01|-l|/DEFAULTLIB:)}}autolink{{(\.lib)?}}"} @@ -47,4 +45,4 @@ int use_autolink_sub3() { // CHECK: ![[NOUMBRELLA]] = !{!"-framework", !"NoUmbrella"} // CHECK-AUTOLINK-DISABLED: !llvm.module.flags -// CHECK-AUTOLINK-DISABLED-NOT: "Linker Options" +// CHECK-AUTOLINK-DISABLED-NOT: !llvm.linker.options diff --git a/test/Modules/autolinkTBD.m b/test/Modules/autolinkTBD.m index 6107952c3b9b..d6b9e997b2f8 100644 --- a/test/Modules/autolinkTBD.m +++ b/test/Modules/autolinkTBD.m @@ -8,10 +8,8 @@ int f() { return foo(); } -// CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[AUTOLINK_OPTIONS:[0-9]+]]} -// CHECK: ![[AUTOLINK_OPTIONS]] = !{![[AUTOLINK_FRAMEWORK:[0-9]+]]} +// CHECK: !llvm.linker.options = !{![[AUTOLINK_FRAMEWORK:[0-9]+]]} // CHECK: ![[AUTOLINK_FRAMEWORK]] = !{!"-framework", !"AutolinkTBD"} // CHECK-AUTOLINK-DISABLED: !llvm.module.flags -// CHECK-AUTOLINK-DISABLED-NOT: "Linker Options" +// CHECK-AUTOLINK-DISABLED-NOT: !llvm.linker.options diff --git a/test/Modules/module-impl-with-link.c b/test/Modules/module-impl-with-link.c index 3bd4c4abd92b..ffd388c56b90 100644 --- a/test/Modules/module-impl-with-link.c +++ b/test/Modules/module-impl-with-link.c @@ -1,7 +1,6 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fmodule-name=Clib %s -I %S/Inputs/module-impl-with-link -emit-llvm -o - | FileCheck %s #include "foo.h" -// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[LINK_OPTIONS:[0-9]+]]} // Make sure we don't generate linker option for module Clib since this TU is // an implementation of Clib. -// CHECK: ![[LINK_OPTIONS]] = !{} +// CHECK: !llvm.linker.options = !{} diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index a6a0b74743aa..c94940c73eb6 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -486,7 +486,8 @@ struct S12 { }; #else S12 s12; -// TODO: This should produce an error. +// expected-error@second.h:* {{'Method::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter without a default argument}} +// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter with a default argument}} #endif #if defined(FIRST) @@ -499,7 +500,8 @@ struct S13 { }; #else S13 s13; -// TODO: This should produce an error. +// expected-error@second.h:* {{'Method::S13' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter with a default argument}} +// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter with a different default argument}} #endif #if defined(FIRST) @@ -586,6 +588,57 @@ S3 s3; // expected-error@first.h:* {{'TypeDef::S3::a' from module 'FirstModule' is not present in definition of 'TypeDef::S3' in module 'SecondModule'}} // expected-note@second.h:* {{declaration of 'a' does not match}} #endif + +#if defined(FIRST) +struct S4 { + typedef int a; + typedef int b; +}; +#elif defined(SECOND) +struct S4 { + typedef int b; + typedef int a; +}; +#else +S4 s4; +// expected-error@second.h:* {{'TypeDef::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found typedef name 'b'}} +// expected-note@first.h:* {{but in 'FirstModule' found typedef name 'a'}} +#endif + +#if defined(FIRST) +struct S5 { + typedef int a; + typedef int b; + int x; +}; +#elif defined(SECOND) +struct S5 { + int x; + typedef int b; + typedef int a; +}; +#else +S5 s5; +// expected-error@second.h:* {{'TypeDef::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}} +// expected-note@first.h:* {{but in 'FirstModule' found typedef}} +#endif + +#if defined(FIRST) +typedef float F; +struct S6 { + typedef int a; + typedef F b; +}; +#elif defined(SECOND) +struct S6 { + typedef int a; + typedef float b; +}; +#else +S6 s6; +// expected-error@second.h:* {{'TypeDef::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found typedef 'b' with underlying type 'float'}} +// expected-note@first.h:* {{but in 'FirstModule' found typedef 'b' with different underlying type 'TypeDef::F' (aka 'float')}} +#endif } // namespace TypeDef namespace Using { @@ -632,6 +685,57 @@ S3 s3; // expected-error@first.h:* {{'Using::S3::a' from module 'FirstModule' is not present in definition of 'Using::S3' in module 'SecondModule'}} // expected-note@second.h:* {{declaration of 'a' does not match}} #endif + +#if defined(FIRST) +struct S4 { + using a = int; + using b = int; +}; +#elif defined(SECOND) +struct S4 { + using b = int; + using a = int; +}; +#else +S4 s4; +// expected-error@second.h:* {{'Using::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias name 'b'}} +// expected-note@first.h:* {{but in 'FirstModule' found type alias name 'a'}} +#endif + +#if defined(FIRST) +struct S5 { + using a = int; + using b = int; + int x; +}; +#elif defined(SECOND) +struct S5 { + int x; + using b = int; + using a = int; +}; +#else +S5 s5; +// expected-error@second.h:* {{'Using::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}} +// expected-note@first.h:* {{but in 'FirstModule' found type alias}} +#endif + +#if defined(FIRST) +typedef float F; +struct S6 { + using a = int; + using b = F; +}; +#elif defined(SECOND) +struct S6 { + using a = int; + using b = float; +}; +#else +S6 s6; +// expected-error@second.h:* {{'Using::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'b' with underlying type 'float'}} +// expected-note@first.h:* {{but in 'FirstModule' found type alias 'b' with different underlying type 'Using::F' (aka 'float')}} +#endif } // namespace Using namespace RecordType { @@ -900,6 +1004,289 @@ S2 s2; #endif } +namespace TemplateArgument { +#if defined(FIRST) +template struct U1{}; +struct S1 { + U1 x; +}; +#elif defined(SECOND) +template struct U1{}; +struct S1 { + U1<1> x; +}; +#else +S1 s1; +// expected-error@first.h:* {{'TemplateArgument::S1::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S1' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +#endif + +#if defined(FIRST) +template struct U2{}; +struct S2 { + using T = U2<2>; +}; +#elif defined(SECOND) +template struct U2{}; +struct S2 { + using T = U2<(2)>; +}; +#else +S2 s2; +// expected-error@second.h:* {{'TemplateArgument::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'T' with underlying type 'U2<(2)>'}} +// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'U2<2>'}} +#endif + +#if defined(FIRST) +template struct U3{}; +struct S3 { + using T = U3<2>; +}; +#elif defined(SECOND) +template struct U3{}; +struct S3 { + using T = U3<1 + 1>; +}; +#else +S3 s3; +// expected-error@second.h:* {{'TemplateArgument::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'T' with underlying type 'U3<1 + 1>'}} +// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'U3<2>'}} +#endif + +#if defined(FIRST) +template struct T4a {}; +template