Propagating prior merge from 'llvm.org/release_50'.
diff --git a/README.txt b/README.txt
index fc88432..2d64f00 100644
--- a/README.txt
+++ b/README.txt
@@ -8,4 +8,3 @@
terms of the license agreement found in LICENSE.txt.
================================
-
diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c
index d038bb9..553baad 100644
--- a/lib/profile/InstrProfilingFile.c
+++ b/lib/profile/InstrProfilingFile.c
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <signal.h>
#ifdef _MSC_VER
/* For _alloca. */
#include <malloc.h>
@@ -59,6 +60,7 @@
}
#define MAX_PID_SIZE 16
+#define MAX_SIGNAL_HANDLERS 16
/* Data structure holding the result of parsed filename pattern. */
typedef struct lprofFilename {
/* File name string possibly with %p or %h specifiers. */
@@ -79,11 +81,13 @@
* 2 profile data files. %1m is equivalent to %m. Also %m specifier
* can only appear once at the end of the name pattern. */
unsigned MergePoolSize;
+ char ExitOnSignals[MAX_SIGNAL_HANDLERS];
+ unsigned NumExitSignals;
ProfileNameSpecifier PNS;
} lprofFilename;
-COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0},
- 0, 0, 0, PNS_unknown};
+COMPILER_RT_WEAK lprofFilename lprofCurFilename = {
+ 0, 0, 0, {0}, {0}, 0, 0, 0, {0}, 0, PNS_unknown};
int getpid(void);
static int getCurFilenameLength();
@@ -278,6 +282,19 @@
fclose(File);
}
+static void exitSignalHandler(int sig) {
+ (void)sig;
+ exit(0);
+}
+
+static void installExitSignalHandlers(void) {
+ unsigned I;
+ for (I = 0; I < lprofCurFilename.NumExitSignals; ++I) {
+ lprofInstallSignalHandler(lprofCurFilename.ExitOnSignals[I],
+ exitSignalHandler);
+ }
+}
+
static const char *DefaultProfileName = "default.profraw";
static void resetFilenameToDefault(void) {
if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
@@ -288,14 +305,25 @@
lprofCurFilename.PNS = PNS_default;
}
+static int isDigit(char C) { return C >= '0' && C <= '9'; }
+
+static int isNonZeroDigit(char C) { return C >= '1' && C <= '9'; }
+
static int containsMergeSpecifier(const char *FilenamePat, int I) {
return (FilenamePat[I] == 'm' ||
- (FilenamePat[I] >= '1' && FilenamePat[I] <= '9' &&
+ (isNonZeroDigit(FilenamePat[I]) &&
/* If FilenamePat[I] is not '\0', the next byte is guaranteed
* to be in-bound as the string is null terminated. */
FilenamePat[I + 1] == 'm'));
}
+static int containsExitOnSignalSpecifier(const char *FilenamePat, int I) {
+ if (!isNonZeroDigit(FilenamePat[I]))
+ return 0;
+ return (FilenamePat[I + 1] == 'x') ||
+ (isDigit(FilenamePat[I + 1]) && FilenamePat[I + 2] == 'x');
+}
+
/* Parses the pattern string \p FilenamePat and stores the result to
* lprofcurFilename structure. */
static int parseFilenamePattern(const char *FilenamePat,
@@ -304,6 +332,7 @@
char *PidChars = &lprofCurFilename.PidChars[0];
char *Hostname = &lprofCurFilename.Hostname[0];
int MergingEnabled = 0;
+ char SignalNo;
/* Clean up cached prefix. */
if (lprofCurFilename.ProfilePathPrefix)
@@ -353,6 +382,22 @@
lprofCurFilename.MergePoolSize = FilenamePat[I] - '0';
I++; /* advance to 'm' */
}
+ } else if (containsExitOnSignalSpecifier(FilenamePat, I)) {
+ if (lprofCurFilename.NumExitSignals == MAX_SIGNAL_HANDLERS) {
+ PROF_WARN("%%x specifier has been specified too many times in %s.\n",
+ FilenamePat);
+ return -1;
+ }
+ /* Grab the signal number. */
+ SignalNo = FilenamePat[I] - '0';
+ I++; /* advance to either another digit, or 'x' */
+ if (FilenamePat[I] != 'x') {
+ SignalNo = (SignalNo * 10) + (FilenamePat[I] - '0');
+ I++; /* advance to 'x' */
+ }
+ lprofCurFilename.ExitOnSignals[lprofCurFilename.NumExitSignals] =
+ SignalNo;
+ ++lprofCurFilename.NumExitSignals;
}
}
@@ -396,6 +441,7 @@
}
truncateCurrentFile();
+ installExitSignalHandlers();
}
/* Return buffer length that is required to store the current profile
@@ -404,11 +450,12 @@
#define SIGLEN 24
static int getCurFilenameLength() {
int Len;
+ unsigned I;
if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
return 0;
if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
- lprofCurFilename.MergePoolSize))
+ lprofCurFilename.MergePoolSize || lprofCurFilename.NumExitSignals))
return strlen(lprofCurFilename.FilenamePat);
Len = strlen(lprofCurFilename.FilenamePat) +
@@ -416,6 +463,11 @@
lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
if (lprofCurFilename.MergePoolSize)
Len += SIGLEN;
+ for (I = 0; I < lprofCurFilename.NumExitSignals; ++I) {
+ Len -= 3; /* Drop the '%', signal number, and the 'x'. */
+ if (lprofCurFilename.ExitOnSignals[I] >= 10)
+ --Len; /* Drop the second digit of the signal number. */
+ }
return Len;
}
@@ -431,7 +483,7 @@
return 0;
if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
- lprofCurFilename.MergePoolSize))
+ lprofCurFilename.MergePoolSize || lprofCurFilename.NumExitSignals))
return lprofCurFilename.FilenamePat;
PidLength = strlen(lprofCurFilename.PidChars);
@@ -457,6 +509,9 @@
J += S;
if (FilenamePat[I] != 'm')
I++;
+ } else if (containsExitOnSignalSpecifier(FilenamePat, I)) {
+ while (FilenamePat[I] != 'x')
+ ++I;
}
/* Drop any unknown substitutions. */
} else
diff --git a/lib/profile/InstrProfilingUtil.c b/lib/profile/InstrProfilingUtil.c
index fb68f30..b8c1269 100644
--- a/lib/profile/InstrProfilingUtil.c
+++ b/lib/profile/InstrProfilingUtil.c
@@ -26,6 +26,7 @@
#include <sys/utsname.h>
#endif
+#include <signal.h>
#include <stdlib.h>
#include <string.h>
@@ -225,6 +226,24 @@
return Sep;
}
+COMPILER_RT_VISIBILITY void lprofInstallSignalHandler(int sig,
+ void (*handler)(int)) {
+#ifdef _WIN32
+ void (*err)(int) = signal(sig, handler);
+ if (err == SIG_ERR)
+ PROF_WARN("Unable to install an exit signal handler for %d (errno = %d).\n",
+ sig, errno);
+#else
+ struct sigaction sigact;
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = handler;
+ int err = sigaction(sig, &sigact, NULL);
+ if (err)
+ PROF_WARN("Unable to install an exit signal handler for %d (errno = %d).\n",
+ sig, err);
+#endif
+}
+
COMPILER_RT_VISIBILITY int lprofSuspendSigKill() {
#if defined(__linux__)
int PDeachSig = 0;
diff --git a/lib/profile/InstrProfilingUtil.h b/lib/profile/InstrProfilingUtil.h
index 9698599..61e3020 100644
--- a/lib/profile/InstrProfilingUtil.h
+++ b/lib/profile/InstrProfilingUtil.h
@@ -51,6 +51,8 @@
unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV);
void *lprofPtrFetchAdd(void **Mem, long ByteIncr);
+void lprofInstallSignalHandler(int sig, void(*handler)(int));
+
/* Temporarily suspend SIGKILL. Return value of 1 means a restore is needed.
* Other return values mean no restore is needed.
*/
diff --git a/lib/ubsan/ubsan_checks.inc b/lib/ubsan/ubsan_checks.inc
index 0a87e6e..73c6936 100644
--- a/lib/ubsan/ubsan_checks.inc
+++ b/lib/ubsan/ubsan_checks.inc
@@ -29,6 +29,7 @@
UBSAN_CHECK(IntegerDivideByZero, "integer-divide-by-zero",
"integer-divide-by-zero")
UBSAN_CHECK(FloatDivideByZero, "float-divide-by-zero", "float-divide-by-zero")
+UBSAN_CHECK(InvalidBuiltin, "invalid-builtin-use", "invalid-builtin-use")
UBSAN_CHECK(InvalidShiftBase, "invalid-shift-base", "shift-base")
UBSAN_CHECK(InvalidShiftExponent, "invalid-shift-exponent", "shift-exponent")
UBSAN_CHECK(OutOfBoundsIndex, "out-of-bounds-index", "bounds")
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc
index 75a4490..06438a5 100644
--- a/lib/ubsan/ubsan_handlers.cc
+++ b/lib/ubsan/ubsan_handlers.cc
@@ -437,6 +437,30 @@
Die();
}
+static void handleInvalidBuiltin(InvalidBuiltinData *Data, ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::InvalidBuiltin;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error,
+ "passing zero to %0, which is not a valid argument")
+ << ((Data->Kind == BCK_CTZPassedZero) ? "ctz()" : "clz()");
+}
+
+void __ubsan::__ubsan_handle_invalid_builtin(InvalidBuiltinData *Data) {
+ GET_REPORT_OPTIONS(true);
+ handleInvalidBuiltin(Data, Opts);
+}
+void __ubsan::__ubsan_handle_invalid_builtin_abort(InvalidBuiltinData *Data) {
+ GET_REPORT_OPTIONS(true);
+ handleInvalidBuiltin(Data, Opts);
+ Die();
+}
+
static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
ValueHandle Function,
ReportOptions Opts) {
diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h
index 796321b..5a9e902 100644
--- a/lib/ubsan/ubsan_handlers.h
+++ b/lib/ubsan/ubsan_handlers.h
@@ -122,6 +122,21 @@
/// \brief Handle a load of an invalid value for the type.
RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val)
+/// Known builtin check kinds.
+/// Keep in sync with the enum of the same name in CodeGenFunction.h
+enum BuiltinCheckKind : unsigned char {
+ BCK_CTZPassedZero,
+ BCK_CLZPassedZero,
+};
+
+struct InvalidBuiltinData {
+ SourceLocation Loc;
+ unsigned char Kind;
+};
+
+/// Handle a builtin called in an invalid way.
+RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data)
+
struct FunctionTypeMismatchData {
SourceLocation Loc;
const TypeDescriptor &Type;
diff --git a/lib/ubsan/ubsan_interface.inc b/lib/ubsan/ubsan_interface.inc
index a69ca57..4c8f92e 100644
--- a/lib/ubsan/ubsan_interface.inc
+++ b/lib/ubsan/ubsan_interface.inc
@@ -19,6 +19,8 @@
INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow_abort)
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch)
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_abort)
+INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin)
+INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin_abort)
INTERFACE_FUNCTION(__ubsan_handle_load_invalid_value)
INTERFACE_FUNCTION(__ubsan_handle_load_invalid_value_abort)
INTERFACE_FUNCTION(__ubsan_handle_missing_return)
diff --git a/test/lit.common.cfg b/test/lit.common.cfg
index 6080edc..5f89000 100644
--- a/test/lit.common.cfg
+++ b/test/lit.common.cfg
@@ -87,6 +87,9 @@
if re.match(r'^x86_64.*-linux', config.target_triple):
config.available_features.add("x86_64-linux")
+if lit.util.isMacOSTriple(config.target_triple):
+ config.available_features.add('darwin')
+
# Use ugly construction to explicitly prohibit "clang", "clang++" etc.
# in RUN lines.
config.substitutions.append(
diff --git a/test/profile/instrprof-exit-on-signal.c b/test/profile/instrprof-exit-on-signal.c
new file mode 100644
index 0000000..efe1013
--- /dev/null
+++ b/test/profile/instrprof-exit-on-signal.c
@@ -0,0 +1,26 @@
+// RUN: %clang_profgen -o %t %s
+//
+// Verify SIGTERM handling.
+// RUN: %run LLVM_PROFILE_FILE="%15x%t.profraw" %t 15
+// RUN: llvm-profdata show %t.profraw | FileCheck %s
+//
+// Verify SIGUSR1 handling.
+// RUN: %run LLVM_PROFILE_FILE="%30x%t.profraw" %t 30
+// RUN: llvm-profdata show %t.profraw | FileCheck %s
+
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+// CHECK: Total functions: 1
+int main(int argc, char **argv) {
+ (void)argc;
+
+ int sig = atoi(argv[1]);
+ kill(getpid(), sig);
+
+ while (1) {
+ /* loop forever */
+ }
+ return 1;
+}
diff --git a/test/ubsan/TestCases/Misc/builtins.cpp b/test/ubsan/TestCases/Misc/builtins.cpp
new file mode 100644
index 0000000..18c68b5
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/builtins.cpp
@@ -0,0 +1,35 @@
+// REQUIRES: arch=x86_64
+//
+// RUN: %clangxx -fsanitize=builtin -w %s -O3 -o %t
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER
+// RUN: %clangxx -fsanitize=builtin -fno-sanitize-recover=builtin -w %s -O3 -o %t.abort
+// RUN: not %run %t.abort 2>&1 | FileCheck %s --check-prefix=ABORT
+
+void check_ctz(int n) {
+ // ABORT: builtins.cpp:[[@LINE+2]]:17: runtime error: passing zero to ctz(), which is not a valid argument
+ // RECOVER: builtins.cpp:[[@LINE+1]]:17: runtime error: passing zero to ctz(), which is not a valid argument
+ __builtin_ctz(n);
+
+ // RECOVER: builtins.cpp:[[@LINE+1]]:18: runtime error: passing zero to ctz(), which is not a valid argument
+ __builtin_ctzl(n);
+
+ // RECOVER: builtins.cpp:[[@LINE+1]]:19: runtime error: passing zero to ctz(), which is not a valid argument
+ __builtin_ctzll(n);
+}
+
+void check_clz(int n) {
+ // RECOVER: builtins.cpp:[[@LINE+1]]:17: runtime error: passing zero to clz(), which is not a valid argument
+ __builtin_clz(n);
+
+ // RECOVER: builtins.cpp:[[@LINE+1]]:18: runtime error: passing zero to clz(), which is not a valid argument
+ __builtin_clzl(n);
+
+ // RECOVER: builtins.cpp:[[@LINE+1]]:19: runtime error: passing zero to clz(), which is not a valid argument
+ __builtin_clzll(n);
+}
+
+int main() {
+ check_ctz(0);
+ check_clz(0);
+ return 0;
+}
diff --git a/test/ubsan/TestCases/TypeCheck/PR33221.cpp b/test/ubsan/TestCases/TypeCheck/PR33221.cpp
index c691e5f..71da06c 100644
--- a/test/ubsan/TestCases/TypeCheck/PR33221.cpp
+++ b/test/ubsan/TestCases/TypeCheck/PR33221.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=null,vptr -g %s -O3 -o %t
// RUN: %run %t 2>&1 | FileCheck %s
// REQUIRES: cxxabi
diff --git a/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp b/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
index 37ffe5b..898577d 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=vptr,null -fno-sanitize-recover=vptr,null -g %s -O3 -o %t
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-CORRUPTED-VTABLE --strict-whitespace
// UNSUPPORTED: win32
diff --git a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
index 09deac1..f1fb111 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=null,vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// REQUIRES: cxxabi
diff --git a/test/ubsan/TestCases/TypeCheck/vptr.cpp b/test/ubsan/TestCases/TypeCheck/vptr.cpp
index 53a79c9..183c7b7 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t -mllvm -enable-tail-merge=false
+// RUN: %clangxx -frtti -fsanitize=null,vptr -fno-sanitize-recover=null,vptr -g %s -O3 -o %t -mllvm -enable-tail-merge=false
// RUN: %run %t rT && %run %t mT && %run %t fT && %run %t cT
// RUN: %run %t rU && %run %t mU && %run %t fU && %run %t cU
// RUN: %run %t rS && %run %t rV && %run %t oV
@@ -9,7 +9,9 @@
// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t cV 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --check-prefix=CHECK-%os-DOWNCAST --strict-whitespace
// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --check-prefix=CHECK-%os-OFFSET --strict-whitespace
-// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --check-prefix=CHECK-%os-NULL-MEMBER --strict-whitespace
+// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID-MEMBER --check-prefix=CHECK-%os-NULL-MEMBER --strict-whitespace
+// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID-MEMBER --check-prefix=CHECK-%os-NULL-MEMBER --strict-whitespace
+// RUN: not %run %t nN 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMFUN --strict-whitespace
// RUN: (echo "vptr_check:S"; echo "vptr_check:T"; echo "vptr_check:U") > %t.supp
// RUN: %env_ubsan_opts=suppressions='"%t.supp"' %run %t mS
@@ -99,6 +101,9 @@
case 'V':
p = reinterpret_cast<T*>(new U);
break;
+ case 'N':
+ p = 0;
+ break;
}
access_p(p, argv[1][0]);
@@ -134,11 +139,11 @@
// CHECK-Linux-MEMBER: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
return p->b;
- // CHECK-NULL-MEMBER: vptr.cpp:[[@LINE-2]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
- // CHECK-NULL-MEMBER-NEXT: [[PTR]]: note: object has invalid vptr
- // CHECK-NULL-MEMBER-NEXT: {{^ ?.. .. .. .. ?00 00 00 00 ?00 00 00 00 ?}}
- // CHECK-NULL-MEMBER-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
- // CHECK-NULL-MEMBER-NEXT: {{^ invalid vptr}}
+ // CHECK-INVALID-MEMBER: vptr.cpp:[[@LINE-2]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
+ // CHECK-INVALID-MEMBER-NEXT: [[PTR]]: note: object has invalid vptr
+ // CHECK-INVALID-MEMBER-NEXT: {{^ ?.. .. .. .. ?00 00 00 00 ?00 00 00 00 ?}}
+ // CHECK-INVALID-MEMBER-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
+ // CHECK-INVALID-MEMBER-NEXT: {{^ invalid vptr}}
// CHECK-Linux-NULL-MEMBER: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE-7]]
case 'f':
@@ -168,6 +173,10 @@
// CHECK-Linux-DOWNCAST: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
(void)static_cast<T*>(reinterpret_cast<S*>(p));
return 0;
+
+ case 'n':
+ // CHECK-NULL-MEMFUN: vptr.cpp:[[@LINE+1]]:15: runtime error: member call on null pointer of type 'T'
+ return p->g();
}
return 0;
}
diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg
index e3a1367..b55fb5f 100644
--- a/test/ubsan/lit.common.cfg
+++ b/test/ubsan/lit.common.cfg
@@ -77,3 +77,5 @@
# because the test hangs or fails on one configuration and not the other.
if config.target_arch.startswith('arm') == False and config.target_arch != 'aarch64':
config.available_features.add('stable-runtime')
+
+config.available_features.add('arch=' + config.target_arch)